Linux Kernel Markers: fix marker mutex not taken upon module load
[linux-2.6] / drivers / media / dvb / b2c2 / flexcop-fe-tuner.c
1 /*
2  * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
3  *
4  * flexcop-fe-tuner.c - methods for attaching a frontend and controlling DiSEqC.
5  *
6  * see flexcop.c for copyright information.
7  */
8 #include "flexcop.h"
9
10 #include "stv0299.h"
11 #include "mt352.h"
12 #include "nxt200x.h"
13 #include "bcm3510.h"
14 #include "stv0297.h"
15 #include "mt312.h"
16 #include "lgdt330x.h"
17 #include "dvb-pll.h"
18
19 /* lnb control */
20
21 static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
22 {
23         struct flexcop_device *fc = fe->dvb->priv;
24         flexcop_ibi_value v;
25         deb_tuner("polarity/voltage = %u\n", voltage);
26
27         v = fc->read_ibi_reg(fc, misc_204);
28         switch (voltage) {
29                 case SEC_VOLTAGE_OFF:
30                         v.misc_204.ACPI1_sig = 1;
31                         break;
32                 case SEC_VOLTAGE_13:
33                         v.misc_204.ACPI1_sig = 0;
34                         v.misc_204.LNB_L_H_sig = 0;
35                         break;
36                 case SEC_VOLTAGE_18:
37                         v.misc_204.ACPI1_sig = 0;
38                         v.misc_204.LNB_L_H_sig = 1;
39                         break;
40                 default:
41                         err("unknown SEC_VOLTAGE value");
42                         return -EINVAL;
43         }
44         return fc->write_ibi_reg(fc, misc_204, v);
45 }
46
47 static int flexcop_sleep(struct dvb_frontend* fe)
48 {
49         struct flexcop_device *fc = fe->dvb->priv;
50 /*      flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */
51
52         if (fc->fe_sleep)
53                 return fc->fe_sleep(fe);
54
55 /*      v.misc_204.ACPI3_sig = 1;
56         fc->write_ibi_reg(fc,misc_204,v);*/
57
58         return 0;
59 }
60
61 static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
62 {
63         /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
64         struct flexcop_device *fc = fe->dvb->priv;
65         flexcop_ibi_value v;
66         u16 ax;
67         v.raw = 0;
68
69         deb_tuner("tone = %u\n",tone);
70
71         switch (tone) {
72                 case SEC_TONE_ON:
73                         ax = 0x01ff;
74                         break;
75                 case SEC_TONE_OFF:
76                         ax = 0;
77                         break;
78                 default:
79                         err("unknown SEC_TONE value");
80                         return -EINVAL;
81         }
82
83         v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
84
85         v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
86         v.lnb_switch_freq_200.LNB_CTLLowCount_sig  = ax == 0 ? 0x1ff : ax;
87
88         return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
89 }
90
91 static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
92 {
93         flexcop_set_tone(fe, SEC_TONE_ON);
94         udelay(data ? 500 : 1000);
95         flexcop_set_tone(fe, SEC_TONE_OFF);
96         udelay(data ? 1000 : 500);
97 }
98
99 static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
100 {
101         int i, par = 1, d;
102
103         for (i = 7; i >= 0; i--) {
104                 d = (data >> i) & 1;
105                 par ^= d;
106                 flexcop_diseqc_send_bit(fe, d);
107         }
108
109         flexcop_diseqc_send_bit(fe, par);
110 }
111
112 static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst)
113 {
114         int i;
115
116         flexcop_set_tone(fe, SEC_TONE_OFF);
117         mdelay(16);
118
119         for (i = 0; i < len; i++)
120                 flexcop_diseqc_send_byte(fe,msg[i]);
121
122         mdelay(16);
123
124         if (burst != -1) {
125                 if (burst)
126                         flexcop_diseqc_send_byte(fe, 0xff);
127                 else {
128                         flexcop_set_tone(fe, SEC_TONE_ON);
129                         udelay(12500);
130                         flexcop_set_tone(fe, SEC_TONE_OFF);
131                 }
132                 msleep(20);
133         }
134         return 0;
135 }
136
137 static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
138 {
139         return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
140 }
141
142 static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
143 {
144         return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
145 }
146
147 /* dvb-s stv0299 */
148 static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
149 {
150         u8 aclk = 0;
151         u8 bclk = 0;
152
153         if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
154         else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
155         else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
156         else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
157         else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
158         else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
159
160         stv0299_writereg (fe, 0x13, aclk);
161         stv0299_writereg (fe, 0x14, bclk);
162         stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
163         stv0299_writereg (fe, 0x20, (ratio >>  8) & 0xff);
164         stv0299_writereg (fe, 0x21, (ratio      ) & 0xf0);
165
166         return 0;
167 }
168
169 static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
170 {
171         u8 buf[4];
172         u32 div;
173         struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
174         struct flexcop_device *fc = fe->dvb->priv;
175
176         div = params->frequency / 125;
177
178         buf[0] = (div >> 8) & 0x7f;
179         buf[1] = div & 0xff;
180         buf[2] = 0x84;  /* 0xC4 */
181         buf[3] = 0x08;
182
183         if (params->frequency < 1500000) buf[3] |= 0x10;
184
185         if (fe->ops.i2c_gate_ctrl)
186                 fe->ops.i2c_gate_ctrl(fe, 1);
187         if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
188                 return -EIO;
189         }
190         return 0;
191 }
192
193 static u8 samsung_tbmu24112_inittab[] = {
194              0x01, 0x15,
195              0x02, 0x30,
196              0x03, 0x00,
197              0x04, 0x7D,
198              0x05, 0x35,
199              0x06, 0x02,
200              0x07, 0x00,
201              0x08, 0xC3,
202              0x0C, 0x00,
203              0x0D, 0x81,
204              0x0E, 0x23,
205              0x0F, 0x12,
206              0x10, 0x7E,
207              0x11, 0x84,
208              0x12, 0xB9,
209              0x13, 0x88,
210              0x14, 0x89,
211              0x15, 0xC9,
212              0x16, 0x00,
213              0x17, 0x5C,
214              0x18, 0x00,
215              0x19, 0x00,
216              0x1A, 0x00,
217              0x1C, 0x00,
218              0x1D, 0x00,
219              0x1E, 0x00,
220              0x1F, 0x3A,
221              0x20, 0x2E,
222              0x21, 0x80,
223              0x22, 0xFF,
224              0x23, 0xC1,
225              0x28, 0x00,
226              0x29, 0x1E,
227              0x2A, 0x14,
228              0x2B, 0x0F,
229              0x2C, 0x09,
230              0x2D, 0x05,
231              0x31, 0x1F,
232              0x32, 0x19,
233              0x33, 0xFE,
234              0x34, 0x93,
235              0xff, 0xff,
236 };
237
238 static struct stv0299_config samsung_tbmu24112_config = {
239         .demod_address = 0x68,
240         .inittab = samsung_tbmu24112_inittab,
241         .mclk = 88000000UL,
242         .invert = 0,
243         .skip_reinit = 0,
244         .lock_output = STV0229_LOCKOUTPUT_LK,
245         .volt13_op0_op1 = STV0299_VOLT13_OP1,
246         .min_delay_ms = 100,
247         .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
248 };
249
250 /* dvb-t mt352 */
251 static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
252 {
253         static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d };
254         static u8 mt352_reset [] = { 0x50, 0x80 };
255         static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
256         static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 };
257         static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
258
259         mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
260         udelay(2000);
261         mt352_write(fe, mt352_reset, sizeof(mt352_reset));
262         mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
263
264         mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
265         mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
266
267         return 0;
268 }
269
270 static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
271 {
272         u32 div;
273         unsigned char bs = 0;
274
275         if (buf_len < 5)
276                 return -EINVAL;
277
278         #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
279         div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
280
281         if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09;
282         if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
283         if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
284
285         pllbuf[0] = 0x61;
286         pllbuf[1] = div >> 8;
287         pllbuf[2] = div & 0xff;
288         pllbuf[3] = 0xcc;
289         pllbuf[4] = bs;
290
291         return 5;
292 }
293
294 static struct mt352_config samsung_tdtc9251dh0_config = {
295         .demod_address = 0x0f,
296         .demod_init    = samsung_tdtc9251dh0_demod_init,
297 };
298
299 static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
300 {
301         struct flexcop_device *fc = fe->dvb->priv;
302         return request_firmware(fw, name, fc->dev);
303 }
304
305 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
306         .demod_address       = 0x59,
307         .demod_chip          = LGDT3303,
308         .serial_mpeg         = 0x04,
309         .clock_polarity_flip = 1,
310 };
311
312 static struct nxt200x_config samsung_tbmv_config = {
313         .demod_address    = 0x0a,
314 };
315
316 static struct bcm3510_config air2pc_atsc_first_gen_config = {
317         .demod_address    = 0x0f,
318         .request_firmware = flexcop_fe_request_firmware,
319 };
320
321 static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
322 {
323         u8 buf[4];
324         u32 div;
325         struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
326         struct flexcop_device *fc = fe->dvb->priv;
327
328         div = (params->frequency + (125/2)) / 125;
329
330         buf[0] = (div >> 8) & 0x7f;
331         buf[1] = (div >> 0) & 0xff;
332         buf[2] = 0x84 | ((div >> 10) & 0x60);
333         buf[3] = 0x80;
334
335         if (params->frequency < 1550000)
336                 buf[3] |= 0x02;
337
338         if (fe->ops.i2c_gate_ctrl)
339                 fe->ops.i2c_gate_ctrl(fe, 1);
340         if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
341                 return -EIO;
342         return 0;
343 }
344
345 static struct mt312_config skystar23_samsung_tbdu18132_config = {
346
347         .demod_address = 0x0e,
348 };
349
350 static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
351                                                struct dvb_frontend_parameters *fep)
352 {
353         struct flexcop_device *fc = fe->dvb->priv;
354         u8 buf[4];
355         u16 div;
356         int ret;
357
358 /*  62.5 kHz * 10 */
359 #define REF_FREQ    625
360 #define FREQ_OFFSET 36125
361
362         div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10)  / REF_FREQ; // 4 MHz = 4000 KHz
363
364         buf[0] = (u8)( div >> 8) & 0x7f;
365         buf[1] = (u8)        div & 0xff;
366
367 /* F(osc) = N * Reference Freq. (62.5 kHz)
368  * byte 2 :  0 N14 N13 N12 N11 N10 N9  N8
369  * byte 3 : N7 N6  N5  N4  N3  N2  N1  N0
370  * byte 4 : 1  *   *   AGD R3  R2  R1  R0
371  * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
372  * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
373         buf[2] = 0x95;
374
375 // Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
376 //  47 - 153   0  *  0   0   0   0   0   1   0x01
377 // 153 - 430   0  *  0   0   0   0   1   0   0x02
378 // 430 - 822   0  *  0   0   1   0   0   0   0x08
379 // 822 - 862   1  *  0   0   1   0   0   0   0x88
380
381              if (fep->frequency <= 153000000) buf[3] = 0x01;
382         else if (fep->frequency <= 430000000) buf[3] = 0x02;
383         else if (fep->frequency <= 822000000) buf[3] = 0x08;
384         else buf[3] = 0x88;
385
386         if (fe->ops.i2c_gate_ctrl)
387                 fe->ops.i2c_gate_ctrl(fe, 0);
388         deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
389         ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
390         deb_tuner("tuner write returned: %d\n",ret);
391
392         return 0;
393 }
394
395 static u8 alps_tdee4_stv0297_inittab[] = {
396         0x80, 0x01,
397         0x80, 0x00,
398         0x81, 0x01,
399         0x81, 0x00,
400         0x00, 0x48,
401         0x01, 0x58,
402         0x03, 0x00,
403         0x04, 0x00,
404         0x07, 0x00,
405         0x08, 0x00,
406         0x30, 0xff,
407         0x31, 0x9d,
408         0x32, 0xff,
409         0x33, 0x00,
410         0x34, 0x29,
411         0x35, 0x55,
412         0x36, 0x80,
413         0x37, 0x6e,
414         0x38, 0x9c,
415         0x40, 0x1a,
416         0x41, 0xfe,
417         0x42, 0x33,
418         0x43, 0x00,
419         0x44, 0xff,
420         0x45, 0x00,
421         0x46, 0x00,
422         0x49, 0x04,
423         0x4a, 0x51,
424         0x4b, 0xf8,
425         0x52, 0x30,
426         0x53, 0x06,
427         0x59, 0x06,
428         0x5a, 0x5e,
429         0x5b, 0x04,
430         0x61, 0x49,
431         0x62, 0x0a,
432         0x70, 0xff,
433         0x71, 0x04,
434         0x72, 0x00,
435         0x73, 0x00,
436         0x74, 0x0c,
437         0x80, 0x20,
438         0x81, 0x00,
439         0x82, 0x30,
440         0x83, 0x00,
441         0x84, 0x04,
442         0x85, 0x22,
443         0x86, 0x08,
444         0x87, 0x1b,
445         0x88, 0x00,
446         0x89, 0x00,
447         0x90, 0x00,
448         0x91, 0x04,
449         0xa0, 0x86,
450         0xa1, 0x00,
451         0xa2, 0x00,
452         0xb0, 0x91,
453         0xb1, 0x0b,
454         0xc0, 0x5b,
455         0xc1, 0x10,
456         0xc2, 0x12,
457         0xd0, 0x02,
458         0xd1, 0x00,
459         0xd2, 0x00,
460         0xd3, 0x00,
461         0xd4, 0x02,
462         0xd5, 0x00,
463         0xde, 0x00,
464         0xdf, 0x01,
465         0xff, 0xff,
466 };
467
468 static struct stv0297_config alps_tdee4_stv0297_config = {
469         .demod_address = 0x1c,
470         .inittab = alps_tdee4_stv0297_inittab,
471 //      .invert = 1,
472 //      .pll_set = alps_tdee4_stv0297_pll_set,
473 };
474
475 /* try to figure out the frontend, each card/box can have on of the following list */
476 int flexcop_frontend_init(struct flexcop_device *fc)
477 {
478         struct dvb_frontend_ops *ops;
479
480         /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
481         if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
482                 ops = &fc->fe->ops;
483
484                 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
485
486                 ops->set_voltage = flexcop_set_voltage;
487
488                 fc->fe_sleep             = ops->sleep;
489                 ops->sleep               = flexcop_sleep;
490
491                 fc->dev_type          = FC_SKY;
492                 info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
493         } else
494         /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
495         if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
496                 fc->dev_type          = FC_AIR_DVB;
497                 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
498                 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
499         } else
500         /* try the air atsc 2nd generation (nxt2002) */
501         if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
502                 fc->dev_type          = FC_AIR_ATSC2;
503                 dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
504                 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
505         } else
506         /* try the air atsc 3nd generation (lgdt3303) */
507         if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
508                 fc->dev_type          = FC_AIR_ATSC3;
509                 dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
510                 info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
511         } else
512         /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
513         if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
514                 fc->dev_type          = FC_AIR_ATSC1;
515                 info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
516         } else
517         /* try the cable dvb (stv0297) */
518         if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
519                 fc->dev_type                        = FC_CABLE;
520                 fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
521                 info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
522         } else
523         /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
524         if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
525                 ops = &fc->fe->ops;
526
527                 ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
528
529                 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
530                 ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
531                 ops->set_tone               = flexcop_set_tone;
532                 ops->set_voltage            = flexcop_set_voltage;
533
534                 fc->fe_sleep                = ops->sleep;
535                 ops->sleep                  = flexcop_sleep;
536
537                 fc->dev_type                = FC_SKY_OLD;
538                 info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
539         }
540
541         if (fc->fe == NULL) {
542                 err("no frontend driver found for this B2C2/FlexCop adapter");
543                 return -ENODEV;
544         } else {
545                 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
546                         err("frontend registration failed!");
547                         dvb_frontend_detach(fc->fe);
548                         fc->fe = NULL;
549                         return -EINVAL;
550                 }
551         }
552         fc->init_state |= FC_STATE_FE_INIT;
553         return 0;
554 }
555
556 void flexcop_frontend_exit(struct flexcop_device *fc)
557 {
558         if (fc->init_state & FC_STATE_FE_INIT) {
559                 dvb_unregister_frontend(fc->fe);
560                 dvb_frontend_detach(fc->fe);
561         }
562
563         fc->init_state &= ~FC_STATE_FE_INIT;
564 }