diff options
Diffstat (limited to 'drivers/media/video/cx88/cx88-dvb.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 1764 |
1 files changed, 1764 insertions, 0 deletions
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c new file mode 100644 index 00000000000..cf3d33ab541 --- /dev/null +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -0,0 +1,1764 @@ | |||
1 | /* | ||
2 | * | ||
3 | * device driver for Conexant 2388x based TV cards | ||
4 | * MPEG Transport Stream (DVB) routines | ||
5 | * | ||
6 | * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> | ||
7 | * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/fs.h> | ||
28 | #include <linux/kthread.h> | ||
29 | #include <linux/file.h> | ||
30 | #include <linux/suspend.h> | ||
31 | |||
32 | #include "cx88.h" | ||
33 | #include "dvb-pll.h" | ||
34 | #include <media/v4l2-common.h> | ||
35 | |||
36 | #include "mt352.h" | ||
37 | #include "mt352_priv.h" | ||
38 | #include "cx88-vp3054-i2c.h" | ||
39 | #include "zl10353.h" | ||
40 | #include "cx22702.h" | ||
41 | #include "or51132.h" | ||
42 | #include "lgdt330x.h" | ||
43 | #include "s5h1409.h" | ||
44 | #include "xc4000.h" | ||
45 | #include "xc5000.h" | ||
46 | #include "nxt200x.h" | ||
47 | #include "cx24123.h" | ||
48 | #include "isl6421.h" | ||
49 | #include "tuner-simple.h" | ||
50 | #include "tda9887.h" | ||
51 | #include "s5h1411.h" | ||
52 | #include "stv0299.h" | ||
53 | #include "z0194a.h" | ||
54 | #include "stv0288.h" | ||
55 | #include "stb6000.h" | ||
56 | #include "cx24116.h" | ||
57 | #include "stv0900.h" | ||
58 | #include "stb6100.h" | ||
59 | #include "stb6100_proc.h" | ||
60 | #include "mb86a16.h" | ||
61 | #include "ds3000.h" | ||
62 | |||
63 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); | ||
64 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | ||
65 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | ||
66 | MODULE_LICENSE("GPL"); | ||
67 | MODULE_VERSION(CX88_VERSION); | ||
68 | |||
69 | static unsigned int debug; | ||
70 | module_param(debug, int, 0644); | ||
71 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); | ||
72 | |||
73 | static unsigned int dvb_buf_tscnt = 32; | ||
74 | module_param(dvb_buf_tscnt, int, 0644); | ||
75 | MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]"); | ||
76 | |||
77 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
78 | |||
79 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | ||
80 | printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) | ||
81 | |||
82 | /* ------------------------------------------------------------------ */ | ||
83 | |||
84 | static int dvb_buf_setup(struct videobuf_queue *q, | ||
85 | unsigned int *count, unsigned int *size) | ||
86 | { | ||
87 | struct cx8802_dev *dev = q->priv_data; | ||
88 | |||
89 | dev->ts_packet_size = 188 * 4; | ||
90 | dev->ts_packet_count = dvb_buf_tscnt; | ||
91 | |||
92 | *size = dev->ts_packet_size * dev->ts_packet_count; | ||
93 | *count = dvb_buf_tscnt; | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int dvb_buf_prepare(struct videobuf_queue *q, | ||
98 | struct videobuf_buffer *vb, enum v4l2_field field) | ||
99 | { | ||
100 | struct cx8802_dev *dev = q->priv_data; | ||
101 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); | ||
102 | } | ||
103 | |||
104 | static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
105 | { | ||
106 | struct cx8802_dev *dev = q->priv_data; | ||
107 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); | ||
108 | } | ||
109 | |||
110 | static void dvb_buf_release(struct videobuf_queue *q, | ||
111 | struct videobuf_buffer *vb) | ||
112 | { | ||
113 | cx88_free_buffer(q, (struct cx88_buffer*)vb); | ||
114 | } | ||
115 | |||
116 | static const struct videobuf_queue_ops dvb_qops = { | ||
117 | .buf_setup = dvb_buf_setup, | ||
118 | .buf_prepare = dvb_buf_prepare, | ||
119 | .buf_queue = dvb_buf_queue, | ||
120 | .buf_release = dvb_buf_release, | ||
121 | }; | ||
122 | |||
123 | /* ------------------------------------------------------------------ */ | ||
124 | |||
125 | static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | ||
126 | { | ||
127 | struct cx8802_dev *dev= fe->dvb->priv; | ||
128 | struct cx8802_driver *drv = NULL; | ||
129 | int ret = 0; | ||
130 | int fe_id; | ||
131 | |||
132 | fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe); | ||
133 | if (!fe_id) { | ||
134 | printk(KERN_ERR "%s() No frontend found\n", __func__); | ||
135 | return -EINVAL; | ||
136 | } | ||
137 | |||
138 | mutex_lock(&dev->core->lock); | ||
139 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); | ||
140 | if (drv) { | ||
141 | if (acquire){ | ||
142 | dev->frontends.active_fe_id = fe_id; | ||
143 | ret = drv->request_acquire(drv); | ||
144 | } else { | ||
145 | ret = drv->request_release(drv); | ||
146 | dev->frontends.active_fe_id = 0; | ||
147 | } | ||
148 | } | ||
149 | mutex_unlock(&dev->core->lock); | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open) | ||
155 | { | ||
156 | struct videobuf_dvb_frontends *f; | ||
157 | struct videobuf_dvb_frontend *fe; | ||
158 | |||
159 | if (!core->dvbdev) | ||
160 | return; | ||
161 | |||
162 | f = &core->dvbdev->frontends; | ||
163 | |||
164 | if (!f) | ||
165 | return; | ||
166 | |||
167 | if (f->gate <= 1) /* undefined or fe0 */ | ||
168 | fe = videobuf_dvb_get_frontend(f, 1); | ||
169 | else | ||
170 | fe = videobuf_dvb_get_frontend(f, f->gate); | ||
171 | |||
172 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) | ||
173 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); | ||
174 | } | ||
175 | |||
176 | /* ------------------------------------------------------------------ */ | ||
177 | |||
178 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) | ||
179 | { | ||
180 | static const u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; | ||
181 | static const u8 reset [] = { RESET, 0x80 }; | ||
182 | static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | ||
183 | static const u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; | ||
184 | static const u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | ||
185 | static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | ||
186 | |||
187 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
188 | udelay(200); | ||
189 | mt352_write(fe, reset, sizeof(reset)); | ||
190 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
191 | |||
192 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
193 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | ||
194 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int dvico_dual_demod_init(struct dvb_frontend *fe) | ||
199 | { | ||
200 | static const u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; | ||
201 | static const u8 reset [] = { RESET, 0x80 }; | ||
202 | static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | ||
203 | static const u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; | ||
204 | static const u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | ||
205 | static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | ||
206 | |||
207 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
208 | udelay(200); | ||
209 | mt352_write(fe, reset, sizeof(reset)); | ||
210 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
211 | |||
212 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
213 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | ||
214 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) | ||
220 | { | ||
221 | static const u8 clock_config [] = { 0x89, 0x38, 0x39 }; | ||
222 | static const u8 reset [] = { 0x50, 0x80 }; | ||
223 | static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; | ||
224 | static const u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, | ||
225 | 0x00, 0xFF, 0x00, 0x40, 0x40 }; | ||
226 | static const u8 dntv_extra[] = { 0xB5, 0x7A }; | ||
227 | static const u8 capt_range_cfg[] = { 0x75, 0x32 }; | ||
228 | |||
229 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
230 | udelay(2000); | ||
231 | mt352_write(fe, reset, sizeof(reset)); | ||
232 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
233 | |||
234 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
235 | udelay(2000); | ||
236 | mt352_write(fe, dntv_extra, sizeof(dntv_extra)); | ||
237 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static const struct mt352_config dvico_fusionhdtv = { | ||
243 | .demod_address = 0x0f, | ||
244 | .demod_init = dvico_fusionhdtv_demod_init, | ||
245 | }; | ||
246 | |||
247 | static const struct mt352_config dntv_live_dvbt_config = { | ||
248 | .demod_address = 0x0f, | ||
249 | .demod_init = dntv_live_dvbt_demod_init, | ||
250 | }; | ||
251 | |||
252 | static const struct mt352_config dvico_fusionhdtv_dual = { | ||
253 | .demod_address = 0x0f, | ||
254 | .demod_init = dvico_dual_demod_init, | ||
255 | }; | ||
256 | |||
257 | static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = { | ||
258 | .demod_address = (0x1e >> 1), | ||
259 | .no_tuner = 1, | ||
260 | .if2 = 45600, | ||
261 | }; | ||
262 | |||
263 | static struct mb86a16_config twinhan_vp1027 = { | ||
264 | .demod_address = 0x08, | ||
265 | }; | ||
266 | |||
267 | #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) | ||
268 | static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) | ||
269 | { | ||
270 | static const u8 clock_config [] = { 0x89, 0x38, 0x38 }; | ||
271 | static const u8 reset [] = { 0x50, 0x80 }; | ||
272 | static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; | ||
273 | static const u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF, | ||
274 | 0x00, 0xFF, 0x00, 0x40, 0x40 }; | ||
275 | static const u8 dntv_extra[] = { 0xB5, 0x7A }; | ||
276 | static const u8 capt_range_cfg[] = { 0x75, 0x32 }; | ||
277 | |||
278 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
279 | udelay(2000); | ||
280 | mt352_write(fe, reset, sizeof(reset)); | ||
281 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
282 | |||
283 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
284 | udelay(2000); | ||
285 | mt352_write(fe, dntv_extra, sizeof(dntv_extra)); | ||
286 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static const struct mt352_config dntv_live_dvbt_pro_config = { | ||
292 | .demod_address = 0x0f, | ||
293 | .no_tuner = 1, | ||
294 | .demod_init = dntv_live_dvbt_pro_demod_init, | ||
295 | }; | ||
296 | #endif | ||
297 | |||
298 | static const struct zl10353_config dvico_fusionhdtv_hybrid = { | ||
299 | .demod_address = 0x0f, | ||
300 | .no_tuner = 1, | ||
301 | }; | ||
302 | |||
303 | static const struct zl10353_config dvico_fusionhdtv_xc3028 = { | ||
304 | .demod_address = 0x0f, | ||
305 | .if2 = 45600, | ||
306 | .no_tuner = 1, | ||
307 | }; | ||
308 | |||
309 | static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = { | ||
310 | .demod_address = 0x0f, | ||
311 | .if2 = 4560, | ||
312 | .no_tuner = 1, | ||
313 | .demod_init = dvico_fusionhdtv_demod_init, | ||
314 | }; | ||
315 | |||
316 | static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { | ||
317 | .demod_address = 0x0f, | ||
318 | }; | ||
319 | |||
320 | static const struct cx22702_config connexant_refboard_config = { | ||
321 | .demod_address = 0x43, | ||
322 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
323 | }; | ||
324 | |||
325 | static const struct cx22702_config hauppauge_hvr_config = { | ||
326 | .demod_address = 0x63, | ||
327 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
328 | }; | ||
329 | |||
330 | static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) | ||
331 | { | ||
332 | struct cx8802_dev *dev= fe->dvb->priv; | ||
333 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static const struct or51132_config pchdtv_hd3000 = { | ||
338 | .demod_address = 0x15, | ||
339 | .set_ts_params = or51132_set_ts_param, | ||
340 | }; | ||
341 | |||
342 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) | ||
343 | { | ||
344 | struct cx8802_dev *dev= fe->dvb->priv; | ||
345 | struct cx88_core *core = dev->core; | ||
346 | |||
347 | dprintk(1, "%s: index = %d\n", __func__, index); | ||
348 | if (index == 0) | ||
349 | cx_clear(MO_GP0_IO, 8); | ||
350 | else | ||
351 | cx_set(MO_GP0_IO, 8); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) | ||
356 | { | ||
357 | struct cx8802_dev *dev= fe->dvb->priv; | ||
358 | if (is_punctured) | ||
359 | dev->ts_gen_cntrl |= 0x04; | ||
360 | else | ||
361 | dev->ts_gen_cntrl &= ~0x04; | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static struct lgdt330x_config fusionhdtv_3_gold = { | ||
366 | .demod_address = 0x0e, | ||
367 | .demod_chip = LGDT3302, | ||
368 | .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ | ||
369 | .set_ts_params = lgdt330x_set_ts_param, | ||
370 | }; | ||
371 | |||
372 | static const struct lgdt330x_config fusionhdtv_5_gold = { | ||
373 | .demod_address = 0x0e, | ||
374 | .demod_chip = LGDT3303, | ||
375 | .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ | ||
376 | .set_ts_params = lgdt330x_set_ts_param, | ||
377 | }; | ||
378 | |||
379 | static const struct lgdt330x_config pchdtv_hd5500 = { | ||
380 | .demod_address = 0x59, | ||
381 | .demod_chip = LGDT3303, | ||
382 | .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ | ||
383 | .set_ts_params = lgdt330x_set_ts_param, | ||
384 | }; | ||
385 | |||
386 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) | ||
387 | { | ||
388 | struct cx8802_dev *dev= fe->dvb->priv; | ||
389 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static const struct nxt200x_config ati_hdtvwonder = { | ||
394 | .demod_address = 0x0a, | ||
395 | .set_ts_params = nxt200x_set_ts_param, | ||
396 | }; | ||
397 | |||
398 | static int cx24123_set_ts_param(struct dvb_frontend* fe, | ||
399 | int is_punctured) | ||
400 | { | ||
401 | struct cx8802_dev *dev= fe->dvb->priv; | ||
402 | dev->ts_gen_cntrl = 0x02; | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, | ||
407 | fe_sec_voltage_t voltage) | ||
408 | { | ||
409 | struct cx8802_dev *dev= fe->dvb->priv; | ||
410 | struct cx88_core *core = dev->core; | ||
411 | |||
412 | if (voltage == SEC_VOLTAGE_OFF) | ||
413 | cx_write(MO_GP0_IO, 0x000006fb); | ||
414 | else | ||
415 | cx_write(MO_GP0_IO, 0x000006f9); | ||
416 | |||
417 | if (core->prev_set_voltage) | ||
418 | return core->prev_set_voltage(fe, voltage); | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, | ||
423 | fe_sec_voltage_t voltage) | ||
424 | { | ||
425 | struct cx8802_dev *dev= fe->dvb->priv; | ||
426 | struct cx88_core *core = dev->core; | ||
427 | |||
428 | if (voltage == SEC_VOLTAGE_OFF) { | ||
429 | dprintk(1,"LNB Voltage OFF\n"); | ||
430 | cx_write(MO_GP0_IO, 0x0000efff); | ||
431 | } | ||
432 | |||
433 | if (core->prev_set_voltage) | ||
434 | return core->prev_set_voltage(fe, voltage); | ||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, | ||
439 | fe_sec_voltage_t voltage) | ||
440 | { | ||
441 | struct cx8802_dev *dev= fe->dvb->priv; | ||
442 | struct cx88_core *core = dev->core; | ||
443 | |||
444 | cx_set(MO_GP0_IO, 0x6040); | ||
445 | switch (voltage) { | ||
446 | case SEC_VOLTAGE_13: | ||
447 | cx_clear(MO_GP0_IO, 0x20); | ||
448 | break; | ||
449 | case SEC_VOLTAGE_18: | ||
450 | cx_set(MO_GP0_IO, 0x20); | ||
451 | break; | ||
452 | case SEC_VOLTAGE_OFF: | ||
453 | cx_clear(MO_GP0_IO, 0x20); | ||
454 | break; | ||
455 | } | ||
456 | |||
457 | if (core->prev_set_voltage) | ||
458 | return core->prev_set_voltage(fe, voltage); | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static int vp1027_set_voltage(struct dvb_frontend *fe, | ||
463 | fe_sec_voltage_t voltage) | ||
464 | { | ||
465 | struct cx8802_dev *dev = fe->dvb->priv; | ||
466 | struct cx88_core *core = dev->core; | ||
467 | |||
468 | switch (voltage) { | ||
469 | case SEC_VOLTAGE_13: | ||
470 | dprintk(1, "LNB SEC Voltage=13\n"); | ||
471 | cx_write(MO_GP0_IO, 0x00001220); | ||
472 | break; | ||
473 | case SEC_VOLTAGE_18: | ||
474 | dprintk(1, "LNB SEC Voltage=18\n"); | ||
475 | cx_write(MO_GP0_IO, 0x00001222); | ||
476 | break; | ||
477 | case SEC_VOLTAGE_OFF: | ||
478 | dprintk(1, "LNB Voltage OFF\n"); | ||
479 | cx_write(MO_GP0_IO, 0x00001230); | ||
480 | break; | ||
481 | } | ||
482 | |||
483 | if (core->prev_set_voltage) | ||
484 | return core->prev_set_voltage(fe, voltage); | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static const struct cx24123_config geniatech_dvbs_config = { | ||
489 | .demod_address = 0x55, | ||
490 | .set_ts_params = cx24123_set_ts_param, | ||
491 | }; | ||
492 | |||
493 | static const struct cx24123_config hauppauge_novas_config = { | ||
494 | .demod_address = 0x55, | ||
495 | .set_ts_params = cx24123_set_ts_param, | ||
496 | }; | ||
497 | |||
498 | static const struct cx24123_config kworld_dvbs_100_config = { | ||
499 | .demod_address = 0x15, | ||
500 | .set_ts_params = cx24123_set_ts_param, | ||
501 | .lnb_polarity = 1, | ||
502 | }; | ||
503 | |||
504 | static const struct s5h1409_config pinnacle_pctv_hd_800i_config = { | ||
505 | .demod_address = 0x32 >> 1, | ||
506 | .output_mode = S5H1409_PARALLEL_OUTPUT, | ||
507 | .gpio = S5H1409_GPIO_ON, | ||
508 | .qam_if = 44000, | ||
509 | .inversion = S5H1409_INVERSION_OFF, | ||
510 | .status_mode = S5H1409_DEMODLOCKING, | ||
511 | .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, | ||
512 | }; | ||
513 | |||
514 | static const struct s5h1409_config dvico_hdtv5_pci_nano_config = { | ||
515 | .demod_address = 0x32 >> 1, | ||
516 | .output_mode = S5H1409_SERIAL_OUTPUT, | ||
517 | .gpio = S5H1409_GPIO_OFF, | ||
518 | .inversion = S5H1409_INVERSION_OFF, | ||
519 | .status_mode = S5H1409_DEMODLOCKING, | ||
520 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, | ||
521 | }; | ||
522 | |||
523 | static const struct s5h1409_config kworld_atsc_120_config = { | ||
524 | .demod_address = 0x32 >> 1, | ||
525 | .output_mode = S5H1409_SERIAL_OUTPUT, | ||
526 | .gpio = S5H1409_GPIO_OFF, | ||
527 | .inversion = S5H1409_INVERSION_OFF, | ||
528 | .status_mode = S5H1409_DEMODLOCKING, | ||
529 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, | ||
530 | }; | ||
531 | |||
532 | static const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { | ||
533 | .i2c_address = 0x64, | ||
534 | .if_khz = 5380, | ||
535 | }; | ||
536 | |||
537 | static const struct zl10353_config cx88_pinnacle_hybrid_pctv = { | ||
538 | .demod_address = (0x1e >> 1), | ||
539 | .no_tuner = 1, | ||
540 | .if2 = 45600, | ||
541 | }; | ||
542 | |||
543 | static const struct zl10353_config cx88_geniatech_x8000_mt = { | ||
544 | .demod_address = (0x1e >> 1), | ||
545 | .no_tuner = 1, | ||
546 | .disable_i2c_gate_ctrl = 1, | ||
547 | }; | ||
548 | |||
549 | static const struct s5h1411_config dvico_fusionhdtv7_config = { | ||
550 | .output_mode = S5H1411_SERIAL_OUTPUT, | ||
551 | .gpio = S5H1411_GPIO_ON, | ||
552 | .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, | ||
553 | .qam_if = S5H1411_IF_44000, | ||
554 | .vsb_if = S5H1411_IF_44000, | ||
555 | .inversion = S5H1411_INVERSION_OFF, | ||
556 | .status_mode = S5H1411_DEMODLOCKING | ||
557 | }; | ||
558 | |||
559 | static const struct xc5000_config dvico_fusionhdtv7_tuner_config = { | ||
560 | .i2c_address = 0xc2 >> 1, | ||
561 | .if_khz = 5380, | ||
562 | }; | ||
563 | |||
564 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | ||
565 | { | ||
566 | struct dvb_frontend *fe; | ||
567 | struct videobuf_dvb_frontend *fe0 = NULL; | ||
568 | struct xc2028_ctrl ctl; | ||
569 | struct xc2028_config cfg = { | ||
570 | .i2c_adap = &dev->core->i2c_adap, | ||
571 | .i2c_addr = addr, | ||
572 | .ctrl = &ctl, | ||
573 | }; | ||
574 | |||
575 | /* Get the first frontend */ | ||
576 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | ||
577 | if (!fe0) | ||
578 | return -EINVAL; | ||
579 | |||
580 | if (!fe0->dvb.frontend) { | ||
581 | printk(KERN_ERR "%s/2: dvb frontend not attached. " | ||
582 | "Can't attach xc3028\n", | ||
583 | dev->core->name); | ||
584 | return -EINVAL; | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * Some xc3028 devices may be hidden by an I2C gate. This is known | ||
589 | * to happen with some s5h1409-based devices. | ||
590 | * Now that I2C gate is open, sets up xc3028 configuration | ||
591 | */ | ||
592 | cx88_setup_xc3028(dev->core, &ctl); | ||
593 | |||
594 | fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); | ||
595 | if (!fe) { | ||
596 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", | ||
597 | dev->core->name); | ||
598 | dvb_frontend_detach(fe0->dvb.frontend); | ||
599 | dvb_unregister_frontend(fe0->dvb.frontend); | ||
600 | fe0->dvb.frontend = NULL; | ||
601 | return -EINVAL; | ||
602 | } | ||
603 | |||
604 | printk(KERN_INFO "%s/2: xc3028 attached\n", | ||
605 | dev->core->name); | ||
606 | |||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg) | ||
611 | { | ||
612 | struct dvb_frontend *fe; | ||
613 | struct videobuf_dvb_frontend *fe0 = NULL; | ||
614 | |||
615 | /* Get the first frontend */ | ||
616 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | ||
617 | if (!fe0) | ||
618 | return -EINVAL; | ||
619 | |||
620 | if (!fe0->dvb.frontend) { | ||
621 | printk(KERN_ERR "%s/2: dvb frontend not attached. " | ||
622 | "Can't attach xc4000\n", | ||
623 | dev->core->name); | ||
624 | return -EINVAL; | ||
625 | } | ||
626 | |||
627 | fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap, | ||
628 | cfg); | ||
629 | if (!fe) { | ||
630 | printk(KERN_ERR "%s/2: xc4000 attach failed\n", | ||
631 | dev->core->name); | ||
632 | dvb_frontend_detach(fe0->dvb.frontend); | ||
633 | dvb_unregister_frontend(fe0->dvb.frontend); | ||
634 | fe0->dvb.frontend = NULL; | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | |||
638 | printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name); | ||
639 | |||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | static int cx24116_set_ts_param(struct dvb_frontend *fe, | ||
644 | int is_punctured) | ||
645 | { | ||
646 | struct cx8802_dev *dev = fe->dvb->priv; | ||
647 | dev->ts_gen_cntrl = 0x2; | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static int stv0900_set_ts_param(struct dvb_frontend *fe, | ||
653 | int is_punctured) | ||
654 | { | ||
655 | struct cx8802_dev *dev = fe->dvb->priv; | ||
656 | dev->ts_gen_cntrl = 0; | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static int cx24116_reset_device(struct dvb_frontend *fe) | ||
662 | { | ||
663 | struct cx8802_dev *dev = fe->dvb->priv; | ||
664 | struct cx88_core *core = dev->core; | ||
665 | |||
666 | /* Reset the part */ | ||
667 | /* Put the cx24116 into reset */ | ||
668 | cx_write(MO_SRST_IO, 0); | ||
669 | msleep(10); | ||
670 | /* Take the cx24116 out of reset */ | ||
671 | cx_write(MO_SRST_IO, 1); | ||
672 | msleep(10); | ||
673 | |||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | static const struct cx24116_config hauppauge_hvr4000_config = { | ||
678 | .demod_address = 0x05, | ||
679 | .set_ts_params = cx24116_set_ts_param, | ||
680 | .reset_device = cx24116_reset_device, | ||
681 | }; | ||
682 | |||
683 | static const struct cx24116_config tevii_s460_config = { | ||
684 | .demod_address = 0x55, | ||
685 | .set_ts_params = cx24116_set_ts_param, | ||
686 | .reset_device = cx24116_reset_device, | ||
687 | }; | ||
688 | |||
689 | static int ds3000_set_ts_param(struct dvb_frontend *fe, | ||
690 | int is_punctured) | ||
691 | { | ||
692 | struct cx8802_dev *dev = fe->dvb->priv; | ||
693 | dev->ts_gen_cntrl = 4; | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static struct ds3000_config tevii_ds3000_config = { | ||
699 | .demod_address = 0x68, | ||
700 | .set_ts_params = ds3000_set_ts_param, | ||
701 | }; | ||
702 | |||
703 | static const struct stv0900_config prof_7301_stv0900_config = { | ||
704 | .demod_address = 0x6a, | ||
705 | /* demod_mode = 0,*/ | ||
706 | .xtal = 27000000, | ||
707 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | ||
708 | .diseqc_mode = 2,/* 2/3 PWM */ | ||
709 | .tun1_maddress = 0,/* 0x60 */ | ||
710 | .tun1_adc = 0,/* 2 Vpp */ | ||
711 | .path1_mode = 3, | ||
712 | .set_ts_params = stv0900_set_ts_param, | ||
713 | }; | ||
714 | |||
715 | static const struct stb6100_config prof_7301_stb6100_config = { | ||
716 | .tuner_address = 0x60, | ||
717 | .refclock = 27000000, | ||
718 | }; | ||
719 | |||
720 | static const struct stv0299_config tevii_tuner_sharp_config = { | ||
721 | .demod_address = 0x68, | ||
722 | .inittab = sharp_z0194a_inittab, | ||
723 | .mclk = 88000000UL, | ||
724 | .invert = 1, | ||
725 | .skip_reinit = 0, | ||
726 | .lock_output = 1, | ||
727 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
728 | .min_delay_ms = 100, | ||
729 | .set_symbol_rate = sharp_z0194a_set_symbol_rate, | ||
730 | .set_ts_params = cx24116_set_ts_param, | ||
731 | }; | ||
732 | |||
733 | static const struct stv0288_config tevii_tuner_earda_config = { | ||
734 | .demod_address = 0x68, | ||
735 | .min_delay_ms = 100, | ||
736 | .set_ts_params = cx24116_set_ts_param, | ||
737 | }; | ||
738 | |||
739 | static int cx8802_alloc_frontends(struct cx8802_dev *dev) | ||
740 | { | ||
741 | struct cx88_core *core = dev->core; | ||
742 | struct videobuf_dvb_frontend *fe = NULL; | ||
743 | int i; | ||
744 | |||
745 | mutex_init(&dev->frontends.lock); | ||
746 | INIT_LIST_HEAD(&dev->frontends.felist); | ||
747 | |||
748 | if (!core->board.num_frontends) | ||
749 | return -ENODEV; | ||
750 | |||
751 | printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, | ||
752 | core->board.num_frontends); | ||
753 | for (i = 1; i <= core->board.num_frontends; i++) { | ||
754 | fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); | ||
755 | if (!fe) { | ||
756 | printk(KERN_ERR "%s() failed to alloc\n", __func__); | ||
757 | videobuf_dvb_dealloc_frontends(&dev->frontends); | ||
758 | return -ENOMEM; | ||
759 | } | ||
760 | } | ||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | |||
765 | |||
766 | static const u8 samsung_smt_7020_inittab[] = { | ||
767 | 0x01, 0x15, | ||
768 | 0x02, 0x00, | ||
769 | 0x03, 0x00, | ||
770 | 0x04, 0x7D, | ||
771 | 0x05, 0x0F, | ||
772 | 0x06, 0x02, | ||
773 | 0x07, 0x00, | ||
774 | 0x08, 0x60, | ||
775 | |||
776 | 0x0A, 0xC2, | ||
777 | 0x0B, 0x00, | ||
778 | 0x0C, 0x01, | ||
779 | 0x0D, 0x81, | ||
780 | 0x0E, 0x44, | ||
781 | 0x0F, 0x09, | ||
782 | 0x10, 0x3C, | ||
783 | 0x11, 0x84, | ||
784 | 0x12, 0xDA, | ||
785 | 0x13, 0x99, | ||
786 | 0x14, 0x8D, | ||
787 | 0x15, 0xCE, | ||
788 | 0x16, 0xE8, | ||
789 | 0x17, 0x43, | ||
790 | 0x18, 0x1C, | ||
791 | 0x19, 0x1B, | ||
792 | 0x1A, 0x1D, | ||
793 | |||
794 | 0x1C, 0x12, | ||
795 | 0x1D, 0x00, | ||
796 | 0x1E, 0x00, | ||
797 | 0x1F, 0x00, | ||
798 | 0x20, 0x00, | ||
799 | 0x21, 0x00, | ||
800 | 0x22, 0x00, | ||
801 | 0x23, 0x00, | ||
802 | |||
803 | 0x28, 0x02, | ||
804 | 0x29, 0x28, | ||
805 | 0x2A, 0x14, | ||
806 | 0x2B, 0x0F, | ||
807 | 0x2C, 0x09, | ||
808 | 0x2D, 0x05, | ||
809 | |||
810 | 0x31, 0x1F, | ||
811 | 0x32, 0x19, | ||
812 | 0x33, 0xFC, | ||
813 | 0x34, 0x13, | ||
814 | 0xff, 0xff, | ||
815 | }; | ||
816 | |||
817 | |||
818 | static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe, | ||
819 | struct dvb_frontend_parameters *params) | ||
820 | { | ||
821 | struct cx8802_dev *dev = fe->dvb->priv; | ||
822 | u8 buf[4]; | ||
823 | u32 div; | ||
824 | struct i2c_msg msg = { | ||
825 | .addr = 0x61, | ||
826 | .flags = 0, | ||
827 | .buf = buf, | ||
828 | .len = sizeof(buf) }; | ||
829 | |||
830 | div = params->frequency / 125; | ||
831 | |||
832 | buf[0] = (div >> 8) & 0x7f; | ||
833 | buf[1] = div & 0xff; | ||
834 | buf[2] = 0x84; /* 0xC4 */ | ||
835 | buf[3] = 0x00; | ||
836 | |||
837 | if (params->frequency < 1500000) | ||
838 | buf[3] |= 0x10; | ||
839 | |||
840 | if (fe->ops.i2c_gate_ctrl) | ||
841 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
842 | |||
843 | if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1) | ||
844 | return -EIO; | ||
845 | |||
846 | return 0; | ||
847 | } | ||
848 | |||
849 | static int samsung_smt_7020_set_tone(struct dvb_frontend *fe, | ||
850 | fe_sec_tone_mode_t tone) | ||
851 | { | ||
852 | struct cx8802_dev *dev = fe->dvb->priv; | ||
853 | struct cx88_core *core = dev->core; | ||
854 | |||
855 | cx_set(MO_GP0_IO, 0x0800); | ||
856 | |||
857 | switch (tone) { | ||
858 | case SEC_TONE_ON: | ||
859 | cx_set(MO_GP0_IO, 0x08); | ||
860 | break; | ||
861 | case SEC_TONE_OFF: | ||
862 | cx_clear(MO_GP0_IO, 0x08); | ||
863 | break; | ||
864 | default: | ||
865 | return -EINVAL; | ||
866 | } | ||
867 | |||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe, | ||
872 | fe_sec_voltage_t voltage) | ||
873 | { | ||
874 | struct cx8802_dev *dev = fe->dvb->priv; | ||
875 | struct cx88_core *core = dev->core; | ||
876 | |||
877 | u8 data; | ||
878 | struct i2c_msg msg = { | ||
879 | .addr = 8, | ||
880 | .flags = 0, | ||
881 | .buf = &data, | ||
882 | .len = sizeof(data) }; | ||
883 | |||
884 | cx_set(MO_GP0_IO, 0x8000); | ||
885 | |||
886 | switch (voltage) { | ||
887 | case SEC_VOLTAGE_OFF: | ||
888 | break; | ||
889 | case SEC_VOLTAGE_13: | ||
890 | data = ISL6421_EN1 | ISL6421_LLC1; | ||
891 | cx_clear(MO_GP0_IO, 0x80); | ||
892 | break; | ||
893 | case SEC_VOLTAGE_18: | ||
894 | data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1; | ||
895 | cx_clear(MO_GP0_IO, 0x80); | ||
896 | break; | ||
897 | default: | ||
898 | return -EINVAL; | ||
899 | }; | ||
900 | |||
901 | return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; | ||
902 | } | ||
903 | |||
904 | static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe, | ||
905 | u32 srate, u32 ratio) | ||
906 | { | ||
907 | u8 aclk = 0; | ||
908 | u8 bclk = 0; | ||
909 | |||
910 | if (srate < 1500000) { | ||
911 | aclk = 0xb7; | ||
912 | bclk = 0x47; | ||
913 | } else if (srate < 3000000) { | ||
914 | aclk = 0xb7; | ||
915 | bclk = 0x4b; | ||
916 | } else if (srate < 7000000) { | ||
917 | aclk = 0xb7; | ||
918 | bclk = 0x4f; | ||
919 | } else if (srate < 14000000) { | ||
920 | aclk = 0xb7; | ||
921 | bclk = 0x53; | ||
922 | } else if (srate < 30000000) { | ||
923 | aclk = 0xb6; | ||
924 | bclk = 0x53; | ||
925 | } else if (srate < 45000000) { | ||
926 | aclk = 0xb4; | ||
927 | bclk = 0x51; | ||
928 | } | ||
929 | |||
930 | stv0299_writereg(fe, 0x13, aclk); | ||
931 | stv0299_writereg(fe, 0x14, bclk); | ||
932 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); | ||
933 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); | ||
934 | stv0299_writereg(fe, 0x21, ratio & 0xf0); | ||
935 | |||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | |||
940 | static const struct stv0299_config samsung_stv0299_config = { | ||
941 | .demod_address = 0x68, | ||
942 | .inittab = samsung_smt_7020_inittab, | ||
943 | .mclk = 88000000UL, | ||
944 | .invert = 0, | ||
945 | .skip_reinit = 0, | ||
946 | .lock_output = STV0299_LOCKOUTPUT_LK, | ||
947 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
948 | .min_delay_ms = 100, | ||
949 | .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate, | ||
950 | }; | ||
951 | |||
952 | static int dvb_register(struct cx8802_dev *dev) | ||
953 | { | ||
954 | struct cx88_core *core = dev->core; | ||
955 | struct videobuf_dvb_frontend *fe0, *fe1 = NULL; | ||
956 | int mfe_shared = 0; /* bus not shared by default */ | ||
957 | |||
958 | if (0 != core->i2c_rc) { | ||
959 | printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); | ||
960 | goto frontend_detach; | ||
961 | } | ||
962 | |||
963 | /* Get the first frontend */ | ||
964 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | ||
965 | if (!fe0) | ||
966 | goto frontend_detach; | ||
967 | |||
968 | /* multi-frontend gate control is undefined or defaults to fe0 */ | ||
969 | dev->frontends.gate = 0; | ||
970 | |||
971 | /* Sets the gate control callback to be used by i2c command calls */ | ||
972 | core->gate_ctrl = cx88_dvb_gate_ctrl; | ||
973 | |||
974 | /* init frontend(s) */ | ||
975 | switch (core->boardnr) { | ||
976 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | ||
977 | fe0->dvb.frontend = dvb_attach(cx22702_attach, | ||
978 | &connexant_refboard_config, | ||
979 | &core->i2c_adap); | ||
980 | if (fe0->dvb.frontend != NULL) { | ||
981 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, | ||
982 | 0x61, &core->i2c_adap, | ||
983 | DVB_PLL_THOMSON_DTT759X)) | ||
984 | goto frontend_detach; | ||
985 | } | ||
986 | break; | ||
987 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | ||
988 | case CX88_BOARD_CONEXANT_DVB_T1: | ||
989 | case CX88_BOARD_KWORLD_DVB_T_CX22702: | ||
990 | case CX88_BOARD_WINFAST_DTV1000: | ||
991 | fe0->dvb.frontend = dvb_attach(cx22702_attach, | ||
992 | &connexant_refboard_config, | ||
993 | &core->i2c_adap); | ||
994 | if (fe0->dvb.frontend != NULL) { | ||
995 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, | ||
996 | 0x60, &core->i2c_adap, | ||
997 | DVB_PLL_THOMSON_DTT7579)) | ||
998 | goto frontend_detach; | ||
999 | } | ||
1000 | break; | ||
1001 | case CX88_BOARD_WINFAST_DTV2000H: | ||
1002 | case CX88_BOARD_WINFAST_DTV2000H_J: | ||
1003 | case CX88_BOARD_HAUPPAUGE_HVR1100: | ||
1004 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | ||
1005 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1006 | fe0->dvb.frontend = dvb_attach(cx22702_attach, | ||
1007 | &hauppauge_hvr_config, | ||
1008 | &core->i2c_adap); | ||
1009 | if (fe0->dvb.frontend != NULL) { | ||
1010 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1011 | &core->i2c_adap, 0x61, | ||
1012 | TUNER_PHILIPS_FMD1216ME_MK3)) | ||
1013 | goto frontend_detach; | ||
1014 | } | ||
1015 | break; | ||
1016 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
1017 | /* MFE frontend 1 */ | ||
1018 | mfe_shared = 1; | ||
1019 | dev->frontends.gate = 2; | ||
1020 | /* DVB-S init */ | ||
1021 | fe0->dvb.frontend = dvb_attach(cx24123_attach, | ||
1022 | &hauppauge_novas_config, | ||
1023 | &dev->core->i2c_adap); | ||
1024 | if (fe0->dvb.frontend) { | ||
1025 | if (!dvb_attach(isl6421_attach, | ||
1026 | fe0->dvb.frontend, | ||
1027 | &dev->core->i2c_adap, | ||
1028 | 0x08, ISL6421_DCL, 0x00)) | ||
1029 | goto frontend_detach; | ||
1030 | } | ||
1031 | /* MFE frontend 2 */ | ||
1032 | fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); | ||
1033 | if (!fe1) | ||
1034 | goto frontend_detach; | ||
1035 | /* DVB-T init */ | ||
1036 | fe1->dvb.frontend = dvb_attach(cx22702_attach, | ||
1037 | &hauppauge_hvr_config, | ||
1038 | &dev->core->i2c_adap); | ||
1039 | if (fe1->dvb.frontend) { | ||
1040 | fe1->dvb.frontend->id = 1; | ||
1041 | if (!dvb_attach(simple_tuner_attach, | ||
1042 | fe1->dvb.frontend, | ||
1043 | &dev->core->i2c_adap, | ||
1044 | 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) | ||
1045 | goto frontend_detach; | ||
1046 | } | ||
1047 | break; | ||
1048 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | ||
1049 | fe0->dvb.frontend = dvb_attach(mt352_attach, | ||
1050 | &dvico_fusionhdtv, | ||
1051 | &core->i2c_adap); | ||
1052 | if (fe0->dvb.frontend != NULL) { | ||
1053 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, | ||
1054 | 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) | ||
1055 | goto frontend_detach; | ||
1056 | break; | ||
1057 | } | ||
1058 | /* ZL10353 replaces MT352 on later cards */ | ||
1059 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1060 | &dvico_fusionhdtv_plus_v1_1, | ||
1061 | &core->i2c_adap); | ||
1062 | if (fe0->dvb.frontend != NULL) { | ||
1063 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, | ||
1064 | 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) | ||
1065 | goto frontend_detach; | ||
1066 | } | ||
1067 | break; | ||
1068 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: | ||
1069 | /* The tin box says DEE1601, but it seems to be DTT7579 | ||
1070 | * compatible, with a slightly different MT352 AGC gain. */ | ||
1071 | fe0->dvb.frontend = dvb_attach(mt352_attach, | ||
1072 | &dvico_fusionhdtv_dual, | ||
1073 | &core->i2c_adap); | ||
1074 | if (fe0->dvb.frontend != NULL) { | ||
1075 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, | ||
1076 | 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) | ||
1077 | goto frontend_detach; | ||
1078 | break; | ||
1079 | } | ||
1080 | /* ZL10353 replaces MT352 on later cards */ | ||
1081 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1082 | &dvico_fusionhdtv_plus_v1_1, | ||
1083 | &core->i2c_adap); | ||
1084 | if (fe0->dvb.frontend != NULL) { | ||
1085 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, | ||
1086 | 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) | ||
1087 | goto frontend_detach; | ||
1088 | } | ||
1089 | break; | ||
1090 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: | ||
1091 | fe0->dvb.frontend = dvb_attach(mt352_attach, | ||
1092 | &dvico_fusionhdtv, | ||
1093 | &core->i2c_adap); | ||
1094 | if (fe0->dvb.frontend != NULL) { | ||
1095 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, | ||
1096 | 0x61, NULL, DVB_PLL_LG_Z201)) | ||
1097 | goto frontend_detach; | ||
1098 | } | ||
1099 | break; | ||
1100 | case CX88_BOARD_KWORLD_DVB_T: | ||
1101 | case CX88_BOARD_DNTV_LIVE_DVB_T: | ||
1102 | case CX88_BOARD_ADSTECH_DVB_T_PCI: | ||
1103 | fe0->dvb.frontend = dvb_attach(mt352_attach, | ||
1104 | &dntv_live_dvbt_config, | ||
1105 | &core->i2c_adap); | ||
1106 | if (fe0->dvb.frontend != NULL) { | ||
1107 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, | ||
1108 | 0x61, NULL, DVB_PLL_UNKNOWN_1)) | ||
1109 | goto frontend_detach; | ||
1110 | } | ||
1111 | break; | ||
1112 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | ||
1113 | #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) | ||
1114 | /* MT352 is on a secondary I2C bus made from some GPIO lines */ | ||
1115 | fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, | ||
1116 | &dev->vp3054->adap); | ||
1117 | if (fe0->dvb.frontend != NULL) { | ||
1118 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1119 | &core->i2c_adap, 0x61, | ||
1120 | TUNER_PHILIPS_FMD1216ME_MK3)) | ||
1121 | goto frontend_detach; | ||
1122 | } | ||
1123 | #else | ||
1124 | printk(KERN_ERR "%s/2: built without vp3054 support\n", | ||
1125 | core->name); | ||
1126 | #endif | ||
1127 | break; | ||
1128 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | ||
1129 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1130 | &dvico_fusionhdtv_hybrid, | ||
1131 | &core->i2c_adap); | ||
1132 | if (fe0->dvb.frontend != NULL) { | ||
1133 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1134 | &core->i2c_adap, 0x61, | ||
1135 | TUNER_THOMSON_FE6600)) | ||
1136 | goto frontend_detach; | ||
1137 | } | ||
1138 | break; | ||
1139 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | ||
1140 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1141 | &dvico_fusionhdtv_xc3028, | ||
1142 | &core->i2c_adap); | ||
1143 | if (fe0->dvb.frontend == NULL) | ||
1144 | fe0->dvb.frontend = dvb_attach(mt352_attach, | ||
1145 | &dvico_fusionhdtv_mt352_xc3028, | ||
1146 | &core->i2c_adap); | ||
1147 | /* | ||
1148 | * On this board, the demod provides the I2C bus pullup. | ||
1149 | * We must not permit gate_ctrl to be performed, or | ||
1150 | * the xc3028 cannot communicate on the bus. | ||
1151 | */ | ||
1152 | if (fe0->dvb.frontend) | ||
1153 | fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; | ||
1154 | if (attach_xc3028(0x61, dev) < 0) | ||
1155 | goto frontend_detach; | ||
1156 | break; | ||
1157 | case CX88_BOARD_PCHDTV_HD3000: | ||
1158 | fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, | ||
1159 | &core->i2c_adap); | ||
1160 | if (fe0->dvb.frontend != NULL) { | ||
1161 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1162 | &core->i2c_adap, 0x61, | ||
1163 | TUNER_THOMSON_DTT761X)) | ||
1164 | goto frontend_detach; | ||
1165 | } | ||
1166 | break; | ||
1167 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: | ||
1168 | dev->ts_gen_cntrl = 0x08; | ||
1169 | |||
1170 | /* Do a hardware reset of chip before using it. */ | ||
1171 | cx_clear(MO_GP0_IO, 1); | ||
1172 | mdelay(100); | ||
1173 | cx_set(MO_GP0_IO, 1); | ||
1174 | mdelay(200); | ||
1175 | |||
1176 | /* Select RF connector callback */ | ||
1177 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; | ||
1178 | fe0->dvb.frontend = dvb_attach(lgdt330x_attach, | ||
1179 | &fusionhdtv_3_gold, | ||
1180 | &core->i2c_adap); | ||
1181 | if (fe0->dvb.frontend != NULL) { | ||
1182 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1183 | &core->i2c_adap, 0x61, | ||
1184 | TUNER_MICROTUNE_4042FI5)) | ||
1185 | goto frontend_detach; | ||
1186 | } | ||
1187 | break; | ||
1188 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: | ||
1189 | dev->ts_gen_cntrl = 0x08; | ||
1190 | |||
1191 | /* Do a hardware reset of chip before using it. */ | ||
1192 | cx_clear(MO_GP0_IO, 1); | ||
1193 | mdelay(100); | ||
1194 | cx_set(MO_GP0_IO, 9); | ||
1195 | mdelay(200); | ||
1196 | fe0->dvb.frontend = dvb_attach(lgdt330x_attach, | ||
1197 | &fusionhdtv_3_gold, | ||
1198 | &core->i2c_adap); | ||
1199 | if (fe0->dvb.frontend != NULL) { | ||
1200 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1201 | &core->i2c_adap, 0x61, | ||
1202 | TUNER_THOMSON_DTT761X)) | ||
1203 | goto frontend_detach; | ||
1204 | } | ||
1205 | break; | ||
1206 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: | ||
1207 | dev->ts_gen_cntrl = 0x08; | ||
1208 | |||
1209 | /* Do a hardware reset of chip before using it. */ | ||
1210 | cx_clear(MO_GP0_IO, 1); | ||
1211 | mdelay(100); | ||
1212 | cx_set(MO_GP0_IO, 1); | ||
1213 | mdelay(200); | ||
1214 | fe0->dvb.frontend = dvb_attach(lgdt330x_attach, | ||
1215 | &fusionhdtv_5_gold, | ||
1216 | &core->i2c_adap); | ||
1217 | if (fe0->dvb.frontend != NULL) { | ||
1218 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1219 | &core->i2c_adap, 0x61, | ||
1220 | TUNER_LG_TDVS_H06XF)) | ||
1221 | goto frontend_detach; | ||
1222 | if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, | ||
1223 | &core->i2c_adap, 0x43)) | ||
1224 | goto frontend_detach; | ||
1225 | } | ||
1226 | break; | ||
1227 | case CX88_BOARD_PCHDTV_HD5500: | ||
1228 | dev->ts_gen_cntrl = 0x08; | ||
1229 | |||
1230 | /* Do a hardware reset of chip before using it. */ | ||
1231 | cx_clear(MO_GP0_IO, 1); | ||
1232 | mdelay(100); | ||
1233 | cx_set(MO_GP0_IO, 1); | ||
1234 | mdelay(200); | ||
1235 | fe0->dvb.frontend = dvb_attach(lgdt330x_attach, | ||
1236 | &pchdtv_hd5500, | ||
1237 | &core->i2c_adap); | ||
1238 | if (fe0->dvb.frontend != NULL) { | ||
1239 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1240 | &core->i2c_adap, 0x61, | ||
1241 | TUNER_LG_TDVS_H06XF)) | ||
1242 | goto frontend_detach; | ||
1243 | if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, | ||
1244 | &core->i2c_adap, 0x43)) | ||
1245 | goto frontend_detach; | ||
1246 | } | ||
1247 | break; | ||
1248 | case CX88_BOARD_ATI_HDTVWONDER: | ||
1249 | fe0->dvb.frontend = dvb_attach(nxt200x_attach, | ||
1250 | &ati_hdtvwonder, | ||
1251 | &core->i2c_adap); | ||
1252 | if (fe0->dvb.frontend != NULL) { | ||
1253 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1254 | &core->i2c_adap, 0x61, | ||
1255 | TUNER_PHILIPS_TUV1236D)) | ||
1256 | goto frontend_detach; | ||
1257 | } | ||
1258 | break; | ||
1259 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | ||
1260 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | ||
1261 | fe0->dvb.frontend = dvb_attach(cx24123_attach, | ||
1262 | &hauppauge_novas_config, | ||
1263 | &core->i2c_adap); | ||
1264 | if (fe0->dvb.frontend) { | ||
1265 | if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, | ||
1266 | &core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) | ||
1267 | goto frontend_detach; | ||
1268 | } | ||
1269 | break; | ||
1270 | case CX88_BOARD_KWORLD_DVBS_100: | ||
1271 | fe0->dvb.frontend = dvb_attach(cx24123_attach, | ||
1272 | &kworld_dvbs_100_config, | ||
1273 | &core->i2c_adap); | ||
1274 | if (fe0->dvb.frontend) { | ||
1275 | core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; | ||
1276 | fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; | ||
1277 | } | ||
1278 | break; | ||
1279 | case CX88_BOARD_GENIATECH_DVBS: | ||
1280 | fe0->dvb.frontend = dvb_attach(cx24123_attach, | ||
1281 | &geniatech_dvbs_config, | ||
1282 | &core->i2c_adap); | ||
1283 | if (fe0->dvb.frontend) { | ||
1284 | core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; | ||
1285 | fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; | ||
1286 | } | ||
1287 | break; | ||
1288 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: | ||
1289 | fe0->dvb.frontend = dvb_attach(s5h1409_attach, | ||
1290 | &pinnacle_pctv_hd_800i_config, | ||
1291 | &core->i2c_adap); | ||
1292 | if (fe0->dvb.frontend != NULL) { | ||
1293 | if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, | ||
1294 | &core->i2c_adap, | ||
1295 | &pinnacle_pctv_hd_800i_tuner_config)) | ||
1296 | goto frontend_detach; | ||
1297 | } | ||
1298 | break; | ||
1299 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | ||
1300 | fe0->dvb.frontend = dvb_attach(s5h1409_attach, | ||
1301 | &dvico_hdtv5_pci_nano_config, | ||
1302 | &core->i2c_adap); | ||
1303 | if (fe0->dvb.frontend != NULL) { | ||
1304 | struct dvb_frontend *fe; | ||
1305 | struct xc2028_config cfg = { | ||
1306 | .i2c_adap = &core->i2c_adap, | ||
1307 | .i2c_addr = 0x61, | ||
1308 | }; | ||
1309 | static struct xc2028_ctrl ctl = { | ||
1310 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
1311 | .max_len = 64, | ||
1312 | .scode_table = XC3028_FE_OREN538, | ||
1313 | }; | ||
1314 | |||
1315 | fe = dvb_attach(xc2028_attach, | ||
1316 | fe0->dvb.frontend, &cfg); | ||
1317 | if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) | ||
1318 | fe->ops.tuner_ops.set_config(fe, &ctl); | ||
1319 | } | ||
1320 | break; | ||
1321 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: | ||
1322 | case CX88_BOARD_WINFAST_DTV1800H: | ||
1323 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1324 | &cx88_pinnacle_hybrid_pctv, | ||
1325 | &core->i2c_adap); | ||
1326 | if (fe0->dvb.frontend) { | ||
1327 | fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; | ||
1328 | if (attach_xc3028(0x61, dev) < 0) | ||
1329 | goto frontend_detach; | ||
1330 | } | ||
1331 | break; | ||
1332 | case CX88_BOARD_WINFAST_DTV1800H_XC4000: | ||
1333 | case CX88_BOARD_WINFAST_DTV2000H_PLUS: | ||
1334 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1335 | &cx88_pinnacle_hybrid_pctv, | ||
1336 | &core->i2c_adap); | ||
1337 | if (fe0->dvb.frontend) { | ||
1338 | struct xc4000_config cfg = { | ||
1339 | .i2c_address = 0x61, | ||
1340 | .default_pm = 0, | ||
1341 | .dvb_amplitude = 134, | ||
1342 | .set_smoothedcvbs = 1, | ||
1343 | .if_khz = 4560 | ||
1344 | }; | ||
1345 | fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; | ||
1346 | if (attach_xc4000(dev, &cfg) < 0) | ||
1347 | goto frontend_detach; | ||
1348 | } | ||
1349 | break; | ||
1350 | case CX88_BOARD_GENIATECH_X8000_MT: | ||
1351 | dev->ts_gen_cntrl = 0x00; | ||
1352 | |||
1353 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1354 | &cx88_geniatech_x8000_mt, | ||
1355 | &core->i2c_adap); | ||
1356 | if (attach_xc3028(0x61, dev) < 0) | ||
1357 | goto frontend_detach; | ||
1358 | break; | ||
1359 | case CX88_BOARD_KWORLD_ATSC_120: | ||
1360 | fe0->dvb.frontend = dvb_attach(s5h1409_attach, | ||
1361 | &kworld_atsc_120_config, | ||
1362 | &core->i2c_adap); | ||
1363 | if (attach_xc3028(0x61, dev) < 0) | ||
1364 | goto frontend_detach; | ||
1365 | break; | ||
1366 | case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: | ||
1367 | fe0->dvb.frontend = dvb_attach(s5h1411_attach, | ||
1368 | &dvico_fusionhdtv7_config, | ||
1369 | &core->i2c_adap); | ||
1370 | if (fe0->dvb.frontend != NULL) { | ||
1371 | if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, | ||
1372 | &core->i2c_adap, | ||
1373 | &dvico_fusionhdtv7_tuner_config)) | ||
1374 | goto frontend_detach; | ||
1375 | } | ||
1376 | break; | ||
1377 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
1378 | /* MFE frontend 1 */ | ||
1379 | mfe_shared = 1; | ||
1380 | dev->frontends.gate = 2; | ||
1381 | /* DVB-S/S2 Init */ | ||
1382 | fe0->dvb.frontend = dvb_attach(cx24116_attach, | ||
1383 | &hauppauge_hvr4000_config, | ||
1384 | &dev->core->i2c_adap); | ||
1385 | if (fe0->dvb.frontend) { | ||
1386 | if (!dvb_attach(isl6421_attach, | ||
1387 | fe0->dvb.frontend, | ||
1388 | &dev->core->i2c_adap, | ||
1389 | 0x08, ISL6421_DCL, 0x00)) | ||
1390 | goto frontend_detach; | ||
1391 | } | ||
1392 | /* MFE frontend 2 */ | ||
1393 | fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); | ||
1394 | if (!fe1) | ||
1395 | goto frontend_detach; | ||
1396 | /* DVB-T Init */ | ||
1397 | fe1->dvb.frontend = dvb_attach(cx22702_attach, | ||
1398 | &hauppauge_hvr_config, | ||
1399 | &dev->core->i2c_adap); | ||
1400 | if (fe1->dvb.frontend) { | ||
1401 | fe1->dvb.frontend->id = 1; | ||
1402 | if (!dvb_attach(simple_tuner_attach, | ||
1403 | fe1->dvb.frontend, | ||
1404 | &dev->core->i2c_adap, | ||
1405 | 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) | ||
1406 | goto frontend_detach; | ||
1407 | } | ||
1408 | break; | ||
1409 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
1410 | fe0->dvb.frontend = dvb_attach(cx24116_attach, | ||
1411 | &hauppauge_hvr4000_config, | ||
1412 | &dev->core->i2c_adap); | ||
1413 | if (fe0->dvb.frontend) { | ||
1414 | if (!dvb_attach(isl6421_attach, | ||
1415 | fe0->dvb.frontend, | ||
1416 | &dev->core->i2c_adap, | ||
1417 | 0x08, ISL6421_DCL, 0x00)) | ||
1418 | goto frontend_detach; | ||
1419 | } | ||
1420 | break; | ||
1421 | case CX88_BOARD_PROF_6200: | ||
1422 | case CX88_BOARD_TBS_8910: | ||
1423 | case CX88_BOARD_TEVII_S420: | ||
1424 | fe0->dvb.frontend = dvb_attach(stv0299_attach, | ||
1425 | &tevii_tuner_sharp_config, | ||
1426 | &core->i2c_adap); | ||
1427 | if (fe0->dvb.frontend != NULL) { | ||
1428 | if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, | ||
1429 | &core->i2c_adap, DVB_PLL_OPERA1)) | ||
1430 | goto frontend_detach; | ||
1431 | core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; | ||
1432 | fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
1433 | |||
1434 | } else { | ||
1435 | fe0->dvb.frontend = dvb_attach(stv0288_attach, | ||
1436 | &tevii_tuner_earda_config, | ||
1437 | &core->i2c_adap); | ||
1438 | if (fe0->dvb.frontend != NULL) { | ||
1439 | if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61, | ||
1440 | &core->i2c_adap)) | ||
1441 | goto frontend_detach; | ||
1442 | core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; | ||
1443 | fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
1444 | } | ||
1445 | } | ||
1446 | break; | ||
1447 | case CX88_BOARD_TEVII_S460: | ||
1448 | fe0->dvb.frontend = dvb_attach(cx24116_attach, | ||
1449 | &tevii_s460_config, | ||
1450 | &core->i2c_adap); | ||
1451 | if (fe0->dvb.frontend != NULL) | ||
1452 | fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
1453 | break; | ||
1454 | case CX88_BOARD_TEVII_S464: | ||
1455 | fe0->dvb.frontend = dvb_attach(ds3000_attach, | ||
1456 | &tevii_ds3000_config, | ||
1457 | &core->i2c_adap); | ||
1458 | if (fe0->dvb.frontend != NULL) | ||
1459 | fe0->dvb.frontend->ops.set_voltage = | ||
1460 | tevii_dvbs_set_voltage; | ||
1461 | break; | ||
1462 | case CX88_BOARD_OMICOM_SS4_PCI: | ||
1463 | case CX88_BOARD_TBS_8920: | ||
1464 | case CX88_BOARD_PROF_7300: | ||
1465 | case CX88_BOARD_SATTRADE_ST4200: | ||
1466 | fe0->dvb.frontend = dvb_attach(cx24116_attach, | ||
1467 | &hauppauge_hvr4000_config, | ||
1468 | &core->i2c_adap); | ||
1469 | if (fe0->dvb.frontend != NULL) | ||
1470 | fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
1471 | break; | ||
1472 | case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: | ||
1473 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1474 | &cx88_terratec_cinergy_ht_pci_mkii_config, | ||
1475 | &core->i2c_adap); | ||
1476 | if (fe0->dvb.frontend) { | ||
1477 | fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; | ||
1478 | if (attach_xc3028(0x61, dev) < 0) | ||
1479 | goto frontend_detach; | ||
1480 | } | ||
1481 | break; | ||
1482 | case CX88_BOARD_PROF_7301:{ | ||
1483 | struct dvb_tuner_ops *tuner_ops = NULL; | ||
1484 | |||
1485 | fe0->dvb.frontend = dvb_attach(stv0900_attach, | ||
1486 | &prof_7301_stv0900_config, | ||
1487 | &core->i2c_adap, 0); | ||
1488 | if (fe0->dvb.frontend != NULL) { | ||
1489 | if (!dvb_attach(stb6100_attach, fe0->dvb.frontend, | ||
1490 | &prof_7301_stb6100_config, | ||
1491 | &core->i2c_adap)) | ||
1492 | goto frontend_detach; | ||
1493 | |||
1494 | tuner_ops = &fe0->dvb.frontend->ops.tuner_ops; | ||
1495 | tuner_ops->set_frequency = stb6100_set_freq; | ||
1496 | tuner_ops->get_frequency = stb6100_get_freq; | ||
1497 | tuner_ops->set_bandwidth = stb6100_set_bandw; | ||
1498 | tuner_ops->get_bandwidth = stb6100_get_bandw; | ||
1499 | |||
1500 | core->prev_set_voltage = | ||
1501 | fe0->dvb.frontend->ops.set_voltage; | ||
1502 | fe0->dvb.frontend->ops.set_voltage = | ||
1503 | tevii_dvbs_set_voltage; | ||
1504 | } | ||
1505 | break; | ||
1506 | } | ||
1507 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
1508 | dev->ts_gen_cntrl = 0x08; | ||
1509 | |||
1510 | cx_set(MO_GP0_IO, 0x0101); | ||
1511 | |||
1512 | cx_clear(MO_GP0_IO, 0x01); | ||
1513 | mdelay(100); | ||
1514 | cx_set(MO_GP0_IO, 0x01); | ||
1515 | mdelay(200); | ||
1516 | |||
1517 | fe0->dvb.frontend = dvb_attach(stv0299_attach, | ||
1518 | &samsung_stv0299_config, | ||
1519 | &dev->core->i2c_adap); | ||
1520 | if (fe0->dvb.frontend) { | ||
1521 | fe0->dvb.frontend->ops.tuner_ops.set_params = | ||
1522 | samsung_smt_7020_tuner_set_params; | ||
1523 | fe0->dvb.frontend->tuner_priv = | ||
1524 | &dev->core->i2c_adap; | ||
1525 | fe0->dvb.frontend->ops.set_voltage = | ||
1526 | samsung_smt_7020_set_voltage; | ||
1527 | fe0->dvb.frontend->ops.set_tone = | ||
1528 | samsung_smt_7020_set_tone; | ||
1529 | } | ||
1530 | |||
1531 | break; | ||
1532 | case CX88_BOARD_TWINHAN_VP1027_DVBS: | ||
1533 | dev->ts_gen_cntrl = 0x00; | ||
1534 | fe0->dvb.frontend = dvb_attach(mb86a16_attach, | ||
1535 | &twinhan_vp1027, | ||
1536 | &core->i2c_adap); | ||
1537 | if (fe0->dvb.frontend) { | ||
1538 | core->prev_set_voltage = | ||
1539 | fe0->dvb.frontend->ops.set_voltage; | ||
1540 | fe0->dvb.frontend->ops.set_voltage = | ||
1541 | vp1027_set_voltage; | ||
1542 | } | ||
1543 | break; | ||
1544 | |||
1545 | default: | ||
1546 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | ||
1547 | core->name); | ||
1548 | break; | ||
1549 | } | ||
1550 | |||
1551 | if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) { | ||
1552 | printk(KERN_ERR | ||
1553 | "%s/2: frontend initialization failed\n", | ||
1554 | core->name); | ||
1555 | goto frontend_detach; | ||
1556 | } | ||
1557 | /* define general-purpose callback pointer */ | ||
1558 | fe0->dvb.frontend->callback = cx88_tuner_callback; | ||
1559 | |||
1560 | /* Ensure all frontends negotiate bus access */ | ||
1561 | fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | ||
1562 | if (fe1) | ||
1563 | fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | ||
1564 | |||
1565 | /* Put the analog decoder in standby to keep it quiet */ | ||
1566 | call_all(core, core, s_power, 0); | ||
1567 | |||
1568 | /* register everything */ | ||
1569 | return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, | ||
1570 | &dev->pci->dev, adapter_nr, mfe_shared, NULL); | ||
1571 | |||
1572 | frontend_detach: | ||
1573 | core->gate_ctrl = NULL; | ||
1574 | videobuf_dvb_dealloc_frontends(&dev->frontends); | ||
1575 | return -EINVAL; | ||
1576 | } | ||
1577 | |||
1578 | /* ----------------------------------------------------------- */ | ||
1579 | |||
1580 | /* CX8802 MPEG -> mini driver - We have been given the hardware */ | ||
1581 | static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) | ||
1582 | { | ||
1583 | struct cx88_core *core = drv->core; | ||
1584 | int err = 0; | ||
1585 | dprintk( 1, "%s\n", __func__); | ||
1586 | |||
1587 | switch (core->boardnr) { | ||
1588 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1589 | /* We arrive here with either the cx23416 or the cx22702 | ||
1590 | * on the bus. Take the bus from the cx23416 and enable the | ||
1591 | * cx22702 demod | ||
1592 | */ | ||
1593 | /* Toggle reset on cx22702 leaving i2c active */ | ||
1594 | cx_set(MO_GP0_IO, 0x00000080); | ||
1595 | udelay(1000); | ||
1596 | cx_clear(MO_GP0_IO, 0x00000080); | ||
1597 | udelay(50); | ||
1598 | cx_set(MO_GP0_IO, 0x00000080); | ||
1599 | udelay(1000); | ||
1600 | /* enable the cx22702 pins */ | ||
1601 | cx_clear(MO_GP0_IO, 0x00000004); | ||
1602 | udelay(1000); | ||
1603 | break; | ||
1604 | |||
1605 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
1606 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
1607 | /* Toggle reset on cx22702 leaving i2c active */ | ||
1608 | cx_set(MO_GP0_IO, 0x00000080); | ||
1609 | udelay(1000); | ||
1610 | cx_clear(MO_GP0_IO, 0x00000080); | ||
1611 | udelay(50); | ||
1612 | cx_set(MO_GP0_IO, 0x00000080); | ||
1613 | udelay(1000); | ||
1614 | switch (core->dvbdev->frontends.active_fe_id) { | ||
1615 | case 1: /* DVB-S/S2 Enabled */ | ||
1616 | /* tri-state the cx22702 pins */ | ||
1617 | cx_set(MO_GP0_IO, 0x00000004); | ||
1618 | /* Take the cx24116/cx24123 out of reset */ | ||
1619 | cx_write(MO_SRST_IO, 1); | ||
1620 | core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */ | ||
1621 | break; | ||
1622 | case 2: /* DVB-T Enabled */ | ||
1623 | /* Put the cx24116/cx24123 into reset */ | ||
1624 | cx_write(MO_SRST_IO, 0); | ||
1625 | /* enable the cx22702 pins */ | ||
1626 | cx_clear(MO_GP0_IO, 0x00000004); | ||
1627 | core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */ | ||
1628 | break; | ||
1629 | } | ||
1630 | udelay(1000); | ||
1631 | break; | ||
1632 | |||
1633 | case CX88_BOARD_WINFAST_DTV2000H_PLUS: | ||
1634 | /* set RF input to AIR for DVB-T (GPIO 16) */ | ||
1635 | cx_write(MO_GP2_IO, 0x0101); | ||
1636 | break; | ||
1637 | |||
1638 | default: | ||
1639 | err = -ENODEV; | ||
1640 | } | ||
1641 | return err; | ||
1642 | } | ||
1643 | |||
1644 | /* CX8802 MPEG -> mini driver - We no longer have the hardware */ | ||
1645 | static int cx8802_dvb_advise_release(struct cx8802_driver *drv) | ||
1646 | { | ||
1647 | struct cx88_core *core = drv->core; | ||
1648 | int err = 0; | ||
1649 | dprintk( 1, "%s\n", __func__); | ||
1650 | |||
1651 | switch (core->boardnr) { | ||
1652 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1653 | /* Do Nothing, leave the cx22702 on the bus. */ | ||
1654 | break; | ||
1655 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
1656 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
1657 | break; | ||
1658 | default: | ||
1659 | err = -ENODEV; | ||
1660 | } | ||
1661 | return err; | ||
1662 | } | ||
1663 | |||
1664 | static int cx8802_dvb_probe(struct cx8802_driver *drv) | ||
1665 | { | ||
1666 | struct cx88_core *core = drv->core; | ||
1667 | struct cx8802_dev *dev = drv->core->dvbdev; | ||
1668 | int err; | ||
1669 | struct videobuf_dvb_frontend *fe; | ||
1670 | int i; | ||
1671 | |||
1672 | dprintk( 1, "%s\n", __func__); | ||
1673 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", | ||
1674 | core->boardnr, | ||
1675 | core->name, | ||
1676 | core->pci_bus, | ||
1677 | core->pci_slot); | ||
1678 | |||
1679 | err = -ENODEV; | ||
1680 | if (!(core->board.mpeg & CX88_MPEG_DVB)) | ||
1681 | goto fail_core; | ||
1682 | |||
1683 | /* If vp3054 isn't enabled, a stub will just return 0 */ | ||
1684 | err = vp3054_i2c_probe(dev); | ||
1685 | if (0 != err) | ||
1686 | goto fail_core; | ||
1687 | |||
1688 | /* dvb stuff */ | ||
1689 | printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); | ||
1690 | dev->ts_gen_cntrl = 0x0c; | ||
1691 | |||
1692 | err = cx8802_alloc_frontends(dev); | ||
1693 | if (err) | ||
1694 | goto fail_core; | ||
1695 | |||
1696 | err = -ENODEV; | ||
1697 | for (i = 1; i <= core->board.num_frontends; i++) { | ||
1698 | fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); | ||
1699 | if (fe == NULL) { | ||
1700 | printk(KERN_ERR "%s() failed to get frontend(%d)\n", | ||
1701 | __func__, i); | ||
1702 | goto fail_probe; | ||
1703 | } | ||
1704 | videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, | ||
1705 | &dev->pci->dev, &dev->slock, | ||
1706 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1707 | V4L2_FIELD_TOP, | ||
1708 | sizeof(struct cx88_buffer), | ||
1709 | dev, NULL); | ||
1710 | /* init struct videobuf_dvb */ | ||
1711 | fe->dvb.name = dev->core->name; | ||
1712 | } | ||
1713 | |||
1714 | err = dvb_register(dev); | ||
1715 | if (err) | ||
1716 | /* frontends/adapter de-allocated in dvb_register */ | ||
1717 | printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", | ||
1718 | core->name, err); | ||
1719 | return err; | ||
1720 | fail_probe: | ||
1721 | videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends); | ||
1722 | fail_core: | ||
1723 | return err; | ||
1724 | } | ||
1725 | |||
1726 | static int cx8802_dvb_remove(struct cx8802_driver *drv) | ||
1727 | { | ||
1728 | struct cx88_core *core = drv->core; | ||
1729 | struct cx8802_dev *dev = drv->core->dvbdev; | ||
1730 | |||
1731 | dprintk( 1, "%s\n", __func__); | ||
1732 | |||
1733 | videobuf_dvb_unregister_bus(&dev->frontends); | ||
1734 | |||
1735 | vp3054_i2c_remove(dev); | ||
1736 | |||
1737 | core->gate_ctrl = NULL; | ||
1738 | |||
1739 | return 0; | ||
1740 | } | ||
1741 | |||
1742 | static struct cx8802_driver cx8802_dvb_driver = { | ||
1743 | .type_id = CX88_MPEG_DVB, | ||
1744 | .hw_access = CX8802_DRVCTL_SHARED, | ||
1745 | .probe = cx8802_dvb_probe, | ||
1746 | .remove = cx8802_dvb_remove, | ||
1747 | .advise_acquire = cx8802_dvb_advise_acquire, | ||
1748 | .advise_release = cx8802_dvb_advise_release, | ||
1749 | }; | ||
1750 | |||
1751 | static int __init dvb_init(void) | ||
1752 | { | ||
1753 | printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n", | ||
1754 | CX88_VERSION); | ||
1755 | return cx8802_register_driver(&cx8802_dvb_driver); | ||
1756 | } | ||
1757 | |||
1758 | static void __exit dvb_fini(void) | ||
1759 | { | ||
1760 | cx8802_unregister_driver(&cx8802_dvb_driver); | ||
1761 | } | ||
1762 | |||
1763 | module_init(dvb_init); | ||
1764 | module_exit(dvb_fini); | ||