[PATCH] IB/ipath: fixed bug 9776 for real
[linux-2.6/verdex.git] / drivers / media / dvb / b2c2 / flexcop-fe-tuner.c
blob3be87c72e37b7f6bf13053f3db75a0fd9a4229af
1 /*
2 * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
4 * flexcop-fe-tuner.c - methods for attaching a frontend and controlling DiSEqC.
6 * see flexcop.c for copyright information.
7 */
8 #include "flexcop.h"
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"
20 /* lnb control */
22 static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
24 struct flexcop_device *fc = fe->dvb->priv;
25 flexcop_ibi_value v;
26 deb_tuner("polarity/voltage = %u\n", voltage);
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;
45 return fc->write_ibi_reg(fc, misc_204, v);
48 static int flexcop_sleep(struct dvb_frontend* fe)
50 struct flexcop_device *fc = fe->dvb->priv;
51 /* flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */
53 if (fc->fe_sleep)
54 return fc->fe_sleep(fe);
56 /* v.misc_204.ACPI3_sig = 1;
57 fc->write_ibi_reg(fc,misc_204,v);*/
59 return 0;
62 static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
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;
70 deb_tuner("tone = %u\n",tone);
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;
84 v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
86 v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
87 v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax;
89 return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
92 static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
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);
100 static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
102 int i, par = 1, d;
104 for (i = 7; i >= 0; i--) {
105 d = (data >> i) & 1;
106 par ^= d;
107 flexcop_diseqc_send_bit(fe, d);
110 flexcop_diseqc_send_bit(fe, par);
113 static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst)
115 int i;
117 flexcop_set_tone(fe, SEC_TONE_OFF);
118 mdelay(16);
120 for (i = 0; i < len; i++)
121 flexcop_diseqc_send_byte(fe,msg[i]);
123 mdelay(16);
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);
133 msleep(20);
135 return 0;
138 static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
140 return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
143 static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
145 return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
148 /* dvb-s stv0299 */
149 static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
151 u8 aclk = 0;
152 u8 bclk = 0;
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; }
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);
167 return 0;
170 static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
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;
177 div = params->frequency / 125;
179 buf[0] = (div >> 8) & 0x7f;
180 buf[1] = div & 0xff;
181 buf[2] = 0x84; /* 0xC4 */
182 buf[3] = 0x08;
184 if (params->frequency < 1500000) buf[3] |= 0x10;
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;
191 return 0;
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,
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,
251 /* dvb-t mt352 */
252 static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
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 };
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));
265 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
266 mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
268 return 0;
271 static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
273 u32 div;
274 unsigned char bs = 0;
276 if (buf_len < 5)
277 return -EINVAL;
279 #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
280 div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
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;
286 pllbuf[0] = 0x61;
287 pllbuf[1] = div >> 8;
288 pllbuf[2] = div & 0xff;
289 pllbuf[3] = 0xcc;
290 pllbuf[4] = bs;
292 return 5;
295 static struct mt352_config samsung_tdtc9251dh0_config = {
296 .demod_address = 0x0f,
297 .demod_init = samsung_tdtc9251dh0_demod_init,
300 static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
302 struct flexcop_device *fc = fe->dvb->priv;
303 return request_firmware(fw, name, fc->dev);
306 static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
308 struct flexcop_device *fc = fe->dvb->priv;
309 return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
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,
319 static struct nxt200x_config samsung_tbmv_config = {
320 .demod_address = 0x0a,
323 static struct bcm3510_config air2pc_atsc_first_gen_config = {
324 .demod_address = 0x0f,
325 .request_firmware = flexcop_fe_request_firmware,
328 static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
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;
335 div = (params->frequency + (125/2)) / 125;
337 buf[0] = (div >> 8) & 0x7f;
338 buf[1] = (div >> 0) & 0xff;
339 buf[2] = 0x84 | ((div >> 10) & 0x60);
340 buf[3] = 0x80;
342 if (params->frequency < 1550000)
343 buf[3] |= 0x02;
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;
352 static struct mt312_config skystar23_samsung_tbdu18132_config = {
354 .demod_address = 0x0e,
357 static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
358 struct dvb_frontend_parameters *fep)
360 struct flexcop_device *fc = fe->dvb->priv;
361 u8 buf[4];
362 u16 div;
363 int ret;
365 /* 62.5 kHz * 10 */
366 #define REF_FREQ 625
367 #define FREQ_OFFSET 36125
369 div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10) / REF_FREQ; // 4 MHz = 4000 KHz
371 buf[0] = (u8)( div >> 8) & 0x7f;
372 buf[1] = (u8) div & 0xff;
374 /* F(osc) = N * Reference Freq. (62.5 kHz)
375 * byte 2 : 0 N14 N13 N12 N11 N10 N9 N8
376 * byte 3 : N7 N6 N5 N4 N3 N2 N1 N0
377 * byte 4 : 1 * * AGD R3 R2 R1 R0
378 * byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1
379 * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
380 buf[2] = 0x95;
382 // Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
383 // 47 - 153 0 * 0 0 0 0 0 1 0x01
384 // 153 - 430 0 * 0 0 0 0 1 0 0x02
385 // 430 - 822 0 * 0 0 1 0 0 0 0x08
386 // 822 - 862 1 * 0 0 1 0 0 0 0x88
388 if (fep->frequency <= 153000000) buf[3] = 0x01;
389 else if (fep->frequency <= 430000000) buf[3] = 0x02;
390 else if (fep->frequency <= 822000000) buf[3] = 0x08;
391 else buf[3] = 0x88;
393 if (fe->ops.i2c_gate_ctrl)
394 fe->ops.i2c_gate_ctrl(fe, 1);
395 deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
396 ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
397 deb_tuner("tuner write returned: %d\n",ret);
399 return 0;
402 static u8 alps_tdee4_stv0297_inittab[] = {
403 0x80, 0x01,
404 0x80, 0x00,
405 0x81, 0x01,
406 0x81, 0x00,
407 0x00, 0x09,
408 0x01, 0x69,
409 0x03, 0x00,
410 0x04, 0x00,
411 0x07, 0x00,
412 0x08, 0x00,
413 0x20, 0x00,
414 0x21, 0x40,
415 0x22, 0x00,
416 0x23, 0x00,
417 0x24, 0x40,
418 0x25, 0x88,
419 0x30, 0xff,
420 0x31, 0x00,
421 0x32, 0xff,
422 0x33, 0x00,
423 0x34, 0x50,
424 0x35, 0x7f,
425 0x36, 0x00,
426 0x37, 0x20,
427 0x38, 0x00,
428 0x40, 0x1c,
429 0x41, 0xff,
430 0x42, 0x29,
431 0x43, 0x00,
432 0x44, 0xff,
433 0x45, 0x00,
434 0x46, 0x00,
435 0x49, 0x04,
436 0x4a, 0x00,
437 0x4b, 0xf8,
438 0x52, 0x30,
439 0x55, 0xae,
440 0x56, 0x47,
441 0x57, 0xe1,
442 0x58, 0x3a,
443 0x5a, 0x1e,
444 0x5b, 0x34,
445 0x60, 0x00,
446 0x63, 0x00,
447 0x64, 0x00,
448 0x65, 0x00,
449 0x66, 0x00,
450 0x67, 0x00,
451 0x68, 0x00,
452 0x69, 0x00,
453 0x6a, 0x02,
454 0x6b, 0x00,
455 0x70, 0xff,
456 0x71, 0x00,
457 0x72, 0x00,
458 0x73, 0x00,
459 0x74, 0x0c,
460 0x80, 0x00,
461 0x81, 0x00,
462 0x82, 0x00,
463 0x83, 0x00,
464 0x84, 0x04,
465 0x85, 0x80,
466 0x86, 0x24,
467 0x87, 0x78,
468 0x88, 0x10,
469 0x89, 0x00,
470 0x90, 0x01,
471 0x91, 0x01,
472 0xa0, 0x04,
473 0xa1, 0x00,
474 0xa2, 0x00,
475 0xb0, 0x91,
476 0xb1, 0x0b,
477 0xc0, 0x53,
478 0xc1, 0x70,
479 0xc2, 0x12,
480 0xd0, 0x00,
481 0xd1, 0x00,
482 0xd2, 0x00,
483 0xd3, 0x00,
484 0xd4, 0x00,
485 0xd5, 0x00,
486 0xde, 0x00,
487 0xdf, 0x00,
488 0x61, 0x49,
489 0x62, 0x0b,
490 0x53, 0x08,
491 0x59, 0x08,
492 0xff, 0xff,
495 static struct stv0297_config alps_tdee4_stv0297_config = {
496 .demod_address = 0x1c,
497 .inittab = alps_tdee4_stv0297_inittab,
498 // .invert = 1,
499 // .pll_set = alps_tdee4_stv0297_pll_set,
502 /* try to figure out the frontend, each card/box can have on of the following list */
503 int flexcop_frontend_init(struct flexcop_device *fc)
505 struct dvb_frontend_ops *ops;
507 /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
508 if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
509 ops = &fc->fe->ops;
511 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
513 ops->set_voltage = flexcop_set_voltage;
515 fc->fe_sleep = ops->sleep;
516 ops->sleep = flexcop_sleep;
518 fc->dev_type = FC_SKY;
519 info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
520 } else
521 /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
522 if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
523 fc->dev_type = FC_AIR_DVB;
524 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
525 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
526 } else
527 /* try the air atsc 2nd generation (nxt2002) */
528 if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
529 fc->dev_type = FC_AIR_ATSC2;
530 dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
531 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
532 } else
533 /* try the air atsc 3nd generation (lgdt3303) */
534 if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
535 fc->dev_type = FC_AIR_ATSC3;
536 fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
537 info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
538 } else
539 /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
540 if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
541 fc->dev_type = FC_AIR_ATSC1;
542 info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
543 } else
544 /* try the cable dvb (stv0297) */
545 if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
546 fc->dev_type = FC_CABLE;
547 fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
548 info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
549 } else
550 /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
551 if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
552 ops = &fc->fe->ops;
554 ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
556 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
557 ops->diseqc_send_burst = flexcop_diseqc_send_burst;
558 ops->set_tone = flexcop_set_tone;
559 ops->set_voltage = flexcop_set_voltage;
561 fc->fe_sleep = ops->sleep;
562 ops->sleep = flexcop_sleep;
564 fc->dev_type = FC_SKY_OLD;
565 info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
568 if (fc->fe == NULL) {
569 err("no frontend driver found for this B2C2/FlexCop adapter");
570 return -ENODEV;
571 } else {
572 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
573 err("frontend registration failed!");
574 ops = &fc->fe->ops;
575 if (ops->release != NULL)
576 ops->release(fc->fe);
577 fc->fe = NULL;
578 return -EINVAL;
581 fc->init_state |= FC_STATE_FE_INIT;
582 return 0;
585 void flexcop_frontend_exit(struct flexcop_device *fc)
587 if (fc->init_state & FC_STATE_FE_INIT)
588 dvb_unregister_frontend(fc->fe);
590 fc->init_state &= ~FC_STATE_FE_INIT;