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