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 |
780dfef3 CP |
43 | #ifdef HAVE_ZL10353 |
44 | # include "zl10353.h" | |
45 | #endif | |
29780bb7 | 46 | #ifdef HAVE_CX22702 |
1da177e4 LT |
47 | # include "cx22702.h" |
48 | #endif | |
29780bb7 | 49 | #ifdef HAVE_OR51132 |
1da177e4 LT |
50 | # include "or51132.h" |
51 | #endif | |
6ddcc919 MK |
52 | #ifdef HAVE_LGDT330X |
53 | # include "lgdt330x.h" | |
81ad3428 | 54 | # include "lg_h06xf.h" |
f1798495 | 55 | #endif |
fde6d31e KL |
56 | #ifdef HAVE_NXT200X |
57 | # include "nxt200x.h" | |
58 | #endif | |
0fa14aa6 ST |
59 | #ifdef HAVE_CX24123 |
60 | # include "cx24123.h" | |
61 | #endif | |
cd20ca9f | 62 | #include "isl6421.h" |
1da177e4 LT |
63 | |
64 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); | |
65 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | |
66 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | |
67 | MODULE_LICENSE("GPL"); | |
68 | ||
69 | static unsigned int debug = 0; | |
70 | module_param(debug, int, 0644); | |
71 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); | |
72 | ||
73 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | |
74 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg) | |
75 | ||
76 | /* ------------------------------------------------------------------ */ | |
77 | ||
78 | static int dvb_buf_setup(struct videobuf_queue *q, | |
79 | unsigned int *count, unsigned int *size) | |
80 | { | |
81 | struct cx8802_dev *dev = q->priv_data; | |
82 | ||
83 | dev->ts_packet_size = 188 * 4; | |
84 | dev->ts_packet_count = 32; | |
85 | ||
86 | *size = dev->ts_packet_size * dev->ts_packet_count; | |
87 | *count = 32; | |
88 | return 0; | |
89 | } | |
90 | ||
91 | static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |
92 | enum v4l2_field field) | |
93 | { | |
94 | struct cx8802_dev *dev = q->priv_data; | |
c7b0ac05 | 95 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); |
1da177e4 LT |
96 | } |
97 | ||
98 | static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
99 | { | |
100 | struct cx8802_dev *dev = q->priv_data; | |
101 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); | |
102 | } | |
103 | ||
104 | static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
105 | { | |
c7b0ac05 | 106 | cx88_free_buffer(q, (struct cx88_buffer*)vb); |
1da177e4 LT |
107 | } |
108 | ||
408b664a | 109 | static struct videobuf_queue_ops dvb_qops = { |
1da177e4 LT |
110 | .buf_setup = dvb_buf_setup, |
111 | .buf_prepare = dvb_buf_prepare, | |
112 | .buf_queue = dvb_buf_queue, | |
113 | .buf_release = dvb_buf_release, | |
114 | }; | |
115 | ||
116 | /* ------------------------------------------------------------------ */ | |
117 | ||
29780bb7 | 118 | #ifdef HAVE_MT352 |
3d7d027a | 119 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) |
1da177e4 LT |
120 | { |
121 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; | |
122 | static u8 reset [] = { RESET, 0x80 }; | |
123 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | |
124 | static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; | |
125 | static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | |
126 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | |
127 | ||
128 | mt352_write(fe, clock_config, sizeof(clock_config)); | |
129 | udelay(200); | |
130 | mt352_write(fe, reset, sizeof(reset)); | |
131 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | |
132 | ||
133 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | |
134 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | |
135 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | |
136 | return 0; | |
137 | } | |
138 | ||
43eabb4e CP |
139 | static int dvico_dual_demod_init(struct dvb_frontend *fe) |
140 | { | |
141 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; | |
142 | static u8 reset [] = { RESET, 0x80 }; | |
143 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | |
144 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; | |
145 | static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | |
146 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | |
147 | ||
148 | mt352_write(fe, clock_config, sizeof(clock_config)); | |
149 | udelay(200); | |
150 | mt352_write(fe, reset, sizeof(reset)); | |
151 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | |
152 | ||
153 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | |
154 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | |
155 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | |
156 | ||
157 | return 0; | |
158 | } | |
159 | ||
1da177e4 LT |
160 | static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) |
161 | { | |
162 | static u8 clock_config [] = { 0x89, 0x38, 0x39 }; | |
163 | static u8 reset [] = { 0x50, 0x80 }; | |
164 | static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; | |
165 | static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, | |
f2421ca3 | 166 | 0x00, 0xFF, 0x00, 0x40, 0x40 }; |
1da177e4 LT |
167 | static u8 dntv_extra[] = { 0xB5, 0x7A }; |
168 | static u8 capt_range_cfg[] = { 0x75, 0x32 }; | |
169 | ||
170 | mt352_write(fe, clock_config, sizeof(clock_config)); | |
171 | udelay(2000); | |
172 | mt352_write(fe, reset, sizeof(reset)); | |
173 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | |
174 | ||
175 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | |
176 | udelay(2000); | |
177 | mt352_write(fe, dntv_extra, sizeof(dntv_extra)); | |
178 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | |
179 | ||
180 | return 0; | |
181 | } | |
182 | ||
1da177e4 LT |
183 | static struct mt352_config dvico_fusionhdtv = { |
184 | .demod_address = 0x0F, | |
3d7d027a | 185 | .demod_init = dvico_fusionhdtv_demod_init, |
1da177e4 LT |
186 | }; |
187 | ||
188 | static struct mt352_config dntv_live_dvbt_config = { | |
189 | .demod_address = 0x0f, | |
190 | .demod_init = dntv_live_dvbt_demod_init, | |
1da177e4 | 191 | }; |
fc40b261 | 192 | |
43eabb4e CP |
193 | static struct mt352_config dvico_fusionhdtv_dual = { |
194 | .demod_address = 0x0F, | |
195 | .demod_init = dvico_dual_demod_init, | |
43eabb4e CP |
196 | }; |
197 | ||
fc40b261 | 198 | #ifdef HAVE_VP3054_I2C |
3d7d027a CP |
199 | static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) |
200 | { | |
201 | static u8 clock_config [] = { 0x89, 0x38, 0x38 }; | |
202 | static u8 reset [] = { 0x50, 0x80 }; | |
203 | static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; | |
204 | static u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF, | |
205 | 0x00, 0xFF, 0x00, 0x40, 0x40 }; | |
206 | static u8 dntv_extra[] = { 0xB5, 0x7A }; | |
207 | static u8 capt_range_cfg[] = { 0x75, 0x32 }; | |
208 | ||
209 | mt352_write(fe, clock_config, sizeof(clock_config)); | |
210 | udelay(2000); | |
211 | mt352_write(fe, reset, sizeof(reset)); | |
212 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | |
213 | ||
214 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | |
215 | udelay(2000); | |
216 | mt352_write(fe, dntv_extra, sizeof(dntv_extra)); | |
217 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | |
218 | ||
219 | return 0; | |
220 | } | |
221 | ||
fc40b261 CP |
222 | static int philips_fmd1216_pll_init(struct dvb_frontend *fe) |
223 | { | |
224 | struct cx8802_dev *dev= fe->dvb->priv; | |
225 | ||
226 | /* this message is to set up ATC and ALC */ | |
227 | static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; | |
228 | struct i2c_msg msg = | |
229 | { .addr = dev->core->pll_addr, .flags = 0, | |
230 | .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; | |
231 | int err; | |
232 | ||
dea74869 PB |
233 | if (fe->ops.i2c_gate_ctrl) |
234 | fe->ops.i2c_gate_ctrl(fe, 1); | |
fc40b261 CP |
235 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { |
236 | if (err < 0) | |
237 | return err; | |
238 | else | |
239 | return -EREMOTEIO; | |
240 | } | |
241 | ||
242 | return 0; | |
243 | } | |
244 | ||
f54376e2 AQ |
245 | static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe, |
246 | struct dvb_frontend_parameters* params) | |
fc40b261 CP |
247 | { |
248 | struct cx8802_dev *dev= fe->dvb->priv; | |
f54376e2 | 249 | u8 buf[4]; |
fc40b261 CP |
250 | struct i2c_msg msg = |
251 | { .addr = dev->core->pll_addr, .flags = 0, | |
f54376e2 | 252 | .buf = buf, .len = 4 }; |
fc40b261 CP |
253 | int err; |
254 | ||
255 | /* Switch PLL to DVB mode */ | |
256 | err = philips_fmd1216_pll_init(fe); | |
257 | if (err) | |
258 | return err; | |
259 | ||
260 | /* Tune PLL */ | |
f54376e2 | 261 | dvb_pll_configure(dev->core->pll_desc, buf, |
fc40b261 CP |
262 | params->frequency, |
263 | params->u.ofdm.bandwidth); | |
dea74869 PB |
264 | if (fe->ops.i2c_gate_ctrl) |
265 | fe->ops.i2c_gate_ctrl(fe, 1); | |
fc40b261 | 266 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { |
f54376e2 | 267 | |
fc40b261 CP |
268 | printk(KERN_WARNING "cx88-dvb: %s error " |
269 | "(addr %02x <- %02x, err = %i)\n", | |
f54376e2 | 270 | __FUNCTION__, dev->core->pll_addr, buf[0], err); |
fc40b261 CP |
271 | if (err < 0) |
272 | return err; | |
273 | else | |
274 | return -EREMOTEIO; | |
275 | } | |
276 | ||
277 | return 0; | |
278 | } | |
279 | ||
280 | static struct mt352_config dntv_live_dvbt_pro_config = { | |
281 | .demod_address = 0x0f, | |
282 | .no_tuner = 1, | |
3d7d027a | 283 | .demod_init = dntv_live_dvbt_pro_demod_init, |
fc40b261 CP |
284 | }; |
285 | #endif | |
41ef7c1e | 286 | #endif |
1da177e4 | 287 | |
780dfef3 | 288 | #ifdef HAVE_ZL10353 |
f54376e2 AQ |
289 | static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe, |
290 | struct dvb_frontend_parameters *params) | |
780dfef3 | 291 | { |
f54376e2 | 292 | u8 pllbuf[4]; |
780dfef3 CP |
293 | struct cx8802_dev *dev= fe->dvb->priv; |
294 | struct i2c_msg msg = | |
295 | { .addr = dev->core->pll_addr, .flags = 0, | |
f54376e2 | 296 | .buf = pllbuf, .len = 4 }; |
780dfef3 CP |
297 | int err; |
298 | ||
f54376e2 | 299 | dvb_pll_configure(dev->core->pll_desc, pllbuf, |
780dfef3 CP |
300 | params->frequency, |
301 | params->u.ofdm.bandwidth); | |
302 | ||
dea74869 PB |
303 | if (fe->ops.i2c_gate_ctrl) |
304 | fe->ops.i2c_gate_ctrl(fe, 1); | |
780dfef3 CP |
305 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { |
306 | printk(KERN_WARNING "cx88-dvb: %s error " | |
307 | "(addr %02x <- %02x, err = %i)\n", | |
308 | __FUNCTION__, pllbuf[0], pllbuf[1], err); | |
309 | if (err < 0) | |
310 | return err; | |
311 | else | |
312 | return -EREMOTEIO; | |
313 | } | |
314 | ||
315 | return 0; | |
316 | } | |
317 | ||
318 | static struct zl10353_config dvico_fusionhdtv_hybrid = { | |
319 | .demod_address = 0x0F, | |
f54376e2 | 320 | .no_tuner = 1, |
780dfef3 CP |
321 | }; |
322 | ||
323 | static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { | |
324 | .demod_address = 0x0F, | |
780dfef3 CP |
325 | }; |
326 | #endif | |
327 | ||
29780bb7 | 328 | #ifdef HAVE_CX22702 |
1da177e4 LT |
329 | static struct cx22702_config connexant_refboard_config = { |
330 | .demod_address = 0x43, | |
38d84c3b | 331 | .output_mode = CX22702_SERIAL_OUTPUT, |
1da177e4 LT |
332 | }; |
333 | ||
334 | static struct cx22702_config hauppauge_novat_config = { | |
335 | .demod_address = 0x43, | |
38d84c3b | 336 | .output_mode = CX22702_SERIAL_OUTPUT, |
1da177e4 | 337 | }; |
611900c1 ST |
338 | static struct cx22702_config hauppauge_hvr1100_config = { |
339 | .demod_address = 0x63, | |
340 | .output_mode = CX22702_SERIAL_OUTPUT, | |
611900c1 | 341 | }; |
1da177e4 LT |
342 | #endif |
343 | ||
29780bb7 | 344 | #ifdef HAVE_OR51132 |
1da177e4 LT |
345 | static int or51132_set_ts_param(struct dvb_frontend* fe, |
346 | int is_punctured) | |
347 | { | |
348 | struct cx8802_dev *dev= fe->dvb->priv; | |
349 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | |
350 | return 0; | |
351 | } | |
352 | ||
408b664a | 353 | static struct or51132_config pchdtv_hd3000 = { |
1da177e4 | 354 | .demod_address = 0x15, |
1da177e4 LT |
355 | .set_ts_params = or51132_set_ts_param, |
356 | }; | |
357 | #endif | |
358 | ||
6ddcc919 | 359 | #ifdef HAVE_LGDT330X |
f54376e2 | 360 | static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, |
657de3cd | 361 | struct dvb_frontend_parameters* params) |
b6aef071 | 362 | { |
e52e98a7 MCC |
363 | /* FIXME make this routine use the tuner-simple code. |
364 | * It could probably be shared with a number of ATSC | |
365 | * frontends. Many share the same tuner with analog TV. */ | |
366 | ||
b6aef071 | 367 | struct cx8802_dev *dev= fe->dvb->priv; |
e52e98a7 | 368 | struct cx88_core *core = dev->core; |
1963c907 MK |
369 | u8 buf[4]; |
370 | struct i2c_msg msg = | |
371 | { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; | |
372 | int err; | |
373 | ||
e52e98a7 | 374 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); |
1963c907 MK |
375 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", |
376 | __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); | |
f54376e2 | 377 | |
dea74869 PB |
378 | if (fe->ops.i2c_gate_ctrl) |
379 | fe->ops.i2c_gate_ctrl(fe, 1); | |
e52e98a7 | 380 | if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { |
1963c907 MK |
381 | printk(KERN_WARNING "cx88-dvb: %s error " |
382 | "(addr %02x <- %02x, err = %i)\n", | |
383 | __FUNCTION__, buf[0], buf[1], err); | |
384 | if (err < 0) | |
385 | return err; | |
386 | else | |
387 | return -EREMOTEIO; | |
388 | } | |
b6aef071 MK |
389 | return 0; |
390 | } | |
391 | ||
f54376e2 AQ |
392 | static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, |
393 | struct dvb_frontend_parameters* params) | |
7e557743 MK |
394 | { |
395 | struct cx8802_dev *dev= fe->dvb->priv; | |
396 | struct cx88_core *core = dev->core; | |
397 | ||
398 | /* Put the analog decoder in standby to keep it quiet */ | |
399 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | |
400 | ||
401 | return lg_h06xf_pll_set(fe, &core->i2c_adap, params); | |
402 | } | |
403 | ||
6ddcc919 | 404 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) |
0ccef6db MK |
405 | { |
406 | struct cx8802_dev *dev= fe->dvb->priv; | |
407 | struct cx88_core *core = dev->core; | |
408 | ||
409 | dprintk(1, "%s: index = %d\n", __FUNCTION__, index); | |
410 | if (index == 0) | |
411 | cx_clear(MO_GP0_IO, 8); | |
412 | else | |
413 | cx_set(MO_GP0_IO, 8); | |
414 | return 0; | |
415 | } | |
416 | ||
6ddcc919 | 417 | static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) |
f1798495 MK |
418 | { |
419 | struct cx8802_dev *dev= fe->dvb->priv; | |
420 | if (is_punctured) | |
421 | dev->ts_gen_cntrl |= 0x04; | |
422 | else | |
423 | dev->ts_gen_cntrl &= ~0x04; | |
424 | return 0; | |
425 | } | |
426 | ||
6ddcc919 | 427 | static struct lgdt330x_config fusionhdtv_3_gold = { |
0d723c09 | 428 | .demod_address = 0x0e, |
1963c907 MK |
429 | .demod_chip = LGDT3302, |
430 | .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ | |
6ddcc919 | 431 | .set_ts_params = lgdt330x_set_ts_param, |
0d723c09 | 432 | }; |
e52e98a7 MCC |
433 | |
434 | static struct lgdt330x_config fusionhdtv_5_gold = { | |
435 | .demod_address = 0x0e, | |
436 | .demod_chip = LGDT3303, | |
437 | .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ | |
e52e98a7 MCC |
438 | .set_ts_params = lgdt330x_set_ts_param, |
439 | }; | |
da215d22 RS |
440 | |
441 | static struct lgdt330x_config pchdtv_hd5500 = { | |
442 | .demod_address = 0x59, | |
443 | .demod_chip = LGDT3303, | |
444 | .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ | |
da215d22 RS |
445 | .set_ts_params = lgdt330x_set_ts_param, |
446 | }; | |
f1798495 MK |
447 | #endif |
448 | ||
fde6d31e KL |
449 | #ifdef HAVE_NXT200X |
450 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, | |
451 | int is_punctured) | |
452 | { | |
453 | struct cx8802_dev *dev= fe->dvb->priv; | |
454 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | |
455 | return 0; | |
456 | } | |
457 | ||
d4c34aa0 KL |
458 | static int nxt200x_set_pll_input(u8* buf, int input) |
459 | { | |
460 | if (input) | |
461 | buf[3] |= 0x08; | |
462 | else | |
463 | buf[3] &= ~0x08; | |
464 | return 0; | |
465 | } | |
466 | ||
fde6d31e KL |
467 | static struct nxt200x_config ati_hdtvwonder = { |
468 | .demod_address = 0x0a, | |
d4c34aa0 | 469 | .set_pll_input = nxt200x_set_pll_input, |
fde6d31e KL |
470 | .set_ts_params = nxt200x_set_ts_param, |
471 | }; | |
472 | #endif | |
473 | ||
0fa14aa6 ST |
474 | #ifdef HAVE_CX24123 |
475 | static int cx24123_set_ts_param(struct dvb_frontend* fe, | |
476 | int is_punctured) | |
477 | { | |
478 | struct cx8802_dev *dev= fe->dvb->priv; | |
479 | dev->ts_gen_cntrl = 0x2; | |
480 | return 0; | |
481 | } | |
482 | ||
cd20ca9f | 483 | static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) |
0e0351e3 VC |
484 | { |
485 | struct cx8802_dev *dev= fe->dvb->priv; | |
486 | struct cx88_core *core = dev->core; | |
487 | ||
cd20ca9f | 488 | if (voltage == SEC_VOLTAGE_OFF) { |
0e0351e3 | 489 | cx_write(MO_GP0_IO, 0x000006fB); |
cd20ca9f AQ |
490 | } else { |
491 | cx_write(MO_GP0_IO, 0x000006f9); | |
492 | } | |
493 | ||
494 | if (core->prev_set_voltage) | |
495 | return core->prev_set_voltage(fe, voltage); | |
496 | return 0; | |
0e0351e3 VC |
497 | } |
498 | ||
c02a34f4 SA |
499 | static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
500 | { | |
501 | struct cx8802_dev *dev= fe->dvb->priv; | |
502 | struct cx88_core *core = dev->core; | |
503 | ||
504 | if (voltage == SEC_VOLTAGE_OFF) { | |
505 | dprintk(1,"LNB Voltage OFF\n"); | |
506 | cx_write(MO_GP0_IO, 0x0000efff); | |
507 | } | |
508 | ||
509 | if (core->prev_set_voltage) | |
510 | return core->prev_set_voltage(fe, voltage); | |
511 | return 0; | |
512 | } | |
513 | ||
514 | static struct cx24123_config geniatech_dvbs_config = { | |
515 | .demod_address = 0x55, | |
516 | .set_ts_params = cx24123_set_ts_param, | |
517 | }; | |
518 | ||
0fa14aa6 | 519 | static struct cx24123_config hauppauge_novas_config = { |
0e0351e3 | 520 | .demod_address = 0x55, |
0e0351e3 VC |
521 | .set_ts_params = cx24123_set_ts_param, |
522 | }; | |
523 | ||
524 | static struct cx24123_config kworld_dvbs_100_config = { | |
525 | .demod_address = 0x15, | |
0e0351e3 | 526 | .set_ts_params = cx24123_set_ts_param, |
0fa14aa6 ST |
527 | }; |
528 | #endif | |
529 | ||
1da177e4 LT |
530 | static int dvb_register(struct cx8802_dev *dev) |
531 | { | |
532 | /* init struct videobuf_dvb */ | |
533 | dev->dvb.name = dev->core->name; | |
534 | dev->ts_gen_cntrl = 0x0c; | |
535 | ||
536 | /* init frontend */ | |
537 | switch (dev->core->board) { | |
29780bb7 | 538 | #ifdef HAVE_CX22702 |
1da177e4 LT |
539 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
540 | dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, | |
541 | &dev->core->i2c_adap); | |
f54376e2 | 542 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
543 | dvb_pll_attach(dev->dvb.frontend, 0x61, |
544 | &dev->core->i2c_adap, | |
545 | &dvb_pll_thomson_dtt759x); | |
f54376e2 | 546 | } |
1da177e4 | 547 | break; |
e057ee11 | 548 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
1da177e4 | 549 | case CX88_BOARD_CONEXANT_DVB_T1: |
f39624fd | 550 | case CX88_BOARD_KWORLD_DVB_T_CX22702: |
2b5200a7 | 551 | case CX88_BOARD_WINFAST_DTV1000: |
1da177e4 LT |
552 | dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, |
553 | &dev->core->i2c_adap); | |
f54376e2 | 554 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
555 | dvb_pll_attach(dev->dvb.frontend, 0x60, |
556 | &dev->core->i2c_adap, | |
557 | &dvb_pll_thomson_dtt7579); | |
f54376e2 | 558 | } |
1da177e4 | 559 | break; |
4bd6e9d9 | 560 | case CX88_BOARD_WINFAST_DTV2000H: |
611900c1 ST |
561 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
562 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | |
563 | dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, | |
564 | &dev->core->i2c_adap); | |
f54376e2 | 565 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
566 | dvb_pll_attach(dev->dvb.frontend, 0x61, |
567 | &dev->core->i2c_adap, | |
568 | &dvb_pll_fmd1216me); | |
f54376e2 | 569 | } |
611900c1 | 570 | break; |
1da177e4 | 571 | #endif |
780dfef3 CP |
572 | #if defined(HAVE_MT352) || defined(HAVE_ZL10353) |
573 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | |
29780bb7 | 574 | #ifdef HAVE_MT352 |
1da177e4 LT |
575 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, |
576 | &dev->core->i2c_adap); | |
f54376e2 | 577 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
578 | dvb_pll_attach(dev->dvb.frontend, 0x60, |
579 | &dev->core->i2c_adap, | |
580 | &dvb_pll_thomson_dtt7579); | |
780dfef3 | 581 | break; |
f54376e2 | 582 | } |
780dfef3 CP |
583 | #endif |
584 | #ifdef HAVE_ZL10353 | |
585 | /* ZL10353 replaces MT352 on later cards */ | |
586 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, | |
587 | &dev->core->i2c_adap); | |
f54376e2 | 588 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
589 | dvb_pll_attach(dev->dvb.frontend, 0x60, |
590 | &dev->core->i2c_adap, | |
591 | &dvb_pll_thomson_dtt7579); | |
f54376e2 | 592 | } |
c2af3cd6 MK |
593 | #endif |
594 | break; | |
595 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: | |
596 | #ifdef HAVE_MT352 | |
597 | /* The tin box says DEE1601, but it seems to be DTT7579 | |
598 | * compatible, with a slightly different MT352 AGC gain. */ | |
599 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, | |
600 | &dev->core->i2c_adap); | |
601 | if (dev->dvb.frontend != NULL) { | |
0f102910 MK |
602 | dvb_pll_attach(dev->dvb.frontend, 0x61, |
603 | &dev->core->i2c_adap, | |
604 | &dvb_pll_thomson_dtt7579); | |
c2af3cd6 MK |
605 | break; |
606 | } | |
607 | #endif | |
608 | #ifdef HAVE_ZL10353 | |
609 | /* ZL10353 replaces MT352 on later cards */ | |
610 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, | |
611 | &dev->core->i2c_adap); | |
612 | if (dev->dvb.frontend != NULL) { | |
0f102910 MK |
613 | dvb_pll_attach(dev->dvb.frontend, 0x61, |
614 | &dev->core->i2c_adap, | |
615 | &dvb_pll_thomson_dtt7579); | |
c2af3cd6 | 616 | } |
780dfef3 | 617 | #endif |
1da177e4 | 618 | break; |
780dfef3 CP |
619 | #endif /* HAVE_MT352 || HAVE_ZL10353 */ |
620 | #ifdef HAVE_MT352 | |
621 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: | |
1da177e4 LT |
622 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, |
623 | &dev->core->i2c_adap); | |
f54376e2 | 624 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
625 | dvb_pll_attach(dev->dvb.frontend, 0x61, |
626 | &dev->core->i2c_adap, | |
627 | &dvb_pll_lg_z201); | |
f54376e2 | 628 | } |
1da177e4 LT |
629 | break; |
630 | case CX88_BOARD_KWORLD_DVB_T: | |
631 | case CX88_BOARD_DNTV_LIVE_DVB_T: | |
a82decf6 | 632 | case CX88_BOARD_ADSTECH_DVB_T_PCI: |
1da177e4 LT |
633 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, |
634 | &dev->core->i2c_adap); | |
f54376e2 | 635 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
636 | dvb_pll_attach(dev->dvb.frontend, 0x61, |
637 | &dev->core->i2c_adap, | |
638 | &dvb_pll_unknown_1); | |
f54376e2 | 639 | } |
1da177e4 | 640 | break; |
fc40b261 CP |
641 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
642 | #ifdef HAVE_VP3054_I2C | |
643 | dev->core->pll_addr = 0x61; | |
644 | dev->core->pll_desc = &dvb_pll_fmd1216me; | |
645 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, | |
646 | &((struct vp3054_i2c_state *)dev->card_priv)->adap); | |
f54376e2 | 647 | if (dev->dvb.frontend != NULL) { |
dea74869 | 648 | dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params; |
f54376e2 | 649 | } |
fc40b261 CP |
650 | #else |
651 | printk("%s: built without vp3054 support\n", dev->core->name); | |
652 | #endif | |
653 | break; | |
66dd0fcc | 654 | #endif |
780dfef3 CP |
655 | #ifdef HAVE_ZL10353 |
656 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | |
657 | dev->core->pll_addr = 0x61; | |
91ae3299 | 658 | dev->core->pll_desc = &dvb_pll_thomson_fe6600; |
780dfef3 CP |
659 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, |
660 | &dev->core->i2c_adap); | |
f54376e2 | 661 | if (dev->dvb.frontend != NULL) { |
dea74869 | 662 | dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; |
f54376e2 | 663 | } |
780dfef3 CP |
664 | break; |
665 | #endif | |
29780bb7 | 666 | #ifdef HAVE_OR51132 |
1da177e4 LT |
667 | case CX88_BOARD_PCHDTV_HD3000: |
668 | dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, | |
669 | &dev->core->i2c_adap); | |
f54376e2 | 670 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
671 | dvb_pll_attach(dev->dvb.frontend, 0x61, |
672 | &dev->core->i2c_adap, | |
673 | &dvb_pll_thomson_dtt761x); | |
f54376e2 | 674 | } |
1da177e4 | 675 | break; |
f1798495 | 676 | #endif |
6ddcc919 | 677 | #ifdef HAVE_LGDT330X |
f1798495 MK |
678 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: |
679 | dev->ts_gen_cntrl = 0x08; | |
680 | { | |
681 | /* Do a hardware reset of chip before using it. */ | |
682 | struct cx88_core *core = dev->core; | |
683 | ||
684 | cx_clear(MO_GP0_IO, 1); | |
685 | mdelay(100); | |
0ccef6db | 686 | cx_set(MO_GP0_IO, 1); |
f1798495 | 687 | mdelay(200); |
0ccef6db MK |
688 | |
689 | /* Select RF connector callback */ | |
6ddcc919 | 690 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; |
b6aef071 MK |
691 | dev->core->pll_addr = 0x61; |
692 | dev->core->pll_desc = &dvb_pll_microtune_4042; | |
6ddcc919 | 693 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
f1798495 | 694 | &dev->core->i2c_adap); |
f54376e2 | 695 | if (dev->dvb.frontend != NULL) { |
dea74869 | 696 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; |
f54376e2 | 697 | } |
f1798495 MK |
698 | } |
699 | break; | |
0d723c09 MK |
700 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: |
701 | dev->ts_gen_cntrl = 0x08; | |
702 | { | |
703 | /* Do a hardware reset of chip before using it. */ | |
704 | struct cx88_core *core = dev->core; | |
705 | ||
706 | cx_clear(MO_GP0_IO, 1); | |
707 | mdelay(100); | |
d975872c | 708 | cx_set(MO_GP0_IO, 9); |
0d723c09 | 709 | mdelay(200); |
b6aef071 | 710 | dev->core->pll_addr = 0x61; |
83ac8722 | 711 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; |
6ddcc919 | 712 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
0d723c09 | 713 | &dev->core->i2c_adap); |
f54376e2 | 714 | if (dev->dvb.frontend != NULL) { |
dea74869 | 715 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; |
f54376e2 | 716 | } |
0d723c09 MK |
717 | } |
718 | break; | |
e52e98a7 MCC |
719 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: |
720 | dev->ts_gen_cntrl = 0x08; | |
721 | { | |
722 | /* Do a hardware reset of chip before using it. */ | |
723 | struct cx88_core *core = dev->core; | |
724 | ||
725 | cx_clear(MO_GP0_IO, 1); | |
726 | mdelay(100); | |
727 | cx_set(MO_GP0_IO, 1); | |
728 | mdelay(200); | |
e52e98a7 MCC |
729 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold, |
730 | &dev->core->i2c_adap); | |
f54376e2 | 731 | if (dev->dvb.frontend != NULL) { |
dea74869 | 732 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; |
f54376e2 | 733 | } |
e52e98a7 MCC |
734 | } |
735 | break; | |
da215d22 RS |
736 | case CX88_BOARD_PCHDTV_HD5500: |
737 | dev->ts_gen_cntrl = 0x08; | |
738 | { | |
739 | /* Do a hardware reset of chip before using it. */ | |
740 | struct cx88_core *core = dev->core; | |
741 | ||
742 | cx_clear(MO_GP0_IO, 1); | |
743 | mdelay(100); | |
744 | cx_set(MO_GP0_IO, 1); | |
745 | mdelay(200); | |
da215d22 RS |
746 | dev->dvb.frontend = lgdt330x_attach(&pchdtv_hd5500, |
747 | &dev->core->i2c_adap); | |
f54376e2 | 748 | if (dev->dvb.frontend != NULL) { |
dea74869 | 749 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; |
f54376e2 | 750 | } |
da215d22 RS |
751 | } |
752 | break; | |
fde6d31e KL |
753 | #endif |
754 | #ifdef HAVE_NXT200X | |
755 | case CX88_BOARD_ATI_HDTVWONDER: | |
756 | dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder, | |
757 | &dev->core->i2c_adap); | |
f54376e2 | 758 | if (dev->dvb.frontend != NULL) { |
0f102910 MK |
759 | dvb_pll_attach(dev->dvb.frontend, 0x61, |
760 | &dev->core->i2c_adap, | |
761 | &dvb_pll_tuv1236d); | |
f54376e2 | 762 | } |
0fa14aa6 ST |
763 | break; |
764 | #endif | |
765 | #ifdef HAVE_CX24123 | |
766 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | |
767 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | |
768 | dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, | |
769 | &dev->core->i2c_adap); | |
cd20ca9f | 770 | if (dev->dvb.frontend) { |
0f102910 MK |
771 | isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap, |
772 | 0x08, 0x00, 0x00); | |
cd20ca9f | 773 | } |
0e0351e3 VC |
774 | break; |
775 | case CX88_BOARD_KWORLD_DVBS_100: | |
776 | dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, | |
777 | &dev->core->i2c_adap); | |
cd20ca9f | 778 | if (dev->dvb.frontend) { |
dea74869 PB |
779 | dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; |
780 | dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; | |
cd20ca9f | 781 | } |
fde6d31e | 782 | break; |
c02a34f4 SA |
783 | case CX88_BOARD_GENIATECH_DVBS: |
784 | dev->dvb.frontend = cx24123_attach(&geniatech_dvbs_config, | |
785 | &dev->core->i2c_adap); | |
786 | if (dev->dvb.frontend) { | |
787 | dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | |
788 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; | |
789 | } | |
790 | break; | |
1da177e4 LT |
791 | #endif |
792 | default: | |
1622c3fc GK |
793 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
794 | dev->core->name); | |
1da177e4 LT |
795 | break; |
796 | } | |
797 | if (NULL == dev->dvb.frontend) { | |
798 | printk("%s: frontend initialization failed\n",dev->core->name); | |
799 | return -1; | |
800 | } | |
801 | ||
802 | if (dev->core->pll_desc) { | |
dea74869 PB |
803 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; |
804 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; | |
1da177e4 LT |
805 | } |
806 | ||
93352f5c MCC |
807 | /* Put the analog decoder in standby to keep it quiet */ |
808 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | |
809 | ||
1da177e4 | 810 | /* register everything */ |
d09dbf92 | 811 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); |
1da177e4 LT |
812 | } |
813 | ||
814 | /* ----------------------------------------------------------- */ | |
815 | ||
816 | static int __devinit dvb_probe(struct pci_dev *pci_dev, | |
817 | const struct pci_device_id *pci_id) | |
818 | { | |
819 | struct cx8802_dev *dev; | |
820 | struct cx88_core *core; | |
821 | int err; | |
822 | ||
823 | /* general setup */ | |
824 | core = cx88_core_get(pci_dev); | |
825 | if (NULL == core) | |
826 | return -EINVAL; | |
827 | ||
828 | err = -ENODEV; | |
829 | if (!cx88_boards[core->board].dvb) | |
830 | goto fail_core; | |
831 | ||
832 | err = -ENOMEM; | |
7408187d | 833 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); |
1da177e4 LT |
834 | if (NULL == dev) |
835 | goto fail_core; | |
1da177e4 LT |
836 | dev->pci = pci_dev; |
837 | dev->core = core; | |
838 | ||
839 | err = cx8802_init_common(dev); | |
840 | if (0 != err) | |
841 | goto fail_free; | |
842 | ||
fc40b261 CP |
843 | #ifdef HAVE_VP3054_I2C |
844 | err = vp3054_i2c_probe(dev); | |
845 | if (0 != err) | |
846 | goto fail_free; | |
847 | #endif | |
848 | ||
1da177e4 LT |
849 | /* dvb stuff */ |
850 | printk("%s/2: cx2388x based dvb card\n", core->name); | |
851 | videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, | |
852 | dev->pci, &dev->slock, | |
853 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | |
854 | V4L2_FIELD_TOP, | |
855 | sizeof(struct cx88_buffer), | |
856 | dev); | |
857 | err = dvb_register(dev); | |
858 | if (0 != err) | |
1622c3fc | 859 | goto fail_fini; |
611900c1 ST |
860 | |
861 | /* Maintain a reference to cx88-video can query the 8802 device. */ | |
862 | core->dvbdev = dev; | |
1da177e4 LT |
863 | return 0; |
864 | ||
1622c3fc GK |
865 | fail_fini: |
866 | cx8802_fini_common(dev); | |
1da177e4 LT |
867 | fail_free: |
868 | kfree(dev); | |
869 | fail_core: | |
870 | cx88_core_put(core,pci_dev); | |
871 | return err; | |
872 | } | |
873 | ||
874 | static void __devexit dvb_remove(struct pci_dev *pci_dev) | |
875 | { | |
4ac97914 | 876 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); |
1da177e4 | 877 | |
611900c1 ST |
878 | /* Destroy any 8802 reference. */ |
879 | dev->core->dvbdev = NULL; | |
880 | ||
1da177e4 LT |
881 | /* dvb */ |
882 | videobuf_dvb_unregister(&dev->dvb); | |
883 | ||
fc40b261 CP |
884 | #ifdef HAVE_VP3054_I2C |
885 | vp3054_i2c_remove(dev); | |
886 | #endif | |
887 | ||
1da177e4 LT |
888 | /* common */ |
889 | cx8802_fini_common(dev); | |
890 | cx88_core_put(dev->core,dev->pci); | |
891 | kfree(dev); | |
892 | } | |
893 | ||
894 | static struct pci_device_id cx8802_pci_tbl[] = { | |
895 | { | |
896 | .vendor = 0x14f1, | |
897 | .device = 0x8802, | |
4ac97914 MCC |
898 | .subvendor = PCI_ANY_ID, |
899 | .subdevice = PCI_ANY_ID, | |
1da177e4 LT |
900 | },{ |
901 | /* --- end of list --- */ | |
902 | } | |
903 | }; | |
904 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | |
905 | ||
906 | static struct pci_driver dvb_pci_driver = { | |
4ac97914 MCC |
907 | .name = "cx88-dvb", |
908 | .id_table = cx8802_pci_tbl, | |
909 | .probe = dvb_probe, | |
910 | .remove = __devexit_p(dvb_remove), | |
1da177e4 LT |
911 | .suspend = cx8802_suspend_common, |
912 | .resume = cx8802_resume_common, | |
913 | }; | |
914 | ||
915 | static int dvb_init(void) | |
916 | { | |
917 | printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n", | |
918 | (CX88_VERSION_CODE >> 16) & 0xff, | |
919 | (CX88_VERSION_CODE >> 8) & 0xff, | |
920 | CX88_VERSION_CODE & 0xff); | |
921 | #ifdef SNAPSHOT | |
922 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | |
923 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | |
924 | #endif | |
925 | return pci_register_driver(&dvb_pci_driver); | |
926 | } | |
927 | ||
928 | static void dvb_fini(void) | |
929 | { | |
930 | pci_unregister_driver(&dvb_pci_driver); | |
931 | } | |
932 | ||
933 | module_init(dvb_init); | |
934 | module_exit(dvb_fini); | |
935 | ||
936 | /* | |
937 | * Local variables: | |
938 | * c-basic-offset: 8 | |
939 | * compile-command: "make DVB=1" | |
940 | * End: | |
941 | */ |