Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[deliverable/linux.git] / drivers / media / dvb / b2c2 / flexcop-fe-tuner.c
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"
22
23
24 /* Can we use the specified front-end? Remember that if we are compiled
25 * into the kernel we can't call code that's in modules. */
26 #define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
27 (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
28
29 /* lnb control */
30 #if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
31 static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
32 {
33 struct flexcop_device *fc = fe->dvb->priv;
34 flexcop_ibi_value v;
35 deb_tuner("polarity/voltage = %u\n", voltage);
36
37 v = fc->read_ibi_reg(fc, misc_204);
38 switch (voltage) {
39 case SEC_VOLTAGE_OFF:
40 v.misc_204.ACPI1_sig = 1;
41 break;
42 case SEC_VOLTAGE_13:
43 v.misc_204.ACPI1_sig = 0;
44 v.misc_204.LNB_L_H_sig = 0;
45 break;
46 case SEC_VOLTAGE_18:
47 v.misc_204.ACPI1_sig = 0;
48 v.misc_204.LNB_L_H_sig = 1;
49 break;
50 default:
51 err("unknown SEC_VOLTAGE value");
52 return -EINVAL;
53 }
54 return fc->write_ibi_reg(fc, misc_204, v);
55 }
56 #endif
57
58 #if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
59 static int flexcop_sleep(struct dvb_frontend* fe)
60 {
61 struct flexcop_device *fc = fe->dvb->priv;
62 if (fc->fe_sleep)
63 return fc->fe_sleep(fe);
64 return 0;
65 }
66 #endif
67
68 /* SkyStar2 DVB-S rev 2.3 */
69 #if FE_SUPPORTED(MT312)
70 static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
71 {
72 /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
73 struct flexcop_device *fc = fe->dvb->priv;
74 flexcop_ibi_value v;
75 u16 ax;
76 v.raw = 0;
77 deb_tuner("tone = %u\n",tone);
78
79 switch (tone) {
80 case SEC_TONE_ON:
81 ax = 0x01ff;
82 break;
83 case SEC_TONE_OFF:
84 ax = 0;
85 break;
86 default:
87 err("unknown SEC_TONE value");
88 return -EINVAL;
89 }
90
91 v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
92 v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
93 v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax;
94 return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
95 }
96
97 static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
98 {
99 flexcop_set_tone(fe, SEC_TONE_ON);
100 udelay(data ? 500 : 1000);
101 flexcop_set_tone(fe, SEC_TONE_OFF);
102 udelay(data ? 1000 : 500);
103 }
104
105 static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
106 {
107 int i, par = 1, d;
108 for (i = 7; i >= 0; i--) {
109 d = (data >> i) & 1;
110 par ^= d;
111 flexcop_diseqc_send_bit(fe, d);
112 }
113 flexcop_diseqc_send_bit(fe, par);
114 }
115
116 static int flexcop_send_diseqc_msg(struct dvb_frontend *fe,
117 int len, u8 *msg, unsigned long burst)
118 {
119 int i;
120
121 flexcop_set_tone(fe, SEC_TONE_OFF);
122 mdelay(16);
123
124 for (i = 0; i < len; i++)
125 flexcop_diseqc_send_byte(fe,msg[i]);
126 mdelay(16);
127
128 if (burst != -1) {
129 if (burst)
130 flexcop_diseqc_send_byte(fe, 0xff);
131 else {
132 flexcop_set_tone(fe, SEC_TONE_ON);
133 mdelay(12);
134 udelay(500);
135 flexcop_set_tone(fe, SEC_TONE_OFF);
136 }
137 msleep(20);
138 }
139 return 0;
140 }
141
142 static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe,
143 struct dvb_diseqc_master_cmd *cmd)
144 {
145 return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
146 }
147
148 static int flexcop_diseqc_send_burst(struct dvb_frontend *fe,
149 fe_sec_mini_cmd_t minicmd)
150 {
151 return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
152 }
153
154 static struct mt312_config skystar23_samsung_tbdu18132_config = {
155 .demod_address = 0x0e,
156 };
157
158 static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe,
159 struct dvb_frontend_parameters *params)
160 {
161 u8 buf[4];
162 u32 div;
163 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf,
164 .len = sizeof(buf) };
165 struct flexcop_device *fc = fe->dvb->priv;
166 div = (params->frequency + (125/2)) / 125;
167
168 buf[0] = (div >> 8) & 0x7f;
169 buf[1] = (div >> 0) & 0xff;
170 buf[2] = 0x84 | ((div >> 10) & 0x60);
171 buf[3] = 0x80;
172
173 if (params->frequency < 1550000)
174 buf[3] |= 0x02;
175
176 if (fe->ops.i2c_gate_ctrl)
177 fe->ops.i2c_gate_ctrl(fe, 1);
178 if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
179 return -EIO;
180 return 0;
181 }
182
183 static int skystar2_rev23_attach(struct flexcop_device *fc,
184 struct i2c_adapter *i2c)
185 {
186 fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
187 if (fc->fe != NULL) {
188 struct dvb_frontend_ops *ops = &fc->fe->ops;
189 ops->tuner_ops.set_params =
190 skystar23_samsung_tbdu18132_tuner_set_params;
191 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
192 ops->diseqc_send_burst = flexcop_diseqc_send_burst;
193 ops->set_tone = flexcop_set_tone;
194 ops->set_voltage = flexcop_set_voltage;
195 fc->fe_sleep = ops->sleep;
196 ops->sleep = flexcop_sleep;
197 return 1;
198 }
199 return 0;
200 }
201 #else
202 #define skystar2_rev23_attach NULL
203 #endif
204
205 /* SkyStar2 DVB-S rev 2.6 */
206 #if FE_SUPPORTED(STV0299)
207 static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
208 u32 srate, u32 ratio)
209 {
210 u8 aclk = 0;
211 u8 bclk = 0;
212
213 if (srate < 1500000) {
214 aclk = 0xb7; bclk = 0x47;
215 } else if (srate < 3000000) {
216 aclk = 0xb7; bclk = 0x4b;
217 } else if (srate < 7000000) {
218 aclk = 0xb7; bclk = 0x4f;
219 } else if (srate < 14000000) {
220 aclk = 0xb7; bclk = 0x53;
221 } else if (srate < 30000000) {
222 aclk = 0xb6; bclk = 0x53;
223 } else if (srate < 45000000) {
224 aclk = 0xb4; bclk = 0x51;
225 }
226
227 stv0299_writereg(fe, 0x13, aclk);
228 stv0299_writereg(fe, 0x14, bclk);
229 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
230 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
231 stv0299_writereg(fe, 0x21, ratio & 0xf0);
232 return 0;
233 }
234
235 static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend *fe,
236 struct dvb_frontend_parameters *params)
237 {
238 u8 buf[4];
239 u32 div;
240 struct i2c_msg msg = {
241 .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
242 struct flexcop_device *fc = fe->dvb->priv;
243 div = params->frequency / 125;
244
245 buf[0] = (div >> 8) & 0x7f;
246 buf[1] = div & 0xff;
247 buf[2] = 0x84; /* 0xC4 */
248 buf[3] = 0x08;
249
250 if (params->frequency < 1500000)
251 buf[3] |= 0x10;
252
253 if (fe->ops.i2c_gate_ctrl)
254 fe->ops.i2c_gate_ctrl(fe, 1);
255 if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
256 return -EIO;
257 return 0;
258 }
259
260 static u8 samsung_tbmu24112_inittab[] = {
261 0x01, 0x15,
262 0x02, 0x30,
263 0x03, 0x00,
264 0x04, 0x7D,
265 0x05, 0x35,
266 0x06, 0x02,
267 0x07, 0x00,
268 0x08, 0xC3,
269 0x0C, 0x00,
270 0x0D, 0x81,
271 0x0E, 0x23,
272 0x0F, 0x12,
273 0x10, 0x7E,
274 0x11, 0x84,
275 0x12, 0xB9,
276 0x13, 0x88,
277 0x14, 0x89,
278 0x15, 0xC9,
279 0x16, 0x00,
280 0x17, 0x5C,
281 0x18, 0x00,
282 0x19, 0x00,
283 0x1A, 0x00,
284 0x1C, 0x00,
285 0x1D, 0x00,
286 0x1E, 0x00,
287 0x1F, 0x3A,
288 0x20, 0x2E,
289 0x21, 0x80,
290 0x22, 0xFF,
291 0x23, 0xC1,
292 0x28, 0x00,
293 0x29, 0x1E,
294 0x2A, 0x14,
295 0x2B, 0x0F,
296 0x2C, 0x09,
297 0x2D, 0x05,
298 0x31, 0x1F,
299 0x32, 0x19,
300 0x33, 0xFE,
301 0x34, 0x93,
302 0xff, 0xff,
303 };
304
305 static struct stv0299_config samsung_tbmu24112_config = {
306 .demod_address = 0x68,
307 .inittab = samsung_tbmu24112_inittab,
308 .mclk = 88000000UL,
309 .invert = 0,
310 .skip_reinit = 0,
311 .lock_output = STV0299_LOCKOUTPUT_LK,
312 .volt13_op0_op1 = STV0299_VOLT13_OP1,
313 .min_delay_ms = 100,
314 .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
315 };
316
317 static int skystar2_rev26_attach(struct flexcop_device *fc,
318 struct i2c_adapter *i2c)
319 {
320 fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
321 if (fc->fe != NULL) {
322 struct dvb_frontend_ops *ops = &fc->fe->ops;
323 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
324 ops->set_voltage = flexcop_set_voltage;
325 fc->fe_sleep = ops->sleep;
326 ops->sleep = flexcop_sleep;
327 return 1;
328 }
329 return 0;
330 }
331 #else
332 #define skystar2_rev26_attach NULL
333 #endif
334
335 /* SkyStar2 DVB-S rev 2.7 */
336 #if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000)
337 static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
338 .demod_address = 0x53,
339 .invert = 1,
340 .repeated_start_workaround = 1,
341 .serial_mpeg = 1,
342 };
343
344 static struct itd1000_config skystar2_rev2_7_itd1000_config = {
345 .i2c_address = 0x61,
346 };
347
348 static int skystar2_rev27_attach(struct flexcop_device *fc,
349 struct i2c_adapter *i2c)
350 {
351 flexcop_ibi_value r108;
352 struct i2c_adapter *i2c_tuner;
353
354 /* enable no_base_addr - no repeated start when reading */
355 fc->fc_i2c_adap[0].no_base_addr = 1;
356 fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config,
357 i2c);
358 if (!fc->fe)
359 goto fail;
360
361 i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
362 if (!i2c_tuner)
363 goto fail;
364
365 fc->fe_sleep = fc->fe->ops.sleep;
366 fc->fe->ops.sleep = flexcop_sleep;
367
368 /* enable no_base_addr - no repeated start when reading */
369 fc->fc_i2c_adap[2].no_base_addr = 1;
370 if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
371 0x08, 1, 1)) {
372 err("ISL6421 could NOT be attached");
373 goto fail_isl;
374 }
375 info("ISL6421 successfully attached");
376
377 /* the ITD1000 requires a lower i2c clock - is it a problem ? */
378 r108.raw = 0x00000506;
379 fc->write_ibi_reg(fc, tw_sm_c_108, r108);
380 if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
381 &skystar2_rev2_7_itd1000_config)) {
382 err("ITD1000 could NOT be attached");
383 /* Should i2c clock be restored? */
384 goto fail_isl;
385 }
386 info("ITD1000 successfully attached");
387
388 return 1;
389
390 fail_isl:
391 fc->fc_i2c_adap[2].no_base_addr = 0;
392 fail:
393 /* for the next devices we need it again */
394 fc->fc_i2c_adap[0].no_base_addr = 0;
395 return 0;
396 }
397 #else
398 #define skystar2_rev27_attach NULL
399 #endif
400
401 /* SkyStar2 rev 2.8 */
402 #if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113)
403 static struct cx24123_config skystar2_rev2_8_cx24123_config = {
404 .demod_address = 0x55,
405 .dont_use_pll = 1,
406 .agc_callback = cx24113_agc_callback,
407 };
408
409 static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
410 .i2c_addr = 0x54,
411 .xtal_khz = 10111,
412 };
413
414 static int skystar2_rev28_attach(struct flexcop_device *fc,
415 struct i2c_adapter *i2c)
416 {
417 struct i2c_adapter *i2c_tuner;
418
419 fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
420 i2c);
421 if (!fc->fe)
422 return 0;
423
424 i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);;
425 if (!i2c_tuner)
426 return 0;
427
428 if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
429 i2c_tuner)) {
430 err("CX24113 could NOT be attached");
431 return 0;
432 }
433 info("CX24113 successfully attached");
434
435 fc->fc_i2c_adap[2].no_base_addr = 1;
436 if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
437 0x08, 0, 0)) {
438 err("ISL6421 could NOT be attached");
439 fc->fc_i2c_adap[2].no_base_addr = 0;
440 return 0;
441 }
442 info("ISL6421 successfully attached");
443 /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
444 * IR-receiver (PIC16F818) - but the card has no input for that ??? */
445 return 1;
446 }
447 #else
448 #define skystar2_rev28_attach NULL
449 #endif
450
451 /* AirStar DVB-T */
452 #if FE_SUPPORTED(MT352)
453 static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
454 {
455 static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
456 static u8 mt352_reset[] = { 0x50, 0x80 };
457 static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
458 static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 };
459 static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
460
461 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
462 udelay(2000);
463 mt352_write(fe, mt352_reset, sizeof(mt352_reset));
464 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
465 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
466 mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
467 return 0;
468 }
469
470 static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend *fe,
471 struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
472 {
473 u32 div;
474 unsigned char bs = 0;
475
476 if (buf_len < 5)
477 return -EINVAL;
478
479 #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
480 div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
481 if (params->frequency >= 48000000 && params->frequency <= 154000000) \
482 bs = 0x09;
483 if (params->frequency >= 161000000 && params->frequency <= 439000000) \
484 bs = 0x0a;
485 if (params->frequency >= 447000000 && params->frequency <= 863000000) \
486 bs = 0x08;
487
488 pllbuf[0] = 0x61;
489 pllbuf[1] = div >> 8;
490 pllbuf[2] = div & 0xff;
491 pllbuf[3] = 0xcc;
492 pllbuf[4] = bs;
493 return 5;
494 }
495
496 static struct mt352_config samsung_tdtc9251dh0_config = {
497 .demod_address = 0x0f,
498 .demod_init = samsung_tdtc9251dh0_demod_init,
499 };
500
501 static int airstar_dvbt_attach(struct flexcop_device *fc,
502 struct i2c_adapter *i2c)
503 {
504 fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
505 if (fc->fe != NULL) {
506 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
507 return 1;
508 }
509 return 0;
510 }
511 #else
512 #define airstar_dvbt_attach NULL
513 #endif
514
515 /* AirStar ATSC 1st generation */
516 #if FE_SUPPORTED(BCM3510)
517 static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
518 const struct firmware **fw, char* name)
519 {
520 struct flexcop_device *fc = fe->dvb->priv;
521 return request_firmware(fw, name, fc->dev);
522 }
523
524 static struct bcm3510_config air2pc_atsc_first_gen_config = {
525 .demod_address = 0x0f,
526 .request_firmware = flexcop_fe_request_firmware,
527 };
528
529 static int airstar_atsc1_attach(struct flexcop_device *fc,
530 struct i2c_adapter *i2c)
531 {
532 fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
533 return fc->fe != NULL;
534 }
535 #else
536 #define airstar_atsc1_attach NULL
537 #endif
538
539 /* AirStar ATSC 2nd generation */
540 #if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
541 static struct nxt200x_config samsung_tbmv_config = {
542 .demod_address = 0x0a,
543 };
544
545 static int airstar_atsc2_attach(struct flexcop_device *fc,
546 struct i2c_adapter *i2c)
547 {
548 fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
549 if (!fc->fe)
550 return 0;
551
552 return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
553 DVB_PLL_SAMSUNG_TBMV);
554 }
555 #else
556 #define airstar_atsc2_attach NULL
557 #endif
558
559 /* AirStar ATSC 3rd generation */
560 #if FE_SUPPORTED(LGDT330X)
561 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
562 .demod_address = 0x59,
563 .demod_chip = LGDT3303,
564 .serial_mpeg = 0x04,
565 .clock_polarity_flip = 1,
566 };
567
568 static int airstar_atsc3_attach(struct flexcop_device *fc,
569 struct i2c_adapter *i2c)
570 {
571 fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
572 if (!fc->fe)
573 return 0;
574
575 return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
576 TUNER_LG_TDVS_H06XF);
577 }
578 #else
579 #define airstar_atsc3_attach NULL
580 #endif
581
582 /* CableStar2 DVB-C */
583 #if FE_SUPPORTED(STV0297)
584 static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
585 struct dvb_frontend_parameters *fep)
586 {
587 struct flexcop_device *fc = fe->dvb->priv;
588 u8 buf[4];
589 u16 div;
590 int ret;
591
592 /* 62.5 kHz * 10 */
593 #define REF_FREQ 625
594 #define FREQ_OFFSET 36125
595
596 div = ((fep->frequency/1000 + FREQ_OFFSET) * 10) / REF_FREQ;
597 /* 4 MHz = 4000 KHz */
598
599 buf[0] = (u8)( div >> 8) & 0x7f;
600 buf[1] = (u8) div & 0xff;
601
602 /* F(osc) = N * Reference Freq. (62.5 kHz)
603 * byte 2 : 0 N14 N13 N12 N11 N10 N9 N8
604 * byte 3 : N7 N6 N5 N4 N3 N2 N1 N0
605 * byte 4 : 1 * * AGD R3 R2 R1 R0
606 * byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1
607 * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
608 buf[2] = 0x95;
609
610 /* Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
611 * 47 - 153 0 * 0 0 0 0 0 1 0x01
612 * 153 - 430 0 * 0 0 0 0 1 0 0x02
613 * 430 - 822 0 * 0 0 1 0 0 0 0x08
614 * 822 - 862 1 * 0 0 1 0 0 0 0x88 */
615
616 if (fep->frequency <= 153000000) buf[3] = 0x01;
617 else if (fep->frequency <= 430000000) buf[3] = 0x02;
618 else if (fep->frequency <= 822000000) buf[3] = 0x08;
619 else buf[3] = 0x88;
620
621 if (fe->ops.i2c_gate_ctrl)
622 fe->ops.i2c_gate_ctrl(fe, 0);
623 deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n", fep->frequency,
624 buf[0], buf[1], buf[2], buf[3]);
625 ret = fc->i2c_request(&fc->fc_i2c_adap[2],
626 FC_WRITE, 0x61, buf[0], &buf[1], 3);
627 deb_tuner("tuner write returned: %d\n",ret);
628 return ret;
629 }
630
631 static u8 alps_tdee4_stv0297_inittab[] = {
632 0x80, 0x01,
633 0x80, 0x00,
634 0x81, 0x01,
635 0x81, 0x00,
636 0x00, 0x48,
637 0x01, 0x58,
638 0x03, 0x00,
639 0x04, 0x00,
640 0x07, 0x00,
641 0x08, 0x00,
642 0x30, 0xff,
643 0x31, 0x9d,
644 0x32, 0xff,
645 0x33, 0x00,
646 0x34, 0x29,
647 0x35, 0x55,
648 0x36, 0x80,
649 0x37, 0x6e,
650 0x38, 0x9c,
651 0x40, 0x1a,
652 0x41, 0xfe,
653 0x42, 0x33,
654 0x43, 0x00,
655 0x44, 0xff,
656 0x45, 0x00,
657 0x46, 0x00,
658 0x49, 0x04,
659 0x4a, 0x51,
660 0x4b, 0xf8,
661 0x52, 0x30,
662 0x53, 0x06,
663 0x59, 0x06,
664 0x5a, 0x5e,
665 0x5b, 0x04,
666 0x61, 0x49,
667 0x62, 0x0a,
668 0x70, 0xff,
669 0x71, 0x04,
670 0x72, 0x00,
671 0x73, 0x00,
672 0x74, 0x0c,
673 0x80, 0x20,
674 0x81, 0x00,
675 0x82, 0x30,
676 0x83, 0x00,
677 0x84, 0x04,
678 0x85, 0x22,
679 0x86, 0x08,
680 0x87, 0x1b,
681 0x88, 0x00,
682 0x89, 0x00,
683 0x90, 0x00,
684 0x91, 0x04,
685 0xa0, 0x86,
686 0xa1, 0x00,
687 0xa2, 0x00,
688 0xb0, 0x91,
689 0xb1, 0x0b,
690 0xc0, 0x5b,
691 0xc1, 0x10,
692 0xc2, 0x12,
693 0xd0, 0x02,
694 0xd1, 0x00,
695 0xd2, 0x00,
696 0xd3, 0x00,
697 0xd4, 0x02,
698 0xd5, 0x00,
699 0xde, 0x00,
700 0xdf, 0x01,
701 0xff, 0xff,
702 };
703
704 static struct stv0297_config alps_tdee4_stv0297_config = {
705 .demod_address = 0x1c,
706 .inittab = alps_tdee4_stv0297_inittab,
707 };
708
709 static int cablestar2_attach(struct flexcop_device *fc,
710 struct i2c_adapter *i2c)
711 {
712 fc->fc_i2c_adap[0].no_base_addr = 1;
713 fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
714 if (!fc->fe) {
715 /* Reset for next frontend to try */
716 fc->fc_i2c_adap[0].no_base_addr = 0;
717 return 0;
718 }
719 fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
720 return 1;
721 }
722 #else
723 #define cablestar2_attach NULL
724 #endif
725
726 static struct {
727 flexcop_device_type_t type;
728 int (*attach)(struct flexcop_device *, struct i2c_adapter *);
729 } flexcop_frontends[] = {
730 { FC_SKY_REV27, skystar2_rev27_attach },
731 { FC_SKY_REV28, skystar2_rev28_attach },
732 { FC_SKY_REV26, skystar2_rev26_attach },
733 { FC_AIR_DVBT, airstar_dvbt_attach },
734 { FC_AIR_ATSC2, airstar_atsc2_attach },
735 { FC_AIR_ATSC3, airstar_atsc3_attach },
736 { FC_AIR_ATSC1, airstar_atsc1_attach },
737 { FC_CABLE, cablestar2_attach },
738 { FC_SKY_REV23, skystar2_rev23_attach },
739 };
740
741 /* try to figure out the frontend */
742 int flexcop_frontend_init(struct flexcop_device *fc)
743 {
744 int i;
745 for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
746 if (!flexcop_frontends[i].attach)
747 continue;
748 /* type needs to be set before, because of some workarounds
749 * done based on the probed card type */
750 fc->dev_type = flexcop_frontends[i].type;
751 if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
752 goto fe_found;
753 /* Clean up partially attached frontend */
754 if (fc->fe) {
755 dvb_frontend_detach(fc->fe);
756 fc->fe = NULL;
757 }
758 }
759 fc->dev_type = FC_UNK;
760 err("no frontend driver found for this B2C2/FlexCop adapter");
761 return -ENODEV;
762
763 fe_found:
764 info("found '%s' .", fc->fe->ops.info.name);
765 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
766 err("frontend registration failed!");
767 dvb_frontend_detach(fc->fe);
768 fc->fe = NULL;
769 return -EINVAL;
770 }
771 fc->init_state |= FC_STATE_FE_INIT;
772 return 0;
773 }
774
775 void flexcop_frontend_exit(struct flexcop_device *fc)
776 {
777 if (fc->init_state & FC_STATE_FE_INIT) {
778 dvb_unregister_frontend(fc->fe);
779 dvb_frontend_detach(fc->fe);
780 }
781 fc->init_state &= ~FC_STATE_FE_INIT;
782 }
This page took 0.046907 seconds and 6 git commands to generate.