Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
[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 "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, 0);
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, 0x48,
402         0x01, 0x58,
403         0x03, 0x00,
404         0x04, 0x00,
405         0x07, 0x00,
406         0x08, 0x00,
407         0x30, 0xff,
408         0x31, 0x9d,
409         0x32, 0xff,
410         0x33, 0x00,
411         0x34, 0x29,
412         0x35, 0x55,
413         0x36, 0x80,
414         0x37, 0x6e,
415         0x38, 0x9c,
416         0x40, 0x1a,
417         0x41, 0xfe,
418         0x42, 0x33,
419         0x43, 0x00,
420         0x44, 0xff,
421         0x45, 0x00,
422         0x46, 0x00,
423         0x49, 0x04,
424         0x4a, 0x51,
425         0x4b, 0xf8,
426         0x52, 0x30,
427         0x53, 0x06,
428         0x59, 0x06,
429         0x5a, 0x5e,
430         0x5b, 0x04,
431         0x61, 0x49,
432         0x62, 0x0a,
433         0x70, 0xff,
434         0x71, 0x04,
435         0x72, 0x00,
436         0x73, 0x00,
437         0x74, 0x0c,
438         0x80, 0x20,
439         0x81, 0x00,
440         0x82, 0x30,
441         0x83, 0x00,
442         0x84, 0x04,
443         0x85, 0x22,
444         0x86, 0x08,
445         0x87, 0x1b,
446         0x88, 0x00,
447         0x89, 0x00,
448         0x90, 0x00,
449         0x91, 0x04,
450         0xa0, 0x86,
451         0xa1, 0x00,
452         0xa2, 0x00,
453         0xb0, 0x91,
454         0xb1, 0x0b,
455         0xc0, 0x5b,
456         0xc1, 0x10,
457         0xc2, 0x12,
458         0xd0, 0x02,
459         0xd1, 0x00,
460         0xd2, 0x00,
461         0xd3, 0x00,
462         0xd4, 0x02,
463         0xd5, 0x00,
464         0xde, 0x00,
465         0xdf, 0x01,
466         0xff, 0xff,
467 };
468
469 static struct stv0297_config alps_tdee4_stv0297_config = {
470         .demod_address = 0x1c,
471         .inittab = alps_tdee4_stv0297_inittab,
472 //      .invert = 1,
473 //      .pll_set = alps_tdee4_stv0297_pll_set,
474 };
475
476 /* try to figure out the frontend, each card/box can have on of the following list */
477 int flexcop_frontend_init(struct flexcop_device *fc)
478 {
479         struct dvb_frontend_ops *ops;
480
481         /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
482         if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
483                 ops = &fc->fe->ops;
484
485                 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
486
487                 ops->set_voltage = flexcop_set_voltage;
488
489                 fc->fe_sleep             = ops->sleep;
490                 ops->sleep               = flexcop_sleep;
491
492                 fc->dev_type          = FC_SKY;
493                 info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
494         } else
495         /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
496         if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
497                 fc->dev_type          = FC_AIR_DVB;
498                 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
499                 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
500         } else
501         /* try the air atsc 2nd generation (nxt2002) */
502         if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
503                 fc->dev_type          = FC_AIR_ATSC2;
504                 dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, &dvb_pll_samsung_tbmv);
505                 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
506         } else
507         /* try the air atsc 3nd generation (lgdt3303) */
508         if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
509                 fc->dev_type          = FC_AIR_ATSC3;
510                 dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap);
511                 info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
512         } else
513         /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
514         if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
515                 fc->dev_type          = FC_AIR_ATSC1;
516                 info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
517         } else
518         /* try the cable dvb (stv0297) */
519         if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
520                 fc->dev_type                        = FC_CABLE;
521                 fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
522                 info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
523         } else
524         /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
525         if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
526                 ops = &fc->fe->ops;
527
528                 ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
529
530                 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
531                 ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
532                 ops->set_tone               = flexcop_set_tone;
533                 ops->set_voltage            = flexcop_set_voltage;
534
535                 fc->fe_sleep                = ops->sleep;
536                 ops->sleep                  = flexcop_sleep;
537
538                 fc->dev_type                = FC_SKY_OLD;
539                 info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
540         }
541
542         if (fc->fe == NULL) {
543                 err("no frontend driver found for this B2C2/FlexCop adapter");
544                 return -ENODEV;
545         } else {
546                 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
547                         err("frontend registration failed!");
548                         dvb_frontend_detach(fc->fe);
549                         fc->fe = NULL;
550                         return -EINVAL;
551                 }
552         }
553         fc->init_state |= FC_STATE_FE_INIT;
554         return 0;
555 }
556
557 void flexcop_frontend_exit(struct flexcop_device *fc)
558 {
559         if (fc->init_state & FC_STATE_FE_INIT) {
560                 dvb_unregister_frontend(fc->fe);
561                 dvb_frontend_detach(fc->fe);
562         }
563
564         fc->init_state &= ~FC_STATE_FE_INIT;
565 }