V4L/DVB (4028): Change dvb_frontend_ops to be a real field instead of a pointer field...
[linux-block.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 "lg_h06xf.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 int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
307 {
308         struct flexcop_device *fc = fe->dvb->priv;
309         return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
310 }
311
312 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
313         .demod_address       = 0x59,
314         .demod_chip          = LGDT3303,
315         .serial_mpeg         = 0x04,
316         .clock_polarity_flip = 1,
317 };
318
319 static struct nxt200x_config samsung_tbmv_config = {
320         .demod_address    = 0x0a,
321 };
322
323 static struct bcm3510_config air2pc_atsc_first_gen_config = {
324         .demod_address    = 0x0f,
325         .request_firmware = flexcop_fe_request_firmware,
326 };
327
328 static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
329 {
330         u8 buf[4];
331         u32 div;
332         struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
333         struct flexcop_device *fc = fe->dvb->priv;
334
335         div = (params->frequency + (125/2)) / 125;
336
337         buf[0] = (div >> 8) & 0x7f;
338         buf[1] = (div >> 0) & 0xff;
339         buf[2] = 0x84 | ((div >> 10) & 0x60);
340         buf[3] = 0x80;
341
342         if (params->frequency < 1550000)
343                 buf[3] |= 0x02;
344
345         if (fe->ops.i2c_gate_ctrl)
346                 fe->ops.i2c_gate_ctrl(fe, 1);
347         if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
348                 return -EIO;
349         return 0;
350 }
351
352 static struct mt312_config skystar23_samsung_tbdu18132_config = {
353
354         .demod_address = 0x0e,
355 };
356
357 int alps_tdee4_stv0297_tuner_set_params (struct dvb_frontend* fe, struct dvb_frontend_parameters *fep)
358 {
359         struct flexcop_device *fc = fe->dvb->priv;
360         u8 buf[4];
361         u16 div;
362         int ret;
363
364 /*  62.5 kHz * 10 */
365 #define REF_FREQ    625
366 #define FREQ_OFFSET 36125
367
368         div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10)  / REF_FREQ; // 4 MHz = 4000 KHz
369
370         buf[0] = (u8)( div >> 8) & 0x7f;
371         buf[1] = (u8)        div & 0xff;
372
373 /* F(osc) = N * Reference Freq. (62.5 kHz)
374  * byte 2 :  0 N14 N13 N12 N11 N10 N9  N8
375  * byte 3 : N7 N6  N5  N4  N3  N2  N1  N0
376  * byte 4 : 1  *   *   AGD R3  R2  R1  R0
377  * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
378  * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
379         buf[2] = 0x95;
380
381 // Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
382 //  47 - 153   0  *  0   0   0   0   0   1   0x01
383 // 153 - 430   0  *  0   0   0   0   1   0   0x02
384 // 430 - 822   0  *  0   0   1   0   0   0   0x08
385 // 822 - 862   1  *  0   0   1   0   0   0   0x88
386
387              if (fep->frequency <= 153000000) buf[3] = 0x01;
388         else if (fep->frequency <= 430000000) buf[3] = 0x02;
389         else if (fep->frequency <= 822000000) buf[3] = 0x08;
390         else buf[3] = 0x88;
391
392         if (fe->ops.i2c_gate_ctrl)
393                 fe->ops.i2c_gate_ctrl(fe, 1);
394         deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
395         ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
396         deb_tuner("tuner write returned: %d\n",ret);
397
398         return 0;
399 }
400
401 static u8 alps_tdee4_stv0297_inittab[] = {
402         0x80, 0x01,
403         0x80, 0x00,
404         0x81, 0x01,
405         0x81, 0x00,
406         0x00, 0x09,
407         0x01, 0x69,
408         0x03, 0x00,
409         0x04, 0x00,
410         0x07, 0x00,
411         0x08, 0x00,
412         0x20, 0x00,
413         0x21, 0x40,
414         0x22, 0x00,
415         0x23, 0x00,
416         0x24, 0x40,
417         0x25, 0x88,
418         0x30, 0xff,
419         0x31, 0x00,
420         0x32, 0xff,
421         0x33, 0x00,
422         0x34, 0x50,
423         0x35, 0x7f,
424         0x36, 0x00,
425         0x37, 0x20,
426         0x38, 0x00,
427         0x40, 0x1c,
428         0x41, 0xff,
429         0x42, 0x29,
430         0x43, 0x00,
431         0x44, 0xff,
432         0x45, 0x00,
433         0x46, 0x00,
434         0x49, 0x04,
435         0x4a, 0x00,
436         0x4b, 0xf8,
437         0x52, 0x30,
438         0x55, 0xae,
439         0x56, 0x47,
440         0x57, 0xe1,
441         0x58, 0x3a,
442         0x5a, 0x1e,
443         0x5b, 0x34,
444         0x60, 0x00,
445         0x63, 0x00,
446         0x64, 0x00,
447         0x65, 0x00,
448         0x66, 0x00,
449         0x67, 0x00,
450         0x68, 0x00,
451         0x69, 0x00,
452         0x6a, 0x02,
453         0x6b, 0x00,
454         0x70, 0xff,
455         0x71, 0x00,
456         0x72, 0x00,
457         0x73, 0x00,
458         0x74, 0x0c,
459         0x80, 0x00,
460         0x81, 0x00,
461         0x82, 0x00,
462         0x83, 0x00,
463         0x84, 0x04,
464         0x85, 0x80,
465         0x86, 0x24,
466         0x87, 0x78,
467         0x88, 0x10,
468         0x89, 0x00,
469         0x90, 0x01,
470         0x91, 0x01,
471         0xa0, 0x04,
472         0xa1, 0x00,
473         0xa2, 0x00,
474         0xb0, 0x91,
475         0xb1, 0x0b,
476         0xc0, 0x53,
477         0xc1, 0x70,
478         0xc2, 0x12,
479         0xd0, 0x00,
480         0xd1, 0x00,
481         0xd2, 0x00,
482         0xd3, 0x00,
483         0xd4, 0x00,
484         0xd5, 0x00,
485         0xde, 0x00,
486         0xdf, 0x00,
487         0x61, 0x49,
488         0x62, 0x0b,
489         0x53, 0x08,
490         0x59, 0x08,
491         0xff, 0xff,
492 };
493
494 static struct stv0297_config alps_tdee4_stv0297_config = {
495         .demod_address = 0x1c,
496         .inittab = alps_tdee4_stv0297_inittab,
497 //      .invert = 1,
498 //      .pll_set = alps_tdee4_stv0297_pll_set,
499 };
500
501 /* try to figure out the frontend, each card/box can have on of the following list */
502 int flexcop_frontend_init(struct flexcop_device *fc)
503 {
504         struct dvb_frontend_ops *ops;
505
506         /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
507         if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
508                 ops = &fc->fe->ops;
509
510                 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
511
512                 ops->set_voltage = flexcop_set_voltage;
513
514                 fc->fe_sleep             = ops->sleep;
515                 ops->sleep               = flexcop_sleep;
516
517                 fc->dev_type          = FC_SKY;
518                 info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
519         } else
520         /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
521         if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
522                 fc->dev_type          = FC_AIR_DVB;
523                 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
524                 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
525         } else
526         /* try the air atsc 2nd generation (nxt2002) */
527         if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
528                 fc->dev_type          = FC_AIR_ATSC2;
529                 dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
530                 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
531         } else
532         /* try the air atsc 3nd generation (lgdt3303) */
533         if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
534                 fc->dev_type          = FC_AIR_ATSC3;
535                 fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
536                 info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
537         } else
538         /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
539         if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
540                 fc->dev_type          = FC_AIR_ATSC1;
541                 info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
542         } else
543         /* try the cable dvb (stv0297) */
544         if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
545                 fc->dev_type                        = FC_CABLE;
546                 fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
547                 info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
548         } else
549         /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
550         if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
551                 ops = &fc->fe->ops;
552
553                 ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
554
555                 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
556                 ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
557                 ops->set_tone               = flexcop_set_tone;
558                 ops->set_voltage            = flexcop_set_voltage;
559
560                 fc->fe_sleep                = ops->sleep;
561                 ops->sleep                  = flexcop_sleep;
562
563                 fc->dev_type                = FC_SKY_OLD;
564                 info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
565         }
566
567         if (fc->fe == NULL) {
568                 err("no frontend driver found for this B2C2/FlexCop adapter");
569                 return -ENODEV;
570         } else {
571                 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
572                         err("frontend registration failed!");
573                         ops = &fc->fe->ops;
574                         if (ops->release != NULL)
575                                 ops->release(fc->fe);
576                         fc->fe = NULL;
577                         return -EINVAL;
578                 }
579         }
580         fc->init_state |= FC_STATE_FE_INIT;
581         return 0;
582 }
583
584 void flexcop_frontend_exit(struct flexcop_device *fc)
585 {
586         if (fc->init_state & FC_STATE_FE_INIT)
587                 dvb_unregister_frontend(fc->fe);
588
589         fc->init_state &= ~FC_STATE_FE_INIT;
590 }