Merge branch 'fix/pcm-hwptr' into for-linus
[linux/fpc-iii.git] / drivers / media / dvb / b2c2 / flexcop-fe-tuner.c
blobefb4a6c2b57a5d39cf9c70a5cef455a9dbb528e4
1 /*
2 * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
3 * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling
4 * see flexcop.c for copyright information
5 */
6 #include <media/tuner.h>
7 #include "flexcop.h"
8 #include "mt312.h"
9 #include "stv0299.h"
10 #include "s5h1420.h"
11 #include "itd1000.h"
12 #include "cx24113.h"
13 #include "cx24123.h"
14 #include "isl6421.h"
15 #include "mt352.h"
16 #include "bcm3510.h"
17 #include "nxt200x.h"
18 #include "dvb-pll.h"
19 #include "lgdt330x.h"
20 #include "tuner-simple.h"
21 #include "stv0297.h"
23 /* lnb control */
24 #if defined(CONFIG_DVB_MT312_MODULE) || defined(CONFIG_DVB_STV0299_MODULE)
25 static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
27 struct flexcop_device *fc = fe->dvb->priv;
28 flexcop_ibi_value v;
29 deb_tuner("polarity/voltage = %u\n", voltage);
31 v = fc->read_ibi_reg(fc, misc_204);
32 switch (voltage) {
33 case SEC_VOLTAGE_OFF:
34 v.misc_204.ACPI1_sig = 1;
35 break;
36 case SEC_VOLTAGE_13:
37 v.misc_204.ACPI1_sig = 0;
38 v.misc_204.LNB_L_H_sig = 0;
39 break;
40 case SEC_VOLTAGE_18:
41 v.misc_204.ACPI1_sig = 0;
42 v.misc_204.LNB_L_H_sig = 1;
43 break;
44 default:
45 err("unknown SEC_VOLTAGE value");
46 return -EINVAL;
48 return fc->write_ibi_reg(fc, misc_204, v);
50 #endif
52 #if defined(CONFIG_DVB_S5H1420_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) \
53 || defined(CONFIG_DVB_MT312_MODULE)
54 static int flexcop_sleep(struct dvb_frontend* fe)
56 struct flexcop_device *fc = fe->dvb->priv;
57 if (fc->fe_sleep)
58 return fc->fe_sleep(fe);
59 return 0;
61 #endif
63 /* SkyStar2 DVB-S rev 2.3 */
64 #if defined(CONFIG_DVB_MT312_MODULE)
65 static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
67 /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
68 struct flexcop_device *fc = fe->dvb->priv;
69 flexcop_ibi_value v;
70 u16 ax;
71 v.raw = 0;
72 deb_tuner("tone = %u\n",tone);
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;
86 v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
87 v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
88 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;
103 for (i = 7; i >= 0; i--) {
104 d = (data >> i) & 1;
105 par ^= d;
106 flexcop_diseqc_send_bit(fe, d);
108 flexcop_diseqc_send_bit(fe, par);
111 static int flexcop_send_diseqc_msg(struct dvb_frontend *fe,
112 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]);
121 mdelay(16);
123 if (burst != -1) {
124 if (burst)
125 flexcop_diseqc_send_byte(fe, 0xff);
126 else {
127 flexcop_set_tone(fe, SEC_TONE_ON);
128 mdelay(12);
129 udelay(500);
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,
138 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,
144 fe_sec_mini_cmd_t minicmd)
146 return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
149 static struct mt312_config skystar23_samsung_tbdu18132_config = {
150 .demod_address = 0x0e,
153 static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe,
154 struct dvb_frontend_parameters *params)
156 u8 buf[4];
157 u32 div;
158 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf,
159 .len = sizeof(buf) };
160 struct flexcop_device *fc = fe->dvb->priv;
161 div = (params->frequency + (125/2)) / 125;
163 buf[0] = (div >> 8) & 0x7f;
164 buf[1] = (div >> 0) & 0xff;
165 buf[2] = 0x84 | ((div >> 10) & 0x60);
166 buf[3] = 0x80;
168 if (params->frequency < 1550000)
169 buf[3] |= 0x02;
171 if (fe->ops.i2c_gate_ctrl)
172 fe->ops.i2c_gate_ctrl(fe, 1);
173 if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
174 return -EIO;
175 return 0;
178 static int skystar2_rev23_attach(struct flexcop_device *fc,
179 struct i2c_adapter *i2c)
181 fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
182 if (fc->fe != NULL) {
183 struct dvb_frontend_ops *ops = &fc->fe->ops;
184 ops->tuner_ops.set_params =
185 skystar23_samsung_tbdu18132_tuner_set_params;
186 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
187 ops->diseqc_send_burst = flexcop_diseqc_send_burst;
188 ops->set_tone = flexcop_set_tone;
189 ops->set_voltage = flexcop_set_voltage;
190 fc->fe_sleep = ops->sleep;
191 ops->sleep = flexcop_sleep;
192 return 1;
194 return 0;
196 #endif
198 /* SkyStar2 DVB-S rev 2.6 */
199 #if defined(CONFIG_DVB_STV0299_MODULE)
200 static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
201 u32 srate, u32 ratio)
203 u8 aclk = 0;
204 u8 bclk = 0;
206 if (srate < 1500000) {
207 aclk = 0xb7; bclk = 0x47;
208 } else if (srate < 3000000) {
209 aclk = 0xb7; bclk = 0x4b;
210 } else if (srate < 7000000) {
211 aclk = 0xb7; bclk = 0x4f;
212 } else if (srate < 14000000) {
213 aclk = 0xb7; bclk = 0x53;
214 } else if (srate < 30000000) {
215 aclk = 0xb6; bclk = 0x53;
216 } else if (srate < 45000000) {
217 aclk = 0xb4; bclk = 0x51;
220 stv0299_writereg(fe, 0x13, aclk);
221 stv0299_writereg(fe, 0x14, bclk);
222 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
223 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
224 stv0299_writereg(fe, 0x21, ratio & 0xf0);
225 return 0;
228 static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend *fe,
229 struct dvb_frontend_parameters *params)
231 u8 buf[4];
232 u32 div;
233 struct i2c_msg msg = {
234 .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
235 struct flexcop_device *fc = fe->dvb->priv;
236 div = params->frequency / 125;
238 buf[0] = (div >> 8) & 0x7f;
239 buf[1] = div & 0xff;
240 buf[2] = 0x84; /* 0xC4 */
241 buf[3] = 0x08;
243 if (params->frequency < 1500000)
244 buf[3] |= 0x10;
246 if (fe->ops.i2c_gate_ctrl)
247 fe->ops.i2c_gate_ctrl(fe, 1);
248 if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
249 return -EIO;
250 return 0;
253 static u8 samsung_tbmu24112_inittab[] = {
254 0x01, 0x15,
255 0x02, 0x30,
256 0x03, 0x00,
257 0x04, 0x7D,
258 0x05, 0x35,
259 0x06, 0x02,
260 0x07, 0x00,
261 0x08, 0xC3,
262 0x0C, 0x00,
263 0x0D, 0x81,
264 0x0E, 0x23,
265 0x0F, 0x12,
266 0x10, 0x7E,
267 0x11, 0x84,
268 0x12, 0xB9,
269 0x13, 0x88,
270 0x14, 0x89,
271 0x15, 0xC9,
272 0x16, 0x00,
273 0x17, 0x5C,
274 0x18, 0x00,
275 0x19, 0x00,
276 0x1A, 0x00,
277 0x1C, 0x00,
278 0x1D, 0x00,
279 0x1E, 0x00,
280 0x1F, 0x3A,
281 0x20, 0x2E,
282 0x21, 0x80,
283 0x22, 0xFF,
284 0x23, 0xC1,
285 0x28, 0x00,
286 0x29, 0x1E,
287 0x2A, 0x14,
288 0x2B, 0x0F,
289 0x2C, 0x09,
290 0x2D, 0x05,
291 0x31, 0x1F,
292 0x32, 0x19,
293 0x33, 0xFE,
294 0x34, 0x93,
295 0xff, 0xff,
298 static struct stv0299_config samsung_tbmu24112_config = {
299 .demod_address = 0x68,
300 .inittab = samsung_tbmu24112_inittab,
301 .mclk = 88000000UL,
302 .invert = 0,
303 .skip_reinit = 0,
304 .lock_output = STV0299_LOCKOUTPUT_LK,
305 .volt13_op0_op1 = STV0299_VOLT13_OP1,
306 .min_delay_ms = 100,
307 .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
310 static int skystar2_rev26_attach(struct flexcop_device *fc,
311 struct i2c_adapter *i2c)
313 fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
314 if (fc->fe != NULL) {
315 struct dvb_frontend_ops *ops = &fc->fe->ops;
316 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
317 ops->set_voltage = flexcop_set_voltage;
318 fc->fe_sleep = ops->sleep;
319 ops->sleep = flexcop_sleep;
320 return 1;
322 return 0;
324 #endif
326 /* SkyStar2 DVB-S rev 2.7 */
327 #if defined(CONFIG_DVB_S5H1420_MODULE)
328 static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
329 .demod_address = 0x53,
330 .invert = 1,
331 .repeated_start_workaround = 1,
332 .serial_mpeg = 1,
335 static struct itd1000_config skystar2_rev2_7_itd1000_config = {
336 .i2c_address = 0x61,
339 static int skystar2_rev27_attach(struct flexcop_device *fc,
340 struct i2c_adapter *i2c)
342 flexcop_ibi_value r108;
343 struct i2c_adapter *i2c_tuner;
345 /* enable no_base_addr - no repeated start when reading */
346 fc->fc_i2c_adap[0].no_base_addr = 1;
347 fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config,
348 i2c);
349 if (!fc->fe)
350 goto fail;
352 i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
353 if (!i2c_tuner)
354 goto fail;
356 fc->fe_sleep = fc->fe->ops.sleep;
357 fc->fe->ops.sleep = flexcop_sleep;
359 /* enable no_base_addr - no repeated start when reading */
360 fc->fc_i2c_adap[2].no_base_addr = 1;
361 if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
362 0x08, 1, 1)) {
363 err("ISL6421 could NOT be attached");
364 goto fail_isl;
366 info("ISL6421 successfully attached");
368 /* the ITD1000 requires a lower i2c clock - is it a problem ? */
369 r108.raw = 0x00000506;
370 fc->write_ibi_reg(fc, tw_sm_c_108, r108);
371 if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
372 &skystar2_rev2_7_itd1000_config)) {
373 err("ITD1000 could NOT be attached");
374 /* Should i2c clock be restored? */
375 goto fail_isl;
377 info("ITD1000 successfully attached");
379 return 1;
381 fail_isl:
382 fc->fc_i2c_adap[2].no_base_addr = 0;
383 fail:
384 /* for the next devices we need it again */
385 fc->fc_i2c_adap[0].no_base_addr = 0;
386 return 0;
388 #endif
390 /* SkyStar2 rev 2.8 */
391 #if defined(CONFIG_DVB_CX24123_MODULE)
392 static struct cx24123_config skystar2_rev2_8_cx24123_config = {
393 .demod_address = 0x55,
394 .dont_use_pll = 1,
395 .agc_callback = cx24113_agc_callback,
398 static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
399 .i2c_addr = 0x54,
400 .xtal_khz = 10111,
403 static int skystar2_rev28_attach(struct flexcop_device *fc,
404 struct i2c_adapter *i2c)
406 struct i2c_adapter *i2c_tuner;
408 fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
409 i2c);
410 if (!fc->fe)
411 return 0;
413 i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);;
414 if (!i2c_tuner)
415 return 0;
417 if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
418 i2c_tuner)) {
419 err("CX24113 could NOT be attached");
420 return 0;
422 info("CX24113 successfully attached");
424 fc->fc_i2c_adap[2].no_base_addr = 1;
425 if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
426 0x08, 0, 0)) {
427 err("ISL6421 could NOT be attached");
428 fc->fc_i2c_adap[2].no_base_addr = 0;
429 return 0;
431 info("ISL6421 successfully attached");
432 /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
433 * IR-receiver (PIC16F818) - but the card has no input for that ??? */
434 return 1;
436 #endif
438 /* AirStar DVB-T */
439 #if defined(CONFIG_DVB_MT352_MODULE)
440 static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
442 static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
443 static u8 mt352_reset[] = { 0x50, 0x80 };
444 static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
445 static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 };
446 static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
448 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
449 udelay(2000);
450 mt352_write(fe, mt352_reset, sizeof(mt352_reset));
451 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
452 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
453 mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
454 return 0;
457 static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend *fe,
458 struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
460 u32 div;
461 unsigned char bs = 0;
463 if (buf_len < 5)
464 return -EINVAL;
466 #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
467 div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
468 if (params->frequency >= 48000000 && params->frequency <= 154000000) \
469 bs = 0x09;
470 if (params->frequency >= 161000000 && params->frequency <= 439000000) \
471 bs = 0x0a;
472 if (params->frequency >= 447000000 && params->frequency <= 863000000) \
473 bs = 0x08;
475 pllbuf[0] = 0x61;
476 pllbuf[1] = div >> 8;
477 pllbuf[2] = div & 0xff;
478 pllbuf[3] = 0xcc;
479 pllbuf[4] = bs;
480 return 5;
483 static struct mt352_config samsung_tdtc9251dh0_config = {
484 .demod_address = 0x0f,
485 .demod_init = samsung_tdtc9251dh0_demod_init,
488 static int airstar_dvbt_attach(struct flexcop_device *fc,
489 struct i2c_adapter *i2c)
491 fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
492 if (fc->fe != NULL) {
493 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
494 return 1;
496 return 0;
498 #endif
500 /* AirStar ATSC 1st generation */
501 #if defined(CONFIG_DVB_BCM3510_MODULE)
502 static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
503 const struct firmware **fw, char* name)
505 struct flexcop_device *fc = fe->dvb->priv;
506 return request_firmware(fw, name, fc->dev);
509 static struct bcm3510_config air2pc_atsc_first_gen_config = {
510 .demod_address = 0x0f,
511 .request_firmware = flexcop_fe_request_firmware,
514 static int airstar_atsc1_attach(struct flexcop_device *fc,
515 struct i2c_adapter *i2c)
517 fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
518 return fc->fe != NULL;
520 #endif
522 /* AirStar ATSC 2nd generation */
523 #if defined(CONFIG_DVB_NXT200X_MODULE)
524 static struct nxt200x_config samsung_tbmv_config = {
525 .demod_address = 0x0a,
528 static int airstar_atsc2_attach(struct flexcop_device *fc,
529 struct i2c_adapter *i2c)
531 fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
532 if (!fc->fe)
533 return 0;
535 return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
536 DVB_PLL_SAMSUNG_TBMV);
538 #endif
540 /* AirStar ATSC 3rd generation */
541 #if defined(CONFIG_DVB_LGDT330X_MODULE)
542 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
543 .demod_address = 0x59,
544 .demod_chip = LGDT3303,
545 .serial_mpeg = 0x04,
546 .clock_polarity_flip = 1,
549 static int airstar_atsc3_attach(struct flexcop_device *fc,
550 struct i2c_adapter *i2c)
552 fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
553 if (!fc->fe)
554 return 0;
556 return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
557 TUNER_LG_TDVS_H06XF);
559 #endif
561 /* CableStar2 DVB-C */
562 #if defined(CONFIG_DVB_STV0297_MODULE)
563 static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
564 struct dvb_frontend_parameters *fep)
566 struct flexcop_device *fc = fe->dvb->priv;
567 u8 buf[4];
568 u16 div;
569 int ret;
571 /* 62.5 kHz * 10 */
572 #define REF_FREQ 625
573 #define FREQ_OFFSET 36125
575 div = ((fep->frequency/1000 + FREQ_OFFSET) * 10) / REF_FREQ;
576 /* 4 MHz = 4000 KHz */
578 buf[0] = (u8)( div >> 8) & 0x7f;
579 buf[1] = (u8) div & 0xff;
581 /* F(osc) = N * Reference Freq. (62.5 kHz)
582 * byte 2 : 0 N14 N13 N12 N11 N10 N9 N8
583 * byte 3 : N7 N6 N5 N4 N3 N2 N1 N0
584 * byte 4 : 1 * * AGD R3 R2 R1 R0
585 * byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1
586 * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
587 buf[2] = 0x95;
589 /* Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
590 * 47 - 153 0 * 0 0 0 0 0 1 0x01
591 * 153 - 430 0 * 0 0 0 0 1 0 0x02
592 * 430 - 822 0 * 0 0 1 0 0 0 0x08
593 * 822 - 862 1 * 0 0 1 0 0 0 0x88 */
595 if (fep->frequency <= 153000000) buf[3] = 0x01;
596 else if (fep->frequency <= 430000000) buf[3] = 0x02;
597 else if (fep->frequency <= 822000000) buf[3] = 0x08;
598 else buf[3] = 0x88;
600 if (fe->ops.i2c_gate_ctrl)
601 fe->ops.i2c_gate_ctrl(fe, 0);
602 deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n", fep->frequency,
603 buf[0], buf[1], buf[2], buf[3]);
604 ret = fc->i2c_request(&fc->fc_i2c_adap[2],
605 FC_WRITE, 0x61, buf[0], &buf[1], 3);
606 deb_tuner("tuner write returned: %d\n",ret);
607 return ret;
610 static u8 alps_tdee4_stv0297_inittab[] = {
611 0x80, 0x01,
612 0x80, 0x00,
613 0x81, 0x01,
614 0x81, 0x00,
615 0x00, 0x48,
616 0x01, 0x58,
617 0x03, 0x00,
618 0x04, 0x00,
619 0x07, 0x00,
620 0x08, 0x00,
621 0x30, 0xff,
622 0x31, 0x9d,
623 0x32, 0xff,
624 0x33, 0x00,
625 0x34, 0x29,
626 0x35, 0x55,
627 0x36, 0x80,
628 0x37, 0x6e,
629 0x38, 0x9c,
630 0x40, 0x1a,
631 0x41, 0xfe,
632 0x42, 0x33,
633 0x43, 0x00,
634 0x44, 0xff,
635 0x45, 0x00,
636 0x46, 0x00,
637 0x49, 0x04,
638 0x4a, 0x51,
639 0x4b, 0xf8,
640 0x52, 0x30,
641 0x53, 0x06,
642 0x59, 0x06,
643 0x5a, 0x5e,
644 0x5b, 0x04,
645 0x61, 0x49,
646 0x62, 0x0a,
647 0x70, 0xff,
648 0x71, 0x04,
649 0x72, 0x00,
650 0x73, 0x00,
651 0x74, 0x0c,
652 0x80, 0x20,
653 0x81, 0x00,
654 0x82, 0x30,
655 0x83, 0x00,
656 0x84, 0x04,
657 0x85, 0x22,
658 0x86, 0x08,
659 0x87, 0x1b,
660 0x88, 0x00,
661 0x89, 0x00,
662 0x90, 0x00,
663 0x91, 0x04,
664 0xa0, 0x86,
665 0xa1, 0x00,
666 0xa2, 0x00,
667 0xb0, 0x91,
668 0xb1, 0x0b,
669 0xc0, 0x5b,
670 0xc1, 0x10,
671 0xc2, 0x12,
672 0xd0, 0x02,
673 0xd1, 0x00,
674 0xd2, 0x00,
675 0xd3, 0x00,
676 0xd4, 0x02,
677 0xd5, 0x00,
678 0xde, 0x00,
679 0xdf, 0x01,
680 0xff, 0xff,
683 static struct stv0297_config alps_tdee4_stv0297_config = {
684 .demod_address = 0x1c,
685 .inittab = alps_tdee4_stv0297_inittab,
688 static int cablestar2_attach(struct flexcop_device *fc,
689 struct i2c_adapter *i2c)
691 fc->fc_i2c_adap[0].no_base_addr = 1;
692 fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
693 if (!fc->fe) {
694 /* Reset for next frontend to try */
695 fc->fc_i2c_adap[0].no_base_addr = 0;
696 return 0;
698 fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
699 return 1;
701 #endif
703 static struct {
704 flexcop_device_type_t type;
705 int (*attach)(struct flexcop_device *, struct i2c_adapter *);
706 } flexcop_frontends[] = {
707 #if defined(CONFIG_DVB_S5H1420_MODULE)
708 { FC_SKY_REV27, skystar2_rev27_attach },
709 #endif
710 #if defined(CONFIG_DVB_CX24123_MODULE)
711 { FC_SKY_REV28, skystar2_rev28_attach },
712 #endif
713 #if defined(CONFIG_DVB_STV0299_MODULE)
714 { FC_SKY_REV26, skystar2_rev26_attach },
715 #endif
716 #if defined(CONFIG_DVB_MT352_MODULE)
717 { FC_AIR_DVBT, airstar_dvbt_attach },
718 #endif
719 #if defined(CONFIG_DVB_NXT200X_MODULE)
720 { FC_AIR_ATSC2, airstar_atsc2_attach },
721 #endif
722 #if defined(CONFIG_DVB_LGDT330X_MODULE)
723 { FC_AIR_ATSC3, airstar_atsc3_attach },
724 #endif
725 #if defined(CONFIG_DVB_BCM3510_MODULE)
726 { FC_AIR_ATSC1, airstar_atsc1_attach },
727 #endif
728 #if defined(CONFIG_DVB_STV0297_MODULE)
729 { FC_CABLE, cablestar2_attach },
730 #endif
731 #if defined(CONFIG_DVB_MT312_MODULE)
732 { FC_SKY_REV23, skystar2_rev23_attach },
733 #endif
736 /* try to figure out the frontend */
737 int flexcop_frontend_init(struct flexcop_device *fc)
739 int i;
740 for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
741 /* type needs to be set before, because of some workarounds
742 * done based on the probed card type */
743 fc->dev_type = flexcop_frontends[i].type;
744 if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
745 goto fe_found;
746 /* Clean up partially attached frontend */
747 if (fc->fe) {
748 dvb_frontend_detach(fc->fe);
749 fc->fe = NULL;
752 fc->dev_type = FC_UNK;
753 err("no frontend driver found for this B2C2/FlexCop adapter");
754 return -ENODEV;
756 fe_found:
757 info("found '%s' .", fc->fe->ops.info.name);
758 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
759 err("frontend registration failed!");
760 dvb_frontend_detach(fc->fe);
761 fc->fe = NULL;
762 return -EINVAL;
764 fc->init_state |= FC_STATE_FE_INIT;
765 return 0;
768 void flexcop_frontend_exit(struct flexcop_device *fc)
770 if (fc->init_state & FC_STATE_FE_INIT) {
771 dvb_unregister_frontend(fc->fe);
772 dvb_frontend_detach(fc->fe);
774 fc->init_state &= ~FC_STATE_FE_INIT;