Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
1da177e4 LT |
2 | * |
3 | * device driver for Conexant 2388x based TV cards | |
4 | * MPEG Transport Stream (DVB) routines | |
5 | * | |
fc40b261 | 6 | * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> |
1da177e4 LT |
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 | ||
1da177e4 LT |
32 | #include "cx88.h" |
33 | #include "dvb-pll.h" | |
5e453dc7 | 34 | #include <media/v4l2-common.h> |
41ef7c1e | 35 | |
29780bb7 | 36 | #ifdef HAVE_MT352 |
41ef7c1e MCC |
37 | # include "mt352.h" |
38 | # include "mt352_priv.h" | |
fc40b261 CP |
39 | # ifdef HAVE_VP3054_I2C |
40 | # include "cx88-vp3054-i2c.h" | |
41 | # endif | |
41ef7c1e | 42 | #endif |
29780bb7 | 43 | #ifdef HAVE_CX22702 |
1da177e4 LT |
44 | # include "cx22702.h" |
45 | #endif | |
29780bb7 | 46 | #ifdef HAVE_OR51132 |
1da177e4 LT |
47 | # include "or51132.h" |
48 | #endif | |
6ddcc919 MK |
49 | #ifdef HAVE_LGDT330X |
50 | # include "lgdt330x.h" | |
f1798495 | 51 | #endif |
fde6d31e KL |
52 | #ifdef HAVE_NXT200X |
53 | # include "nxt200x.h" | |
54 | #endif | |
0fa14aa6 ST |
55 | #ifdef HAVE_CX24123 |
56 | # include "cx24123.h" | |
57 | #endif | |
1da177e4 LT |
58 | |
59 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); | |
60 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | |
61 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | |
62 | MODULE_LICENSE("GPL"); | |
63 | ||
64 | static unsigned int debug = 0; | |
65 | module_param(debug, int, 0644); | |
66 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); | |
67 | ||
68 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | |
69 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg) | |
70 | ||
71 | /* ------------------------------------------------------------------ */ | |
72 | ||
73 | static int dvb_buf_setup(struct videobuf_queue *q, | |
74 | unsigned int *count, unsigned int *size) | |
75 | { | |
76 | struct cx8802_dev *dev = q->priv_data; | |
77 | ||
78 | dev->ts_packet_size = 188 * 4; | |
79 | dev->ts_packet_count = 32; | |
80 | ||
81 | *size = dev->ts_packet_size * dev->ts_packet_count; | |
82 | *count = 32; | |
83 | return 0; | |
84 | } | |
85 | ||
86 | static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |
87 | enum v4l2_field field) | |
88 | { | |
89 | struct cx8802_dev *dev = q->priv_data; | |
ccd7b650 | 90 | return cx8802_buf_prepare(dev, (struct cx88_buffer*)vb,field); |
1da177e4 LT |
91 | } |
92 | ||
93 | static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
94 | { | |
95 | struct cx8802_dev *dev = q->priv_data; | |
96 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); | |
97 | } | |
98 | ||
99 | static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
100 | { | |
101 | struct cx8802_dev *dev = q->priv_data; | |
102 | cx88_free_buffer(dev->pci, (struct cx88_buffer*)vb); | |
103 | } | |
104 | ||
408b664a | 105 | static struct videobuf_queue_ops dvb_qops = { |
1da177e4 LT |
106 | .buf_setup = dvb_buf_setup, |
107 | .buf_prepare = dvb_buf_prepare, | |
108 | .buf_queue = dvb_buf_queue, | |
109 | .buf_release = dvb_buf_release, | |
110 | }; | |
111 | ||
112 | /* ------------------------------------------------------------------ */ | |
113 | ||
29780bb7 | 114 | #ifdef HAVE_MT352 |
fc40b261 | 115 | static int generic_mt352_demod_init(struct dvb_frontend* fe) |
1da177e4 LT |
116 | { |
117 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; | |
118 | static u8 reset [] = { RESET, 0x80 }; | |
119 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | |
120 | static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; | |
121 | static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | |
122 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | |
123 | ||
124 | mt352_write(fe, clock_config, sizeof(clock_config)); | |
125 | udelay(200); | |
126 | mt352_write(fe, reset, sizeof(reset)); | |
127 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | |
128 | ||
129 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | |
130 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | |
131 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | |
132 | return 0; | |
133 | } | |
134 | ||
135 | static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) | |
136 | { | |
137 | static u8 clock_config [] = { 0x89, 0x38, 0x39 }; | |
138 | static u8 reset [] = { 0x50, 0x80 }; | |
139 | static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; | |
140 | static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, | |
f2421ca3 | 141 | 0x00, 0xFF, 0x00, 0x40, 0x40 }; |
1da177e4 LT |
142 | static u8 dntv_extra[] = { 0xB5, 0x7A }; |
143 | static u8 capt_range_cfg[] = { 0x75, 0x32 }; | |
144 | ||
145 | mt352_write(fe, clock_config, sizeof(clock_config)); | |
146 | udelay(2000); | |
147 | mt352_write(fe, reset, sizeof(reset)); | |
148 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | |
149 | ||
150 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | |
151 | udelay(2000); | |
152 | mt352_write(fe, dntv_extra, sizeof(dntv_extra)); | |
153 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | |
154 | ||
155 | return 0; | |
156 | } | |
157 | ||
158 | static int mt352_pll_set(struct dvb_frontend* fe, | |
159 | struct dvb_frontend_parameters* params, | |
160 | u8* pllbuf) | |
161 | { | |
162 | struct cx8802_dev *dev= fe->dvb->priv; | |
163 | ||
164 | pllbuf[0] = dev->core->pll_addr << 1; | |
165 | dvb_pll_configure(dev->core->pll_desc, pllbuf+1, | |
166 | params->frequency, | |
167 | params->u.ofdm.bandwidth); | |
168 | return 0; | |
169 | } | |
170 | ||
171 | static struct mt352_config dvico_fusionhdtv = { | |
172 | .demod_address = 0x0F, | |
fc40b261 | 173 | .demod_init = generic_mt352_demod_init, |
1da177e4 LT |
174 | .pll_set = mt352_pll_set, |
175 | }; | |
176 | ||
177 | static struct mt352_config dntv_live_dvbt_config = { | |
178 | .demod_address = 0x0f, | |
179 | .demod_init = dntv_live_dvbt_demod_init, | |
180 | .pll_set = mt352_pll_set, | |
181 | }; | |
fc40b261 CP |
182 | |
183 | #ifdef HAVE_VP3054_I2C | |
184 | static int philips_fmd1216_pll_init(struct dvb_frontend *fe) | |
185 | { | |
186 | struct cx8802_dev *dev= fe->dvb->priv; | |
187 | ||
188 | /* this message is to set up ATC and ALC */ | |
189 | static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; | |
190 | struct i2c_msg msg = | |
191 | { .addr = dev->core->pll_addr, .flags = 0, | |
192 | .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; | |
193 | int err; | |
194 | ||
195 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | |
196 | if (err < 0) | |
197 | return err; | |
198 | else | |
199 | return -EREMOTEIO; | |
200 | } | |
201 | ||
202 | return 0; | |
203 | } | |
204 | ||
205 | static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe, | |
206 | struct dvb_frontend_parameters* params, | |
207 | u8* pllbuf) | |
208 | { | |
209 | struct cx8802_dev *dev= fe->dvb->priv; | |
210 | struct i2c_msg msg = | |
211 | { .addr = dev->core->pll_addr, .flags = 0, | |
212 | .buf = pllbuf+1, .len = 4 }; | |
213 | int err; | |
214 | ||
215 | /* Switch PLL to DVB mode */ | |
216 | err = philips_fmd1216_pll_init(fe); | |
217 | if (err) | |
218 | return err; | |
219 | ||
220 | /* Tune PLL */ | |
221 | pllbuf[0] = dev->core->pll_addr << 1; | |
222 | dvb_pll_configure(dev->core->pll_desc, pllbuf+1, | |
223 | params->frequency, | |
224 | params->u.ofdm.bandwidth); | |
225 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | |
226 | printk(KERN_WARNING "cx88-dvb: %s error " | |
227 | "(addr %02x <- %02x, err = %i)\n", | |
228 | __FUNCTION__, pllbuf[0], pllbuf[1], err); | |
229 | if (err < 0) | |
230 | return err; | |
231 | else | |
232 | return -EREMOTEIO; | |
233 | } | |
234 | ||
235 | return 0; | |
236 | } | |
237 | ||
238 | static struct mt352_config dntv_live_dvbt_pro_config = { | |
239 | .demod_address = 0x0f, | |
240 | .no_tuner = 1, | |
241 | .demod_init = generic_mt352_demod_init, | |
242 | .pll_set = dntv_live_dvbt_pro_pll_set, | |
243 | }; | |
244 | #endif | |
41ef7c1e | 245 | #endif |
1da177e4 | 246 | |
29780bb7 | 247 | #ifdef HAVE_CX22702 |
1da177e4 LT |
248 | static struct cx22702_config connexant_refboard_config = { |
249 | .demod_address = 0x43, | |
38d84c3b | 250 | .output_mode = CX22702_SERIAL_OUTPUT, |
1da177e4 LT |
251 | .pll_address = 0x60, |
252 | .pll_desc = &dvb_pll_thomson_dtt7579, | |
253 | }; | |
254 | ||
255 | static struct cx22702_config hauppauge_novat_config = { | |
256 | .demod_address = 0x43, | |
38d84c3b | 257 | .output_mode = CX22702_SERIAL_OUTPUT, |
1da177e4 LT |
258 | .pll_address = 0x61, |
259 | .pll_desc = &dvb_pll_thomson_dtt759x, | |
260 | }; | |
611900c1 ST |
261 | static struct cx22702_config hauppauge_hvr1100_config = { |
262 | .demod_address = 0x63, | |
263 | .output_mode = CX22702_SERIAL_OUTPUT, | |
264 | .pll_address = 0x61, | |
265 | .pll_desc = &dvb_pll_fmd1216me, | |
266 | }; | |
1da177e4 LT |
267 | #endif |
268 | ||
29780bb7 | 269 | #ifdef HAVE_OR51132 |
1da177e4 LT |
270 | static int or51132_set_ts_param(struct dvb_frontend* fe, |
271 | int is_punctured) | |
272 | { | |
273 | struct cx8802_dev *dev= fe->dvb->priv; | |
274 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | |
275 | return 0; | |
276 | } | |
277 | ||
408b664a | 278 | static struct or51132_config pchdtv_hd3000 = { |
1da177e4 LT |
279 | .demod_address = 0x15, |
280 | .pll_address = 0x61, | |
281 | .pll_desc = &dvb_pll_thomson_dtt7610, | |
282 | .set_ts_params = or51132_set_ts_param, | |
283 | }; | |
284 | #endif | |
285 | ||
6ddcc919 MK |
286 | #ifdef HAVE_LGDT330X |
287 | static int lgdt330x_pll_set(struct dvb_frontend* fe, | |
1963c907 | 288 | struct dvb_frontend_parameters* params) |
b6aef071 | 289 | { |
e52e98a7 MCC |
290 | /* FIXME make this routine use the tuner-simple code. |
291 | * It could probably be shared with a number of ATSC | |
292 | * frontends. Many share the same tuner with analog TV. */ | |
293 | ||
b6aef071 | 294 | struct cx8802_dev *dev= fe->dvb->priv; |
e52e98a7 | 295 | struct cx88_core *core = dev->core; |
1963c907 MK |
296 | u8 buf[4]; |
297 | struct i2c_msg msg = | |
298 | { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; | |
299 | int err; | |
300 | ||
e52e98a7 | 301 | /* Put the analog decoder in standby to keep it quiet */ |
93352f5c | 302 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
e52e98a7 MCC |
303 | |
304 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); | |
1963c907 MK |
305 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", |
306 | __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); | |
e52e98a7 | 307 | if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { |
1963c907 MK |
308 | printk(KERN_WARNING "cx88-dvb: %s error " |
309 | "(addr %02x <- %02x, err = %i)\n", | |
310 | __FUNCTION__, buf[0], buf[1], err); | |
311 | if (err < 0) | |
312 | return err; | |
313 | else | |
314 | return -EREMOTEIO; | |
315 | } | |
e52e98a7 MCC |
316 | if (core->tuner_type == TUNER_LG_TDVS_H062F) { |
317 | /* Set the Auxiliary Byte. */ | |
318 | buf[2] &= ~0x20; | |
319 | buf[2] |= 0x18; | |
320 | buf[3] = 0x50; | |
321 | i2c_transfer(&core->i2c_adap, &msg, 1); | |
322 | } | |
b6aef071 MK |
323 | return 0; |
324 | } | |
325 | ||
6ddcc919 | 326 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) |
0ccef6db MK |
327 | { |
328 | struct cx8802_dev *dev= fe->dvb->priv; | |
329 | struct cx88_core *core = dev->core; | |
330 | ||
331 | dprintk(1, "%s: index = %d\n", __FUNCTION__, index); | |
332 | if (index == 0) | |
333 | cx_clear(MO_GP0_IO, 8); | |
334 | else | |
335 | cx_set(MO_GP0_IO, 8); | |
336 | return 0; | |
337 | } | |
338 | ||
6ddcc919 | 339 | static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) |
f1798495 MK |
340 | { |
341 | struct cx8802_dev *dev= fe->dvb->priv; | |
342 | if (is_punctured) | |
343 | dev->ts_gen_cntrl |= 0x04; | |
344 | else | |
345 | dev->ts_gen_cntrl &= ~0x04; | |
346 | return 0; | |
347 | } | |
348 | ||
6ddcc919 | 349 | static struct lgdt330x_config fusionhdtv_3_gold = { |
0d723c09 | 350 | .demod_address = 0x0e, |
1963c907 MK |
351 | .demod_chip = LGDT3302, |
352 | .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ | |
6ddcc919 MK |
353 | .pll_set = lgdt330x_pll_set, |
354 | .set_ts_params = lgdt330x_set_ts_param, | |
0d723c09 | 355 | }; |
e52e98a7 MCC |
356 | |
357 | static struct lgdt330x_config fusionhdtv_5_gold = { | |
358 | .demod_address = 0x0e, | |
359 | .demod_chip = LGDT3303, | |
360 | .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ | |
361 | .pll_set = lgdt330x_pll_set, | |
362 | .set_ts_params = lgdt330x_set_ts_param, | |
363 | }; | |
f1798495 MK |
364 | #endif |
365 | ||
fde6d31e KL |
366 | #ifdef HAVE_NXT200X |
367 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, | |
368 | int is_punctured) | |
369 | { | |
370 | struct cx8802_dev *dev= fe->dvb->priv; | |
371 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | |
372 | return 0; | |
373 | } | |
374 | ||
d4c34aa0 KL |
375 | static int nxt200x_set_pll_input(u8* buf, int input) |
376 | { | |
377 | if (input) | |
378 | buf[3] |= 0x08; | |
379 | else | |
380 | buf[3] &= ~0x08; | |
381 | return 0; | |
382 | } | |
383 | ||
fde6d31e KL |
384 | static struct nxt200x_config ati_hdtvwonder = { |
385 | .demod_address = 0x0a, | |
386 | .pll_address = 0x61, | |
387 | .pll_desc = &dvb_pll_tuv1236d, | |
d4c34aa0 | 388 | .set_pll_input = nxt200x_set_pll_input, |
fde6d31e KL |
389 | .set_ts_params = nxt200x_set_ts_param, |
390 | }; | |
391 | #endif | |
392 | ||
0fa14aa6 ST |
393 | #ifdef HAVE_CX24123 |
394 | static int cx24123_set_ts_param(struct dvb_frontend* fe, | |
395 | int is_punctured) | |
396 | { | |
397 | struct cx8802_dev *dev= fe->dvb->priv; | |
398 | dev->ts_gen_cntrl = 0x2; | |
399 | return 0; | |
400 | } | |
401 | ||
0e0351e3 VC |
402 | static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on) |
403 | { | |
404 | struct cx8802_dev *dev= fe->dvb->priv; | |
405 | struct cx88_core *core = dev->core; | |
406 | ||
407 | if (on) | |
408 | cx_write(MO_GP0_IO, 0x000006f9); | |
409 | else | |
410 | cx_write(MO_GP0_IO, 0x000006fB); | |
411 | } | |
412 | ||
0fa14aa6 | 413 | static struct cx24123_config hauppauge_novas_config = { |
0e0351e3 VC |
414 | .demod_address = 0x55, |
415 | .use_isl6421 = 1, | |
416 | .set_ts_params = cx24123_set_ts_param, | |
417 | }; | |
418 | ||
419 | static struct cx24123_config kworld_dvbs_100_config = { | |
420 | .demod_address = 0x15, | |
421 | .use_isl6421 = 0, | |
422 | .set_ts_params = cx24123_set_ts_param, | |
423 | .enable_lnb_voltage = cx24123_enable_lnb_voltage, | |
0fa14aa6 ST |
424 | }; |
425 | #endif | |
426 | ||
1da177e4 LT |
427 | static int dvb_register(struct cx8802_dev *dev) |
428 | { | |
429 | /* init struct videobuf_dvb */ | |
430 | dev->dvb.name = dev->core->name; | |
431 | dev->ts_gen_cntrl = 0x0c; | |
432 | ||
433 | /* init frontend */ | |
434 | switch (dev->core->board) { | |
29780bb7 | 435 | #ifdef HAVE_CX22702 |
1da177e4 LT |
436 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
437 | dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, | |
438 | &dev->core->i2c_adap); | |
439 | break; | |
e057ee11 | 440 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
1da177e4 | 441 | case CX88_BOARD_CONEXANT_DVB_T1: |
2b5200a7 | 442 | case CX88_BOARD_WINFAST_DTV1000: |
1da177e4 LT |
443 | dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, |
444 | &dev->core->i2c_adap); | |
445 | break; | |
611900c1 ST |
446 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
447 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | |
448 | dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, | |
449 | &dev->core->i2c_adap); | |
450 | break; | |
1da177e4 | 451 | #endif |
29780bb7 | 452 | #ifdef HAVE_MT352 |
1da177e4 LT |
453 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: |
454 | dev->core->pll_addr = 0x61; | |
455 | dev->core->pll_desc = &dvb_pll_lg_z201; | |
456 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, | |
457 | &dev->core->i2c_adap); | |
458 | break; | |
459 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | |
460 | dev->core->pll_addr = 0x60; | |
461 | dev->core->pll_desc = &dvb_pll_thomson_dtt7579; | |
462 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, | |
463 | &dev->core->i2c_adap); | |
464 | break; | |
465 | case CX88_BOARD_KWORLD_DVB_T: | |
466 | case CX88_BOARD_DNTV_LIVE_DVB_T: | |
a82decf6 | 467 | case CX88_BOARD_ADSTECH_DVB_T_PCI: |
1da177e4 LT |
468 | dev->core->pll_addr = 0x61; |
469 | dev->core->pll_desc = &dvb_pll_unknown_1; | |
470 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, | |
471 | &dev->core->i2c_adap); | |
472 | break; | |
fc40b261 CP |
473 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
474 | #ifdef HAVE_VP3054_I2C | |
475 | dev->core->pll_addr = 0x61; | |
476 | dev->core->pll_desc = &dvb_pll_fmd1216me; | |
477 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, | |
478 | &((struct vp3054_i2c_state *)dev->card_priv)->adap); | |
479 | #else | |
480 | printk("%s: built without vp3054 support\n", dev->core->name); | |
481 | #endif | |
482 | break; | |
41ef7c1e | 483 | #endif |
29780bb7 | 484 | #ifdef HAVE_OR51132 |
1da177e4 LT |
485 | case CX88_BOARD_PCHDTV_HD3000: |
486 | dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, | |
487 | &dev->core->i2c_adap); | |
488 | break; | |
f1798495 | 489 | #endif |
6ddcc919 | 490 | #ifdef HAVE_LGDT330X |
f1798495 MK |
491 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: |
492 | dev->ts_gen_cntrl = 0x08; | |
493 | { | |
494 | /* Do a hardware reset of chip before using it. */ | |
495 | struct cx88_core *core = dev->core; | |
496 | ||
497 | cx_clear(MO_GP0_IO, 1); | |
498 | mdelay(100); | |
0ccef6db | 499 | cx_set(MO_GP0_IO, 1); |
f1798495 | 500 | mdelay(200); |
0ccef6db MK |
501 | |
502 | /* Select RF connector callback */ | |
6ddcc919 | 503 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; |
b6aef071 MK |
504 | dev->core->pll_addr = 0x61; |
505 | dev->core->pll_desc = &dvb_pll_microtune_4042; | |
6ddcc919 | 506 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
f1798495 MK |
507 | &dev->core->i2c_adap); |
508 | } | |
509 | break; | |
0d723c09 MK |
510 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: |
511 | dev->ts_gen_cntrl = 0x08; | |
512 | { | |
513 | /* Do a hardware reset of chip before using it. */ | |
514 | struct cx88_core *core = dev->core; | |
515 | ||
516 | cx_clear(MO_GP0_IO, 1); | |
517 | mdelay(100); | |
d975872c | 518 | cx_set(MO_GP0_IO, 9); |
0d723c09 | 519 | mdelay(200); |
b6aef071 | 520 | dev->core->pll_addr = 0x61; |
83ac8722 | 521 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; |
6ddcc919 | 522 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
0d723c09 MK |
523 | &dev->core->i2c_adap); |
524 | } | |
525 | break; | |
e52e98a7 MCC |
526 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: |
527 | dev->ts_gen_cntrl = 0x08; | |
528 | { | |
529 | /* Do a hardware reset of chip before using it. */ | |
530 | struct cx88_core *core = dev->core; | |
531 | ||
532 | cx_clear(MO_GP0_IO, 1); | |
533 | mdelay(100); | |
534 | cx_set(MO_GP0_IO, 1); | |
535 | mdelay(200); | |
536 | dev->core->pll_addr = 0x61; | |
537 | dev->core->pll_desc = &dvb_pll_tdvs_tua6034; | |
538 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold, | |
539 | &dev->core->i2c_adap); | |
540 | } | |
541 | break; | |
fde6d31e KL |
542 | #endif |
543 | #ifdef HAVE_NXT200X | |
544 | case CX88_BOARD_ATI_HDTVWONDER: | |
545 | dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder, | |
546 | &dev->core->i2c_adap); | |
0fa14aa6 ST |
547 | break; |
548 | #endif | |
549 | #ifdef HAVE_CX24123 | |
550 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | |
551 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | |
552 | dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, | |
553 | &dev->core->i2c_adap); | |
0e0351e3 VC |
554 | break; |
555 | case CX88_BOARD_KWORLD_DVBS_100: | |
556 | dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, | |
557 | &dev->core->i2c_adap); | |
fde6d31e | 558 | break; |
1da177e4 LT |
559 | #endif |
560 | default: | |
1622c3fc GK |
561 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
562 | dev->core->name); | |
1da177e4 LT |
563 | break; |
564 | } | |
565 | if (NULL == dev->dvb.frontend) { | |
566 | printk("%s: frontend initialization failed\n",dev->core->name); | |
567 | return -1; | |
568 | } | |
569 | ||
570 | if (dev->core->pll_desc) { | |
571 | dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min; | |
572 | dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max; | |
573 | } | |
574 | ||
93352f5c MCC |
575 | /* Put the analog decoder in standby to keep it quiet */ |
576 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | |
577 | ||
1da177e4 LT |
578 | /* register everything */ |
579 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); | |
580 | } | |
581 | ||
582 | /* ----------------------------------------------------------- */ | |
583 | ||
584 | static int __devinit dvb_probe(struct pci_dev *pci_dev, | |
585 | const struct pci_device_id *pci_id) | |
586 | { | |
587 | struct cx8802_dev *dev; | |
588 | struct cx88_core *core; | |
589 | int err; | |
590 | ||
591 | /* general setup */ | |
592 | core = cx88_core_get(pci_dev); | |
593 | if (NULL == core) | |
594 | return -EINVAL; | |
595 | ||
596 | err = -ENODEV; | |
597 | if (!cx88_boards[core->board].dvb) | |
598 | goto fail_core; | |
599 | ||
600 | err = -ENOMEM; | |
601 | dev = kmalloc(sizeof(*dev),GFP_KERNEL); | |
602 | if (NULL == dev) | |
603 | goto fail_core; | |
604 | memset(dev,0,sizeof(*dev)); | |
605 | dev->pci = pci_dev; | |
606 | dev->core = core; | |
607 | ||
608 | err = cx8802_init_common(dev); | |
609 | if (0 != err) | |
610 | goto fail_free; | |
611 | ||
fc40b261 CP |
612 | #ifdef HAVE_VP3054_I2C |
613 | err = vp3054_i2c_probe(dev); | |
614 | if (0 != err) | |
615 | goto fail_free; | |
616 | #endif | |
617 | ||
1da177e4 LT |
618 | /* dvb stuff */ |
619 | printk("%s/2: cx2388x based dvb card\n", core->name); | |
620 | videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, | |
621 | dev->pci, &dev->slock, | |
622 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | |
623 | V4L2_FIELD_TOP, | |
624 | sizeof(struct cx88_buffer), | |
625 | dev); | |
626 | err = dvb_register(dev); | |
627 | if (0 != err) | |
1622c3fc | 628 | goto fail_fini; |
611900c1 ST |
629 | |
630 | /* Maintain a reference to cx88-video can query the 8802 device. */ | |
631 | core->dvbdev = dev; | |
1da177e4 LT |
632 | return 0; |
633 | ||
1622c3fc GK |
634 | fail_fini: |
635 | cx8802_fini_common(dev); | |
1da177e4 LT |
636 | fail_free: |
637 | kfree(dev); | |
638 | fail_core: | |
639 | cx88_core_put(core,pci_dev); | |
640 | return err; | |
641 | } | |
642 | ||
643 | static void __devexit dvb_remove(struct pci_dev *pci_dev) | |
644 | { | |
4ac97914 | 645 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); |
1da177e4 | 646 | |
611900c1 ST |
647 | /* Destroy any 8802 reference. */ |
648 | dev->core->dvbdev = NULL; | |
649 | ||
1da177e4 LT |
650 | /* dvb */ |
651 | videobuf_dvb_unregister(&dev->dvb); | |
652 | ||
fc40b261 CP |
653 | #ifdef HAVE_VP3054_I2C |
654 | vp3054_i2c_remove(dev); | |
655 | #endif | |
656 | ||
1da177e4 LT |
657 | /* common */ |
658 | cx8802_fini_common(dev); | |
659 | cx88_core_put(dev->core,dev->pci); | |
660 | kfree(dev); | |
661 | } | |
662 | ||
663 | static struct pci_device_id cx8802_pci_tbl[] = { | |
664 | { | |
665 | .vendor = 0x14f1, | |
666 | .device = 0x8802, | |
4ac97914 MCC |
667 | .subvendor = PCI_ANY_ID, |
668 | .subdevice = PCI_ANY_ID, | |
1da177e4 LT |
669 | },{ |
670 | /* --- end of list --- */ | |
671 | } | |
672 | }; | |
673 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | |
674 | ||
675 | static struct pci_driver dvb_pci_driver = { | |
4ac97914 MCC |
676 | .name = "cx88-dvb", |
677 | .id_table = cx8802_pci_tbl, | |
678 | .probe = dvb_probe, | |
679 | .remove = __devexit_p(dvb_remove), | |
1da177e4 LT |
680 | .suspend = cx8802_suspend_common, |
681 | .resume = cx8802_resume_common, | |
682 | }; | |
683 | ||
684 | static int dvb_init(void) | |
685 | { | |
686 | printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n", | |
687 | (CX88_VERSION_CODE >> 16) & 0xff, | |
688 | (CX88_VERSION_CODE >> 8) & 0xff, | |
689 | CX88_VERSION_CODE & 0xff); | |
690 | #ifdef SNAPSHOT | |
691 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | |
692 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | |
693 | #endif | |
694 | return pci_register_driver(&dvb_pci_driver); | |
695 | } | |
696 | ||
697 | static void dvb_fini(void) | |
698 | { | |
699 | pci_unregister_driver(&dvb_pci_driver); | |
700 | } | |
701 | ||
702 | module_init(dvb_init); | |
703 | module_exit(dvb_fini); | |
704 | ||
705 | /* | |
706 | * Local variables: | |
707 | * c-basic-offset: 8 | |
708 | * compile-command: "make DVB=1" | |
709 | * End: | |
710 | */ |