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