Merge branch 'fix/hda' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[pandora-kernel.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 }