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