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 AQ |
360 | static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, |
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 | ||
0fa14aa6 | 499 | static struct cx24123_config hauppauge_novas_config = { |
0e0351e3 | 500 | .demod_address = 0x55, |
0e0351e3 VC |
501 | .set_ts_params = cx24123_set_ts_param, |
502 | }; | |
503 | ||
504 | static struct cx24123_config kworld_dvbs_100_config = { | |
505 | .demod_address = 0x15, | |
0e0351e3 | 506 | .set_ts_params = cx24123_set_ts_param, |
0fa14aa6 ST |
507 | }; |
508 | #endif | |
509 | ||
1da177e4 LT |
510 | static int dvb_register(struct cx8802_dev *dev) |
511 | { | |
512 | /* init struct videobuf_dvb */ | |
513 | dev->dvb.name = dev->core->name; | |
514 | dev->ts_gen_cntrl = 0x0c; | |
515 | ||
516 | /* init frontend */ | |
517 | switch (dev->core->board) { | |
29780bb7 | 518 | #ifdef HAVE_CX22702 |
1da177e4 LT |
519 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
520 | dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, | |
521 | &dev->core->i2c_adap); | |
f54376e2 AQ |
522 | if (dev->dvb.frontend != NULL) { |
523 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_thomson_dtt759x); | |
524 | } | |
1da177e4 | 525 | break; |
e057ee11 | 526 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
1da177e4 | 527 | case CX88_BOARD_CONEXANT_DVB_T1: |
f39624fd | 528 | case CX88_BOARD_KWORLD_DVB_T_CX22702: |
2b5200a7 | 529 | case CX88_BOARD_WINFAST_DTV1000: |
1da177e4 LT |
530 | dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, |
531 | &dev->core->i2c_adap); | |
f54376e2 AQ |
532 | if (dev->dvb.frontend != NULL) { |
533 | dvb_pll_attach(dev->dvb.frontend, 0x60, &dev->core->i2c_adap, &dvb_pll_thomson_dtt7579); | |
534 | } | |
1da177e4 | 535 | break; |
611900c1 ST |
536 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
537 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | |
538 | dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, | |
539 | &dev->core->i2c_adap); | |
f54376e2 AQ |
540 | if (dev->dvb.frontend != NULL) { |
541 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_fmd1216me); | |
542 | } | |
611900c1 | 543 | break; |
1da177e4 | 544 | #endif |
780dfef3 CP |
545 | #if defined(HAVE_MT352) || defined(HAVE_ZL10353) |
546 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | |
29780bb7 | 547 | #ifdef HAVE_MT352 |
1da177e4 LT |
548 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, |
549 | &dev->core->i2c_adap); | |
f54376e2 AQ |
550 | if (dev->dvb.frontend != NULL) { |
551 | dvb_pll_attach(dev->dvb.frontend, 0x60, &dev->core->i2c_adap, &dvb_pll_thomson_dtt7579); | |
780dfef3 | 552 | break; |
f54376e2 | 553 | } |
780dfef3 CP |
554 | #endif |
555 | #ifdef HAVE_ZL10353 | |
556 | /* ZL10353 replaces MT352 on later cards */ | |
557 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, | |
558 | &dev->core->i2c_adap); | |
f54376e2 AQ |
559 | if (dev->dvb.frontend != NULL) { |
560 | dvb_pll_attach(dev->dvb.frontend, 0x60, &dev->core->i2c_adap, &dvb_pll_thomson_dtt7579); | |
561 | } | |
780dfef3 | 562 | #endif |
1da177e4 | 563 | break; |
780dfef3 CP |
564 | #endif /* HAVE_MT352 || HAVE_ZL10353 */ |
565 | #ifdef HAVE_MT352 | |
566 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: | |
1da177e4 LT |
567 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, |
568 | &dev->core->i2c_adap); | |
f54376e2 AQ |
569 | if (dev->dvb.frontend != NULL) { |
570 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_lg_z201); | |
571 | } | |
1da177e4 LT |
572 | break; |
573 | case CX88_BOARD_KWORLD_DVB_T: | |
574 | case CX88_BOARD_DNTV_LIVE_DVB_T: | |
a82decf6 | 575 | case CX88_BOARD_ADSTECH_DVB_T_PCI: |
1da177e4 LT |
576 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, |
577 | &dev->core->i2c_adap); | |
f54376e2 AQ |
578 | if (dev->dvb.frontend != NULL) { |
579 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_unknown_1); | |
580 | } | |
1da177e4 | 581 | break; |
fc40b261 CP |
582 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
583 | #ifdef HAVE_VP3054_I2C | |
584 | dev->core->pll_addr = 0x61; | |
585 | dev->core->pll_desc = &dvb_pll_fmd1216me; | |
586 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, | |
587 | &((struct vp3054_i2c_state *)dev->card_priv)->adap); | |
f54376e2 | 588 | if (dev->dvb.frontend != NULL) { |
dea74869 | 589 | dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params; |
f54376e2 | 590 | } |
fc40b261 CP |
591 | #else |
592 | printk("%s: built without vp3054 support\n", dev->core->name); | |
593 | #endif | |
594 | break; | |
43eabb4e CP |
595 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: |
596 | /* The tin box says DEE1601, but it seems to be DTT7579 | |
597 | * compatible, with a slightly different MT352 AGC gain. */ | |
43eabb4e CP |
598 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, |
599 | &dev->core->i2c_adap); | |
f54376e2 AQ |
600 | if (dev->dvb.frontend != NULL) { |
601 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_thomson_dtt7579); | |
602 | } | |
43eabb4e | 603 | break; |
41ef7c1e | 604 | #endif |
780dfef3 CP |
605 | #ifdef HAVE_ZL10353 |
606 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | |
607 | dev->core->pll_addr = 0x61; | |
91ae3299 | 608 | dev->core->pll_desc = &dvb_pll_thomson_fe6600; |
780dfef3 CP |
609 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, |
610 | &dev->core->i2c_adap); | |
f54376e2 | 611 | if (dev->dvb.frontend != NULL) { |
dea74869 | 612 | dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; |
f54376e2 | 613 | } |
780dfef3 CP |
614 | break; |
615 | #endif | |
29780bb7 | 616 | #ifdef HAVE_OR51132 |
1da177e4 LT |
617 | case CX88_BOARD_PCHDTV_HD3000: |
618 | dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, | |
619 | &dev->core->i2c_adap); | |
f54376e2 AQ |
620 | if (dev->dvb.frontend != NULL) { |
621 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_thomson_dtt761x); | |
622 | } | |
1da177e4 | 623 | break; |
f1798495 | 624 | #endif |
6ddcc919 | 625 | #ifdef HAVE_LGDT330X |
f1798495 MK |
626 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: |
627 | dev->ts_gen_cntrl = 0x08; | |
628 | { | |
629 | /* Do a hardware reset of chip before using it. */ | |
630 | struct cx88_core *core = dev->core; | |
631 | ||
632 | cx_clear(MO_GP0_IO, 1); | |
633 | mdelay(100); | |
0ccef6db | 634 | cx_set(MO_GP0_IO, 1); |
f1798495 | 635 | mdelay(200); |
0ccef6db MK |
636 | |
637 | /* Select RF connector callback */ | |
6ddcc919 | 638 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; |
b6aef071 MK |
639 | dev->core->pll_addr = 0x61; |
640 | dev->core->pll_desc = &dvb_pll_microtune_4042; | |
6ddcc919 | 641 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
f1798495 | 642 | &dev->core->i2c_adap); |
f54376e2 | 643 | if (dev->dvb.frontend != NULL) { |
dea74869 | 644 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; |
f54376e2 | 645 | } |
f1798495 MK |
646 | } |
647 | break; | |
0d723c09 MK |
648 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: |
649 | dev->ts_gen_cntrl = 0x08; | |
650 | { | |
651 | /* Do a hardware reset of chip before using it. */ | |
652 | struct cx88_core *core = dev->core; | |
653 | ||
654 | cx_clear(MO_GP0_IO, 1); | |
655 | mdelay(100); | |
d975872c | 656 | cx_set(MO_GP0_IO, 9); |
0d723c09 | 657 | mdelay(200); |
b6aef071 | 658 | dev->core->pll_addr = 0x61; |
83ac8722 | 659 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; |
6ddcc919 | 660 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
0d723c09 | 661 | &dev->core->i2c_adap); |
f54376e2 | 662 | if (dev->dvb.frontend != NULL) { |
dea74869 | 663 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; |
f54376e2 | 664 | } |
0d723c09 MK |
665 | } |
666 | break; | |
e52e98a7 MCC |
667 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: |
668 | dev->ts_gen_cntrl = 0x08; | |
669 | { | |
670 | /* Do a hardware reset of chip before using it. */ | |
671 | struct cx88_core *core = dev->core; | |
672 | ||
673 | cx_clear(MO_GP0_IO, 1); | |
674 | mdelay(100); | |
675 | cx_set(MO_GP0_IO, 1); | |
676 | mdelay(200); | |
e52e98a7 MCC |
677 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold, |
678 | &dev->core->i2c_adap); | |
f54376e2 | 679 | if (dev->dvb.frontend != NULL) { |
dea74869 | 680 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; |
f54376e2 | 681 | } |
e52e98a7 MCC |
682 | } |
683 | break; | |
da215d22 RS |
684 | case CX88_BOARD_PCHDTV_HD5500: |
685 | dev->ts_gen_cntrl = 0x08; | |
686 | { | |
687 | /* Do a hardware reset of chip before using it. */ | |
688 | struct cx88_core *core = dev->core; | |
689 | ||
690 | cx_clear(MO_GP0_IO, 1); | |
691 | mdelay(100); | |
692 | cx_set(MO_GP0_IO, 1); | |
693 | mdelay(200); | |
da215d22 RS |
694 | dev->dvb.frontend = lgdt330x_attach(&pchdtv_hd5500, |
695 | &dev->core->i2c_adap); | |
f54376e2 | 696 | if (dev->dvb.frontend != NULL) { |
dea74869 | 697 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; |
f54376e2 | 698 | } |
da215d22 RS |
699 | } |
700 | break; | |
fde6d31e KL |
701 | #endif |
702 | #ifdef HAVE_NXT200X | |
703 | case CX88_BOARD_ATI_HDTVWONDER: | |
704 | dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder, | |
705 | &dev->core->i2c_adap); | |
f54376e2 AQ |
706 | if (dev->dvb.frontend != NULL) { |
707 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->core->i2c_adap, &dvb_pll_tuv1236d); | |
708 | } | |
0fa14aa6 ST |
709 | break; |
710 | #endif | |
711 | #ifdef HAVE_CX24123 | |
712 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | |
713 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | |
714 | dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, | |
715 | &dev->core->i2c_adap); | |
cd20ca9f AQ |
716 | if (dev->dvb.frontend) { |
717 | isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap, 0x08, 0x00, 0x00); | |
718 | } | |
0e0351e3 VC |
719 | break; |
720 | case CX88_BOARD_KWORLD_DVBS_100: | |
721 | dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, | |
722 | &dev->core->i2c_adap); | |
cd20ca9f | 723 | if (dev->dvb.frontend) { |
dea74869 PB |
724 | dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; |
725 | dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; | |
cd20ca9f | 726 | } |
fde6d31e | 727 | break; |
1da177e4 LT |
728 | #endif |
729 | default: | |
1622c3fc GK |
730 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
731 | dev->core->name); | |
1da177e4 LT |
732 | break; |
733 | } | |
734 | if (NULL == dev->dvb.frontend) { | |
735 | printk("%s: frontend initialization failed\n",dev->core->name); | |
736 | return -1; | |
737 | } | |
738 | ||
739 | if (dev->core->pll_desc) { | |
dea74869 PB |
740 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; |
741 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; | |
1da177e4 LT |
742 | } |
743 | ||
93352f5c MCC |
744 | /* Put the analog decoder in standby to keep it quiet */ |
745 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | |
746 | ||
1da177e4 | 747 | /* register everything */ |
d09dbf92 | 748 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); |
1da177e4 LT |
749 | } |
750 | ||
751 | /* ----------------------------------------------------------- */ | |
752 | ||
753 | static int __devinit dvb_probe(struct pci_dev *pci_dev, | |
754 | const struct pci_device_id *pci_id) | |
755 | { | |
756 | struct cx8802_dev *dev; | |
757 | struct cx88_core *core; | |
758 | int err; | |
759 | ||
760 | /* general setup */ | |
761 | core = cx88_core_get(pci_dev); | |
762 | if (NULL == core) | |
763 | return -EINVAL; | |
764 | ||
765 | err = -ENODEV; | |
766 | if (!cx88_boards[core->board].dvb) | |
767 | goto fail_core; | |
768 | ||
769 | err = -ENOMEM; | |
7408187d | 770 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); |
1da177e4 LT |
771 | if (NULL == dev) |
772 | goto fail_core; | |
1da177e4 LT |
773 | dev->pci = pci_dev; |
774 | dev->core = core; | |
775 | ||
776 | err = cx8802_init_common(dev); | |
777 | if (0 != err) | |
778 | goto fail_free; | |
779 | ||
fc40b261 CP |
780 | #ifdef HAVE_VP3054_I2C |
781 | err = vp3054_i2c_probe(dev); | |
782 | if (0 != err) | |
783 | goto fail_free; | |
784 | #endif | |
785 | ||
1da177e4 LT |
786 | /* dvb stuff */ |
787 | printk("%s/2: cx2388x based dvb card\n", core->name); | |
788 | videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, | |
789 | dev->pci, &dev->slock, | |
790 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | |
791 | V4L2_FIELD_TOP, | |
792 | sizeof(struct cx88_buffer), | |
793 | dev); | |
794 | err = dvb_register(dev); | |
795 | if (0 != err) | |
1622c3fc | 796 | goto fail_fini; |
611900c1 ST |
797 | |
798 | /* Maintain a reference to cx88-video can query the 8802 device. */ | |
799 | core->dvbdev = dev; | |
1da177e4 LT |
800 | return 0; |
801 | ||
1622c3fc GK |
802 | fail_fini: |
803 | cx8802_fini_common(dev); | |
1da177e4 LT |
804 | fail_free: |
805 | kfree(dev); | |
806 | fail_core: | |
807 | cx88_core_put(core,pci_dev); | |
808 | return err; | |
809 | } | |
810 | ||
811 | static void __devexit dvb_remove(struct pci_dev *pci_dev) | |
812 | { | |
4ac97914 | 813 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); |
1da177e4 | 814 | |
611900c1 ST |
815 | /* Destroy any 8802 reference. */ |
816 | dev->core->dvbdev = NULL; | |
817 | ||
1da177e4 LT |
818 | /* dvb */ |
819 | videobuf_dvb_unregister(&dev->dvb); | |
820 | ||
fc40b261 CP |
821 | #ifdef HAVE_VP3054_I2C |
822 | vp3054_i2c_remove(dev); | |
823 | #endif | |
824 | ||
1da177e4 LT |
825 | /* common */ |
826 | cx8802_fini_common(dev); | |
827 | cx88_core_put(dev->core,dev->pci); | |
828 | kfree(dev); | |
829 | } | |
830 | ||
831 | static struct pci_device_id cx8802_pci_tbl[] = { | |
832 | { | |
833 | .vendor = 0x14f1, | |
834 | .device = 0x8802, | |
4ac97914 MCC |
835 | .subvendor = PCI_ANY_ID, |
836 | .subdevice = PCI_ANY_ID, | |
1da177e4 LT |
837 | },{ |
838 | /* --- end of list --- */ | |
839 | } | |
840 | }; | |
841 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | |
842 | ||
843 | static struct pci_driver dvb_pci_driver = { | |
4ac97914 MCC |
844 | .name = "cx88-dvb", |
845 | .id_table = cx8802_pci_tbl, | |
846 | .probe = dvb_probe, | |
847 | .remove = __devexit_p(dvb_remove), | |
1da177e4 LT |
848 | .suspend = cx8802_suspend_common, |
849 | .resume = cx8802_resume_common, | |
850 | }; | |
851 | ||
852 | static int dvb_init(void) | |
853 | { | |
854 | printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n", | |
855 | (CX88_VERSION_CODE >> 16) & 0xff, | |
856 | (CX88_VERSION_CODE >> 8) & 0xff, | |
857 | CX88_VERSION_CODE & 0xff); | |
858 | #ifdef SNAPSHOT | |
859 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | |
860 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | |
861 | #endif | |
862 | return pci_register_driver(&dvb_pci_driver); | |
863 | } | |
864 | ||
865 | static void dvb_fini(void) | |
866 | { | |
867 | pci_unregister_driver(&dvb_pci_driver); | |
868 | } | |
869 | ||
870 | module_init(dvb_init); | |
871 | module_exit(dvb_fini); | |
872 | ||
873 | /* | |
874 | * Local variables: | |
875 | * c-basic-offset: 8 | |
876 | * compile-command: "make DVB=1" | |
877 | * End: | |
878 | */ |