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