allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / drivers / media / dvb / b2c2 / flexcop-fe-tuner.c
blobb02c2fd65baa9110461293ca8d77c8bd674ee81a
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 "dvb-pll.h"
19 /* lnb control */
21 static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
23 struct flexcop_device *fc = fe->dvb->priv;
24 flexcop_ibi_value v;
25 deb_tuner("polarity/voltage = %u\n", voltage);
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;
44 return fc->write_ibi_reg(fc, misc_204, v);
47 static int flexcop_sleep(struct dvb_frontend* fe)
49 struct flexcop_device *fc = fe->dvb->priv;
50 /* flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */
52 if (fc->fe_sleep)
53 return fc->fe_sleep(fe);
55 /* v.misc_204.ACPI3_sig = 1;
56 fc->write_ibi_reg(fc,misc_204,v);*/
58 return 0;
61 static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
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;
69 deb_tuner("tone = %u\n",tone);
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;
83 v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
85 v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
86 v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax;
88 return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
91 static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
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);
99 static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
101 int i, par = 1, d;
103 for (i = 7; i >= 0; i--) {
104 d = (data >> i) & 1;
105 par ^= d;
106 flexcop_diseqc_send_bit(fe, d);
109 flexcop_diseqc_send_bit(fe, par);
112 static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst)
114 int i;
116 flexcop_set_tone(fe, SEC_TONE_OFF);
117 mdelay(16);
119 for (i = 0; i < len; i++)
120 flexcop_diseqc_send_byte(fe,msg[i]);
122 mdelay(16);
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);
132 msleep(20);
134 return 0;
137 static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
139 return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
142 static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
144 return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
147 /* dvb-s stv0299 */
148 static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
150 u8 aclk = 0;
151 u8 bclk = 0;
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; }
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);
166 return 0;
169 static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
171 u8 buf[4];
172 u32 div;
173 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
174 struct flexcop_device *fc = fe->dvb->priv;
176 div = params->frequency / 125;
178 buf[0] = (div >> 8) & 0x7f;
179 buf[1] = div & 0xff;
180 buf[2] = 0x84; /* 0xC4 */
181 buf[3] = 0x08;
183 if (params->frequency < 1500000) buf[3] |= 0x10;
185 if (fe->ops.i2c_gate_ctrl)
186 fe->ops.i2c_gate_ctrl(fe, 1);
187 if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
188 return -EIO;
190 return 0;
193 static u8 samsung_tbmu24112_inittab[] = {
194 0x01, 0x15,
195 0x02, 0x30,
196 0x03, 0x00,
197 0x04, 0x7D,
198 0x05, 0x35,
199 0x06, 0x02,
200 0x07, 0x00,
201 0x08, 0xC3,
202 0x0C, 0x00,
203 0x0D, 0x81,
204 0x0E, 0x23,
205 0x0F, 0x12,
206 0x10, 0x7E,
207 0x11, 0x84,
208 0x12, 0xB9,
209 0x13, 0x88,
210 0x14, 0x89,
211 0x15, 0xC9,
212 0x16, 0x00,
213 0x17, 0x5C,
214 0x18, 0x00,
215 0x19, 0x00,
216 0x1A, 0x00,
217 0x1C, 0x00,
218 0x1D, 0x00,
219 0x1E, 0x00,
220 0x1F, 0x3A,
221 0x20, 0x2E,
222 0x21, 0x80,
223 0x22, 0xFF,
224 0x23, 0xC1,
225 0x28, 0x00,
226 0x29, 0x1E,
227 0x2A, 0x14,
228 0x2B, 0x0F,
229 0x2C, 0x09,
230 0x2D, 0x05,
231 0x31, 0x1F,
232 0x32, 0x19,
233 0x33, 0xFE,
234 0x34, 0x93,
235 0xff, 0xff,
238 static struct stv0299_config samsung_tbmu24112_config = {
239 .demod_address = 0x68,
240 .inittab = samsung_tbmu24112_inittab,
241 .mclk = 88000000UL,
242 .invert = 0,
243 .skip_reinit = 0,
244 .lock_output = STV0229_LOCKOUTPUT_LK,
245 .volt13_op0_op1 = STV0299_VOLT13_OP1,
246 .min_delay_ms = 100,
247 .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
250 /* dvb-t mt352 */
251 static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
253 static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d };
254 static u8 mt352_reset [] = { 0x50, 0x80 };
255 static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
256 static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 };
257 static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
259 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
260 udelay(2000);
261 mt352_write(fe, mt352_reset, sizeof(mt352_reset));
262 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
264 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
265 mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
267 return 0;
270 static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
272 u32 div;
273 unsigned char bs = 0;
275 if (buf_len < 5)
276 return -EINVAL;
278 #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
279 div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
281 if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09;
282 if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
283 if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
285 pllbuf[0] = 0x61;
286 pllbuf[1] = div >> 8;
287 pllbuf[2] = div & 0xff;
288 pllbuf[3] = 0xcc;
289 pllbuf[4] = bs;
291 return 5;
294 static struct mt352_config samsung_tdtc9251dh0_config = {
295 .demod_address = 0x0f,
296 .demod_init = samsung_tdtc9251dh0_demod_init,
299 static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
301 struct flexcop_device *fc = fe->dvb->priv;
302 return request_firmware(fw, name, fc->dev);
305 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
306 .demod_address = 0x59,
307 .demod_chip = LGDT3303,
308 .serial_mpeg = 0x04,
309 .clock_polarity_flip = 1,
312 static struct nxt200x_config samsung_tbmv_config = {
313 .demod_address = 0x0a,
316 static struct bcm3510_config air2pc_atsc_first_gen_config = {
317 .demod_address = 0x0f,
318 .request_firmware = flexcop_fe_request_firmware,
321 static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
323 u8 buf[4];
324 u32 div;
325 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
326 struct flexcop_device *fc = fe->dvb->priv;
328 div = (params->frequency + (125/2)) / 125;
330 buf[0] = (div >> 8) & 0x7f;
331 buf[1] = (div >> 0) & 0xff;
332 buf[2] = 0x84 | ((div >> 10) & 0x60);
333 buf[3] = 0x80;
335 if (params->frequency < 1550000)
336 buf[3] |= 0x02;
338 if (fe->ops.i2c_gate_ctrl)
339 fe->ops.i2c_gate_ctrl(fe, 1);
340 if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
341 return -EIO;
342 return 0;
345 static struct mt312_config skystar23_samsung_tbdu18132_config = {
347 .demod_address = 0x0e,
350 static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
351 struct dvb_frontend_parameters *fep)
353 struct flexcop_device *fc = fe->dvb->priv;
354 u8 buf[4];
355 u16 div;
356 int ret;
358 /* 62.5 kHz * 10 */
359 #define REF_FREQ 625
360 #define FREQ_OFFSET 36125
362 div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10) / REF_FREQ; // 4 MHz = 4000 KHz
364 buf[0] = (u8)( div >> 8) & 0x7f;
365 buf[1] = (u8) div & 0xff;
367 /* F(osc) = N * Reference Freq. (62.5 kHz)
368 * byte 2 : 0 N14 N13 N12 N11 N10 N9 N8
369 * byte 3 : N7 N6 N5 N4 N3 N2 N1 N0
370 * byte 4 : 1 * * AGD R3 R2 R1 R0
371 * byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1
372 * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
373 buf[2] = 0x95;
375 // Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
376 // 47 - 153 0 * 0 0 0 0 0 1 0x01
377 // 153 - 430 0 * 0 0 0 0 1 0 0x02
378 // 430 - 822 0 * 0 0 1 0 0 0 0x08
379 // 822 - 862 1 * 0 0 1 0 0 0 0x88
381 if (fep->frequency <= 153000000) buf[3] = 0x01;
382 else if (fep->frequency <= 430000000) buf[3] = 0x02;
383 else if (fep->frequency <= 822000000) buf[3] = 0x08;
384 else buf[3] = 0x88;
386 if (fe->ops.i2c_gate_ctrl)
387 fe->ops.i2c_gate_ctrl(fe, 0);
388 deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
389 ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
390 deb_tuner("tuner write returned: %d\n",ret);
392 return 0;
395 static u8 alps_tdee4_stv0297_inittab[] = {
396 0x80, 0x01,
397 0x80, 0x00,
398 0x81, 0x01,
399 0x81, 0x00,
400 0x00, 0x48,
401 0x01, 0x58,
402 0x03, 0x00,
403 0x04, 0x00,
404 0x07, 0x00,
405 0x08, 0x00,
406 0x30, 0xff,
407 0x31, 0x9d,
408 0x32, 0xff,
409 0x33, 0x00,
410 0x34, 0x29,
411 0x35, 0x55,
412 0x36, 0x80,
413 0x37, 0x6e,
414 0x38, 0x9c,
415 0x40, 0x1a,
416 0x41, 0xfe,
417 0x42, 0x33,
418 0x43, 0x00,
419 0x44, 0xff,
420 0x45, 0x00,
421 0x46, 0x00,
422 0x49, 0x04,
423 0x4a, 0x51,
424 0x4b, 0xf8,
425 0x52, 0x30,
426 0x53, 0x06,
427 0x59, 0x06,
428 0x5a, 0x5e,
429 0x5b, 0x04,
430 0x61, 0x49,
431 0x62, 0x0a,
432 0x70, 0xff,
433 0x71, 0x04,
434 0x72, 0x00,
435 0x73, 0x00,
436 0x74, 0x0c,
437 0x80, 0x20,
438 0x81, 0x00,
439 0x82, 0x30,
440 0x83, 0x00,
441 0x84, 0x04,
442 0x85, 0x22,
443 0x86, 0x08,
444 0x87, 0x1b,
445 0x88, 0x00,
446 0x89, 0x00,
447 0x90, 0x00,
448 0x91, 0x04,
449 0xa0, 0x86,
450 0xa1, 0x00,
451 0xa2, 0x00,
452 0xb0, 0x91,
453 0xb1, 0x0b,
454 0xc0, 0x5b,
455 0xc1, 0x10,
456 0xc2, 0x12,
457 0xd0, 0x02,
458 0xd1, 0x00,
459 0xd2, 0x00,
460 0xd3, 0x00,
461 0xd4, 0x02,
462 0xd5, 0x00,
463 0xde, 0x00,
464 0xdf, 0x01,
465 0xff, 0xff,
468 static struct stv0297_config alps_tdee4_stv0297_config = {
469 .demod_address = 0x1c,
470 .inittab = alps_tdee4_stv0297_inittab,
471 // .invert = 1,
472 // .pll_set = alps_tdee4_stv0297_pll_set,
475 /* try to figure out the frontend, each card/box can have on of the following list */
476 int flexcop_frontend_init(struct flexcop_device *fc)
478 struct dvb_frontend_ops *ops;
480 /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
481 if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
482 ops = &fc->fe->ops;
484 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
486 ops->set_voltage = flexcop_set_voltage;
488 fc->fe_sleep = ops->sleep;
489 ops->sleep = flexcop_sleep;
491 fc->dev_type = FC_SKY;
492 info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
493 } else
494 /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
495 if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
496 fc->dev_type = FC_AIR_DVB;
497 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
498 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
499 } else
500 /* try the air atsc 2nd generation (nxt2002) */
501 if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
502 fc->dev_type = FC_AIR_ATSC2;
503 dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, &dvb_pll_samsung_tbmv);
504 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
505 } else
506 /* try the air atsc 3nd generation (lgdt3303) */
507 if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
508 fc->dev_type = FC_AIR_ATSC3;
509 dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_lg_tdvs_h06xf);
510 info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
511 } else
512 /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
513 if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
514 fc->dev_type = FC_AIR_ATSC1;
515 info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
516 } else
517 /* try the cable dvb (stv0297) */
518 if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
519 fc->dev_type = FC_CABLE;
520 fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
521 info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
522 } else
523 /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
524 if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
525 ops = &fc->fe->ops;
527 ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
529 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
530 ops->diseqc_send_burst = flexcop_diseqc_send_burst;
531 ops->set_tone = flexcop_set_tone;
532 ops->set_voltage = flexcop_set_voltage;
534 fc->fe_sleep = ops->sleep;
535 ops->sleep = flexcop_sleep;
537 fc->dev_type = FC_SKY_OLD;
538 info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
541 if (fc->fe == NULL) {
542 err("no frontend driver found for this B2C2/FlexCop adapter");
543 return -ENODEV;
544 } else {
545 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
546 err("frontend registration failed!");
547 dvb_frontend_detach(fc->fe);
548 fc->fe = NULL;
549 return -EINVAL;
552 fc->init_state |= FC_STATE_FE_INIT;
553 return 0;
556 void flexcop_frontend_exit(struct flexcop_device *fc)
558 if (fc->init_state & FC_STATE_FE_INIT) {
559 dvb_unregister_frontend(fc->fe);
560 dvb_frontend_detach(fc->fe);
563 fc->init_state &= ~FC_STATE_FE_INIT;