diff options
Diffstat (limited to 'drivers/media/video/cx231xx/cx231xx-cards.c')
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-cards.c | 1410 |
1 files changed, 1410 insertions, 0 deletions
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c new file mode 100644 index 00000000000..53dae2a8272 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-cards.c | |||
@@ -0,0 +1,1410 @@ | |||
1 | /* | ||
2 | cx231xx-cards.c - driver for Conexant Cx23100/101/102 | ||
3 | USB video capture devices | ||
4 | |||
5 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
6 | Based on em28xx driver | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/usb.h> | ||
29 | #include <media/tuner.h> | ||
30 | #include <media/tveeprom.h> | ||
31 | #include <media/v4l2-common.h> | ||
32 | #include <media/v4l2-chip-ident.h> | ||
33 | |||
34 | #include <media/cx25840.h> | ||
35 | #include "dvb-usb-ids.h" | ||
36 | #include "xc5000.h" | ||
37 | #include "tda18271.h" | ||
38 | |||
39 | #include "cx231xx.h" | ||
40 | |||
41 | static int tuner = -1; | ||
42 | module_param(tuner, int, 0444); | ||
43 | MODULE_PARM_DESC(tuner, "tuner type"); | ||
44 | |||
45 | static int transfer_mode = 1; | ||
46 | module_param(transfer_mode, int, 0444); | ||
47 | MODULE_PARM_DESC(transfer_mode, "transfer mode (1-ISO or 0-BULK)"); | ||
48 | |||
49 | static unsigned int disable_ir; | ||
50 | module_param(disable_ir, int, 0444); | ||
51 | MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); | ||
52 | |||
53 | /* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */ | ||
54 | static unsigned long cx231xx_devused; | ||
55 | |||
56 | /* | ||
57 | * Reset sequences for analog/digital modes | ||
58 | */ | ||
59 | |||
60 | static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = { | ||
61 | {0x03, 0x01, 10}, | ||
62 | {0x03, 0x00, 30}, | ||
63 | {0x03, 0x01, 10}, | ||
64 | {-1, -1, -1}, | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * Board definitions | ||
69 | */ | ||
70 | struct cx231xx_board cx231xx_boards[] = { | ||
71 | [CX231XX_BOARD_UNKNOWN] = { | ||
72 | .name = "Unknown CX231xx video grabber", | ||
73 | .tuner_type = TUNER_ABSENT, | ||
74 | .input = {{ | ||
75 | .type = CX231XX_VMUX_TELEVISION, | ||
76 | .vmux = CX231XX_VIN_3_1, | ||
77 | .amux = CX231XX_AMUX_VIDEO, | ||
78 | .gpio = NULL, | ||
79 | }, { | ||
80 | .type = CX231XX_VMUX_COMPOSITE1, | ||
81 | .vmux = CX231XX_VIN_2_1, | ||
82 | .amux = CX231XX_AMUX_LINE_IN, | ||
83 | .gpio = NULL, | ||
84 | }, { | ||
85 | .type = CX231XX_VMUX_SVIDEO, | ||
86 | .vmux = CX231XX_VIN_1_1 | | ||
87 | (CX231XX_VIN_1_2 << 8) | | ||
88 | CX25840_SVIDEO_ON, | ||
89 | .amux = CX231XX_AMUX_LINE_IN, | ||
90 | .gpio = NULL, | ||
91 | } | ||
92 | }, | ||
93 | }, | ||
94 | [CX231XX_BOARD_CNXT_CARRAERA] = { | ||
95 | .name = "Conexant Hybrid TV - CARRAERA", | ||
96 | .tuner_type = TUNER_XC5000, | ||
97 | .tuner_addr = 0x61, | ||
98 | .tuner_gpio = RDE250_XCV_TUNER, | ||
99 | .tuner_sif_gpio = 0x05, | ||
100 | .tuner_scl_gpio = 0x1a, | ||
101 | .tuner_sda_gpio = 0x1b, | ||
102 | .decoder = CX231XX_AVDECODER, | ||
103 | .output_mode = OUT_MODE_VIP11, | ||
104 | .demod_xfer_mode = 0, | ||
105 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
106 | .agc_analog_digital_select_gpio = 0x0c, | ||
107 | .gpio_pin_status_mask = 0x4001000, | ||
108 | .tuner_i2c_master = 1, | ||
109 | .demod_i2c_master = 2, | ||
110 | .has_dvb = 1, | ||
111 | .demod_addr = 0x02, | ||
112 | .norm = V4L2_STD_PAL, | ||
113 | |||
114 | .input = {{ | ||
115 | .type = CX231XX_VMUX_TELEVISION, | ||
116 | .vmux = CX231XX_VIN_3_1, | ||
117 | .amux = CX231XX_AMUX_VIDEO, | ||
118 | .gpio = NULL, | ||
119 | }, { | ||
120 | .type = CX231XX_VMUX_COMPOSITE1, | ||
121 | .vmux = CX231XX_VIN_2_1, | ||
122 | .amux = CX231XX_AMUX_LINE_IN, | ||
123 | .gpio = NULL, | ||
124 | }, { | ||
125 | .type = CX231XX_VMUX_SVIDEO, | ||
126 | .vmux = CX231XX_VIN_1_1 | | ||
127 | (CX231XX_VIN_1_2 << 8) | | ||
128 | CX25840_SVIDEO_ON, | ||
129 | .amux = CX231XX_AMUX_LINE_IN, | ||
130 | .gpio = NULL, | ||
131 | } | ||
132 | }, | ||
133 | }, | ||
134 | [CX231XX_BOARD_CNXT_SHELBY] = { | ||
135 | .name = "Conexant Hybrid TV - SHELBY", | ||
136 | .tuner_type = TUNER_XC5000, | ||
137 | .tuner_addr = 0x61, | ||
138 | .tuner_gpio = RDE250_XCV_TUNER, | ||
139 | .tuner_sif_gpio = 0x05, | ||
140 | .tuner_scl_gpio = 0x1a, | ||
141 | .tuner_sda_gpio = 0x1b, | ||
142 | .decoder = CX231XX_AVDECODER, | ||
143 | .output_mode = OUT_MODE_VIP11, | ||
144 | .demod_xfer_mode = 0, | ||
145 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
146 | .agc_analog_digital_select_gpio = 0x0c, | ||
147 | .gpio_pin_status_mask = 0x4001000, | ||
148 | .tuner_i2c_master = 1, | ||
149 | .demod_i2c_master = 2, | ||
150 | .has_dvb = 1, | ||
151 | .demod_addr = 0x32, | ||
152 | .norm = V4L2_STD_NTSC, | ||
153 | |||
154 | .input = {{ | ||
155 | .type = CX231XX_VMUX_TELEVISION, | ||
156 | .vmux = CX231XX_VIN_3_1, | ||
157 | .amux = CX231XX_AMUX_VIDEO, | ||
158 | .gpio = NULL, | ||
159 | }, { | ||
160 | .type = CX231XX_VMUX_COMPOSITE1, | ||
161 | .vmux = CX231XX_VIN_2_1, | ||
162 | .amux = CX231XX_AMUX_LINE_IN, | ||
163 | .gpio = NULL, | ||
164 | }, { | ||
165 | .type = CX231XX_VMUX_SVIDEO, | ||
166 | .vmux = CX231XX_VIN_1_1 | | ||
167 | (CX231XX_VIN_1_2 << 8) | | ||
168 | CX25840_SVIDEO_ON, | ||
169 | .amux = CX231XX_AMUX_LINE_IN, | ||
170 | .gpio = NULL, | ||
171 | } | ||
172 | }, | ||
173 | }, | ||
174 | [CX231XX_BOARD_CNXT_RDE_253S] = { | ||
175 | .name = "Conexant Hybrid TV - RDE253S", | ||
176 | .tuner_type = TUNER_NXP_TDA18271, | ||
177 | .tuner_addr = 0x60, | ||
178 | .tuner_gpio = RDE250_XCV_TUNER, | ||
179 | .tuner_sif_gpio = 0x05, | ||
180 | .tuner_scl_gpio = 0x1a, | ||
181 | .tuner_sda_gpio = 0x1b, | ||
182 | .decoder = CX231XX_AVDECODER, | ||
183 | .output_mode = OUT_MODE_VIP11, | ||
184 | .demod_xfer_mode = 0, | ||
185 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
186 | .agc_analog_digital_select_gpio = 0x1c, | ||
187 | .gpio_pin_status_mask = 0x4001000, | ||
188 | .tuner_i2c_master = 1, | ||
189 | .demod_i2c_master = 2, | ||
190 | .has_dvb = 1, | ||
191 | .demod_addr = 0x02, | ||
192 | .norm = V4L2_STD_PAL, | ||
193 | |||
194 | .input = {{ | ||
195 | .type = CX231XX_VMUX_TELEVISION, | ||
196 | .vmux = CX231XX_VIN_3_1, | ||
197 | .amux = CX231XX_AMUX_VIDEO, | ||
198 | .gpio = NULL, | ||
199 | }, { | ||
200 | .type = CX231XX_VMUX_COMPOSITE1, | ||
201 | .vmux = CX231XX_VIN_2_1, | ||
202 | .amux = CX231XX_AMUX_LINE_IN, | ||
203 | .gpio = NULL, | ||
204 | }, { | ||
205 | .type = CX231XX_VMUX_SVIDEO, | ||
206 | .vmux = CX231XX_VIN_1_1 | | ||
207 | (CX231XX_VIN_1_2 << 8) | | ||
208 | CX25840_SVIDEO_ON, | ||
209 | .amux = CX231XX_AMUX_LINE_IN, | ||
210 | .gpio = NULL, | ||
211 | } | ||
212 | }, | ||
213 | }, | ||
214 | |||
215 | [CX231XX_BOARD_CNXT_RDU_253S] = { | ||
216 | .name = "Conexant Hybrid TV - RDU253S", | ||
217 | .tuner_type = TUNER_NXP_TDA18271, | ||
218 | .tuner_addr = 0x60, | ||
219 | .tuner_gpio = RDE250_XCV_TUNER, | ||
220 | .tuner_sif_gpio = 0x05, | ||
221 | .tuner_scl_gpio = 0x1a, | ||
222 | .tuner_sda_gpio = 0x1b, | ||
223 | .decoder = CX231XX_AVDECODER, | ||
224 | .output_mode = OUT_MODE_VIP11, | ||
225 | .demod_xfer_mode = 0, | ||
226 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
227 | .agc_analog_digital_select_gpio = 0x1c, | ||
228 | .gpio_pin_status_mask = 0x4001000, | ||
229 | .tuner_i2c_master = 1, | ||
230 | .demod_i2c_master = 2, | ||
231 | .has_dvb = 1, | ||
232 | .demod_addr = 0x02, | ||
233 | .norm = V4L2_STD_PAL, | ||
234 | |||
235 | .input = {{ | ||
236 | .type = CX231XX_VMUX_TELEVISION, | ||
237 | .vmux = CX231XX_VIN_3_1, | ||
238 | .amux = CX231XX_AMUX_VIDEO, | ||
239 | .gpio = NULL, | ||
240 | }, { | ||
241 | .type = CX231XX_VMUX_COMPOSITE1, | ||
242 | .vmux = CX231XX_VIN_2_1, | ||
243 | .amux = CX231XX_AMUX_LINE_IN, | ||
244 | .gpio = NULL, | ||
245 | }, { | ||
246 | .type = CX231XX_VMUX_SVIDEO, | ||
247 | .vmux = CX231XX_VIN_1_1 | | ||
248 | (CX231XX_VIN_1_2 << 8) | | ||
249 | CX25840_SVIDEO_ON, | ||
250 | .amux = CX231XX_AMUX_LINE_IN, | ||
251 | .gpio = NULL, | ||
252 | } | ||
253 | }, | ||
254 | }, | ||
255 | [CX231XX_BOARD_CNXT_VIDEO_GRABBER] = { | ||
256 | .name = "Conexant VIDEO GRABBER", | ||
257 | .tuner_type = TUNER_ABSENT, | ||
258 | .decoder = CX231XX_AVDECODER, | ||
259 | .output_mode = OUT_MODE_VIP11, | ||
260 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
261 | .agc_analog_digital_select_gpio = 0x1c, | ||
262 | .gpio_pin_status_mask = 0x4001000, | ||
263 | .norm = V4L2_STD_PAL, | ||
264 | .no_alt_vanc = 1, | ||
265 | .external_av = 1, | ||
266 | .has_417 = 1, | ||
267 | |||
268 | .input = {{ | ||
269 | .type = CX231XX_VMUX_COMPOSITE1, | ||
270 | .vmux = CX231XX_VIN_2_1, | ||
271 | .amux = CX231XX_AMUX_LINE_IN, | ||
272 | .gpio = NULL, | ||
273 | }, { | ||
274 | .type = CX231XX_VMUX_SVIDEO, | ||
275 | .vmux = CX231XX_VIN_1_1 | | ||
276 | (CX231XX_VIN_1_2 << 8) | | ||
277 | CX25840_SVIDEO_ON, | ||
278 | .amux = CX231XX_AMUX_LINE_IN, | ||
279 | .gpio = NULL, | ||
280 | } | ||
281 | }, | ||
282 | }, | ||
283 | [CX231XX_BOARD_CNXT_RDE_250] = { | ||
284 | .name = "Conexant Hybrid TV - rde 250", | ||
285 | .tuner_type = TUNER_XC5000, | ||
286 | .tuner_addr = 0x61, | ||
287 | .tuner_gpio = RDE250_XCV_TUNER, | ||
288 | .tuner_sif_gpio = 0x05, | ||
289 | .tuner_scl_gpio = 0x1a, | ||
290 | .tuner_sda_gpio = 0x1b, | ||
291 | .decoder = CX231XX_AVDECODER, | ||
292 | .output_mode = OUT_MODE_VIP11, | ||
293 | .demod_xfer_mode = 0, | ||
294 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
295 | .agc_analog_digital_select_gpio = 0x0c, | ||
296 | .gpio_pin_status_mask = 0x4001000, | ||
297 | .tuner_i2c_master = 1, | ||
298 | .demod_i2c_master = 2, | ||
299 | .has_dvb = 1, | ||
300 | .demod_addr = 0x02, | ||
301 | .norm = V4L2_STD_PAL, | ||
302 | |||
303 | .input = {{ | ||
304 | .type = CX231XX_VMUX_TELEVISION, | ||
305 | .vmux = CX231XX_VIN_2_1, | ||
306 | .amux = CX231XX_AMUX_VIDEO, | ||
307 | .gpio = NULL, | ||
308 | } | ||
309 | }, | ||
310 | }, | ||
311 | [CX231XX_BOARD_CNXT_RDU_250] = { | ||
312 | .name = "Conexant Hybrid TV - RDU 250", | ||
313 | .tuner_type = TUNER_XC5000, | ||
314 | .tuner_addr = 0x61, | ||
315 | .tuner_gpio = RDE250_XCV_TUNER, | ||
316 | .tuner_sif_gpio = 0x05, | ||
317 | .tuner_scl_gpio = 0x1a, | ||
318 | .tuner_sda_gpio = 0x1b, | ||
319 | .decoder = CX231XX_AVDECODER, | ||
320 | .output_mode = OUT_MODE_VIP11, | ||
321 | .demod_xfer_mode = 0, | ||
322 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
323 | .agc_analog_digital_select_gpio = 0x0c, | ||
324 | .gpio_pin_status_mask = 0x4001000, | ||
325 | .tuner_i2c_master = 1, | ||
326 | .demod_i2c_master = 2, | ||
327 | .has_dvb = 1, | ||
328 | .demod_addr = 0x32, | ||
329 | .norm = V4L2_STD_NTSC, | ||
330 | |||
331 | .input = {{ | ||
332 | .type = CX231XX_VMUX_TELEVISION, | ||
333 | .vmux = CX231XX_VIN_2_1, | ||
334 | .amux = CX231XX_AMUX_VIDEO, | ||
335 | .gpio = NULL, | ||
336 | } | ||
337 | }, | ||
338 | }, | ||
339 | [CX231XX_BOARD_HAUPPAUGE_EXETER] = { | ||
340 | .name = "Hauppauge EXETER", | ||
341 | .tuner_type = TUNER_NXP_TDA18271, | ||
342 | .tuner_addr = 0x60, | ||
343 | .tuner_gpio = RDE250_XCV_TUNER, | ||
344 | .tuner_sif_gpio = 0x05, | ||
345 | .tuner_scl_gpio = 0x1a, | ||
346 | .tuner_sda_gpio = 0x1b, | ||
347 | .decoder = CX231XX_AVDECODER, | ||
348 | .output_mode = OUT_MODE_VIP11, | ||
349 | .demod_xfer_mode = 0, | ||
350 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
351 | .agc_analog_digital_select_gpio = 0x0c, | ||
352 | .gpio_pin_status_mask = 0x4001000, | ||
353 | .tuner_i2c_master = 1, | ||
354 | .demod_i2c_master = 2, | ||
355 | .has_dvb = 1, | ||
356 | .demod_addr = 0x0e, | ||
357 | .norm = V4L2_STD_NTSC, | ||
358 | |||
359 | .input = {{ | ||
360 | .type = CX231XX_VMUX_TELEVISION, | ||
361 | .vmux = CX231XX_VIN_3_1, | ||
362 | .amux = CX231XX_AMUX_VIDEO, | ||
363 | .gpio = NULL, | ||
364 | }, { | ||
365 | .type = CX231XX_VMUX_COMPOSITE1, | ||
366 | .vmux = CX231XX_VIN_2_1, | ||
367 | .amux = CX231XX_AMUX_LINE_IN, | ||
368 | .gpio = NULL, | ||
369 | }, { | ||
370 | .type = CX231XX_VMUX_SVIDEO, | ||
371 | .vmux = CX231XX_VIN_1_1 | | ||
372 | (CX231XX_VIN_1_2 << 8) | | ||
373 | CX25840_SVIDEO_ON, | ||
374 | .amux = CX231XX_AMUX_LINE_IN, | ||
375 | .gpio = NULL, | ||
376 | } }, | ||
377 | }, | ||
378 | [CX231XX_BOARD_HAUPPAUGE_USBLIVE2] = { | ||
379 | .name = "Hauppauge USB Live 2", | ||
380 | .tuner_type = TUNER_ABSENT, | ||
381 | .decoder = CX231XX_AVDECODER, | ||
382 | .output_mode = OUT_MODE_VIP11, | ||
383 | .demod_xfer_mode = 0, | ||
384 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
385 | .agc_analog_digital_select_gpio = 0x0c, | ||
386 | .gpio_pin_status_mask = 0x4001000, | ||
387 | .norm = V4L2_STD_NTSC, | ||
388 | .no_alt_vanc = 1, | ||
389 | .external_av = 1, | ||
390 | .dont_use_port_3 = 1, | ||
391 | .input = {{ | ||
392 | .type = CX231XX_VMUX_COMPOSITE1, | ||
393 | .vmux = CX231XX_VIN_2_1, | ||
394 | .amux = CX231XX_AMUX_LINE_IN, | ||
395 | .gpio = NULL, | ||
396 | }, { | ||
397 | .type = CX231XX_VMUX_SVIDEO, | ||
398 | .vmux = CX231XX_VIN_1_1 | | ||
399 | (CX231XX_VIN_1_2 << 8) | | ||
400 | CX25840_SVIDEO_ON, | ||
401 | .amux = CX231XX_AMUX_LINE_IN, | ||
402 | .gpio = NULL, | ||
403 | } }, | ||
404 | }, | ||
405 | [CX231XX_BOARD_KWORLD_UB430_USB_HYBRID] = { | ||
406 | .name = "Kworld UB430 USB Hybrid", | ||
407 | .tuner_type = TUNER_NXP_TDA18271, | ||
408 | .tuner_addr = 0x60, | ||
409 | .decoder = CX231XX_AVDECODER, | ||
410 | .output_mode = OUT_MODE_VIP11, | ||
411 | .demod_xfer_mode = 0, | ||
412 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
413 | .agc_analog_digital_select_gpio = 0x11, /* According with PV cxPolaris.inf file */ | ||
414 | .tuner_sif_gpio = -1, | ||
415 | .tuner_scl_gpio = -1, | ||
416 | .tuner_sda_gpio = -1, | ||
417 | .gpio_pin_status_mask = 0x4001000, | ||
418 | .tuner_i2c_master = 2, | ||
419 | .demod_i2c_master = 1, | ||
420 | .ir_i2c_master = 2, | ||
421 | .has_dvb = 1, | ||
422 | .demod_addr = 0x10, | ||
423 | .norm = V4L2_STD_PAL_M, | ||
424 | .input = {{ | ||
425 | .type = CX231XX_VMUX_TELEVISION, | ||
426 | .vmux = CX231XX_VIN_3_1, | ||
427 | .amux = CX231XX_AMUX_VIDEO, | ||
428 | .gpio = NULL, | ||
429 | }, { | ||
430 | .type = CX231XX_VMUX_COMPOSITE1, | ||
431 | .vmux = CX231XX_VIN_2_1, | ||
432 | .amux = CX231XX_AMUX_LINE_IN, | ||
433 | .gpio = NULL, | ||
434 | }, { | ||
435 | .type = CX231XX_VMUX_SVIDEO, | ||
436 | .vmux = CX231XX_VIN_1_1 | | ||
437 | (CX231XX_VIN_1_2 << 8) | | ||
438 | CX25840_SVIDEO_ON, | ||
439 | .amux = CX231XX_AMUX_LINE_IN, | ||
440 | .gpio = NULL, | ||
441 | } }, | ||
442 | }, | ||
443 | [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { | ||
444 | .name = "Pixelview PlayTV USB Hybrid", | ||
445 | .tuner_type = TUNER_NXP_TDA18271, | ||
446 | .tuner_addr = 0x60, | ||
447 | .decoder = CX231XX_AVDECODER, | ||
448 | .output_mode = OUT_MODE_VIP11, | ||
449 | .demod_xfer_mode = 0, | ||
450 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
451 | .agc_analog_digital_select_gpio = 0x00, /* According with PV cxPolaris.inf file */ | ||
452 | .tuner_sif_gpio = -1, | ||
453 | .tuner_scl_gpio = -1, | ||
454 | .tuner_sda_gpio = -1, | ||
455 | .gpio_pin_status_mask = 0x4001000, | ||
456 | .tuner_i2c_master = 2, | ||
457 | .demod_i2c_master = 1, | ||
458 | .ir_i2c_master = 2, | ||
459 | .rc_map_name = RC_MAP_PIXELVIEW_002T, | ||
460 | .has_dvb = 1, | ||
461 | .demod_addr = 0x10, | ||
462 | .norm = V4L2_STD_PAL_M, | ||
463 | .input = {{ | ||
464 | .type = CX231XX_VMUX_TELEVISION, | ||
465 | .vmux = CX231XX_VIN_3_1, | ||
466 | .amux = CX231XX_AMUX_VIDEO, | ||
467 | .gpio = NULL, | ||
468 | }, { | ||
469 | .type = CX231XX_VMUX_COMPOSITE1, | ||
470 | .vmux = CX231XX_VIN_2_1, | ||
471 | .amux = CX231XX_AMUX_LINE_IN, | ||
472 | .gpio = NULL, | ||
473 | }, { | ||
474 | .type = CX231XX_VMUX_SVIDEO, | ||
475 | .vmux = CX231XX_VIN_1_1 | | ||
476 | (CX231XX_VIN_1_2 << 8) | | ||
477 | CX25840_SVIDEO_ON, | ||
478 | .amux = CX231XX_AMUX_LINE_IN, | ||
479 | .gpio = NULL, | ||
480 | } }, | ||
481 | }, | ||
482 | [CX231XX_BOARD_PV_XCAPTURE_USB] = { | ||
483 | .name = "Pixelview Xcapture USB", | ||
484 | .tuner_type = TUNER_ABSENT, | ||
485 | .decoder = CX231XX_AVDECODER, | ||
486 | .output_mode = OUT_MODE_VIP11, | ||
487 | .demod_xfer_mode = 0, | ||
488 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
489 | .agc_analog_digital_select_gpio = 0x0c, | ||
490 | .gpio_pin_status_mask = 0x4001000, | ||
491 | .norm = V4L2_STD_NTSC, | ||
492 | .no_alt_vanc = 1, | ||
493 | .external_av = 1, | ||
494 | .dont_use_port_3 = 1, | ||
495 | |||
496 | .input = {{ | ||
497 | .type = CX231XX_VMUX_COMPOSITE1, | ||
498 | .vmux = CX231XX_VIN_2_1, | ||
499 | .amux = CX231XX_AMUX_LINE_IN, | ||
500 | .gpio = NULL, | ||
501 | }, { | ||
502 | .type = CX231XX_VMUX_SVIDEO, | ||
503 | .vmux = CX231XX_VIN_1_1 | | ||
504 | (CX231XX_VIN_1_2 << 8) | | ||
505 | CX25840_SVIDEO_ON, | ||
506 | .amux = CX231XX_AMUX_LINE_IN, | ||
507 | .gpio = NULL, | ||
508 | } | ||
509 | }, | ||
510 | }, | ||
511 | |||
512 | [CX231XX_BOARD_ICONBIT_U100] = { | ||
513 | .name = "Iconbit Analog Stick U100 FM", | ||
514 | .tuner_type = TUNER_ABSENT, | ||
515 | .decoder = CX231XX_AVDECODER, | ||
516 | .output_mode = OUT_MODE_VIP11, | ||
517 | .demod_xfer_mode = 0, | ||
518 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
519 | .agc_analog_digital_select_gpio = 0x1C, | ||
520 | .gpio_pin_status_mask = 0x4001000, | ||
521 | |||
522 | .input = {{ | ||
523 | .type = CX231XX_VMUX_COMPOSITE1, | ||
524 | .vmux = CX231XX_VIN_2_1, | ||
525 | .amux = CX231XX_AMUX_LINE_IN, | ||
526 | .gpio = NULL, | ||
527 | }, { | ||
528 | .type = CX231XX_VMUX_SVIDEO, | ||
529 | .vmux = CX231XX_VIN_1_1 | | ||
530 | (CX231XX_VIN_1_2 << 8) | | ||
531 | CX25840_SVIDEO_ON, | ||
532 | .amux = CX231XX_AMUX_LINE_IN, | ||
533 | .gpio = NULL, | ||
534 | } }, | ||
535 | }, | ||
536 | [CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL] = { | ||
537 | .name = "Hauppauge WinTV USB2 FM (PAL)", | ||
538 | .tuner_type = TUNER_NXP_TDA18271, | ||
539 | .tuner_addr = 0x60, | ||
540 | .tuner_gpio = RDE250_XCV_TUNER, | ||
541 | .tuner_sif_gpio = 0x05, | ||
542 | .tuner_scl_gpio = 0x1a, | ||
543 | .tuner_sda_gpio = 0x1b, | ||
544 | .decoder = CX231XX_AVDECODER, | ||
545 | .output_mode = OUT_MODE_VIP11, | ||
546 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
547 | .agc_analog_digital_select_gpio = 0x0c, | ||
548 | .gpio_pin_status_mask = 0x4001000, | ||
549 | .tuner_i2c_master = 1, | ||
550 | .norm = V4L2_STD_PAL, | ||
551 | |||
552 | .input = {{ | ||
553 | .type = CX231XX_VMUX_TELEVISION, | ||
554 | .vmux = CX231XX_VIN_3_1, | ||
555 | .amux = CX231XX_AMUX_VIDEO, | ||
556 | .gpio = NULL, | ||
557 | }, { | ||
558 | .type = CX231XX_VMUX_COMPOSITE1, | ||
559 | .vmux = CX231XX_VIN_2_1, | ||
560 | .amux = CX231XX_AMUX_LINE_IN, | ||
561 | .gpio = NULL, | ||
562 | }, { | ||
563 | .type = CX231XX_VMUX_SVIDEO, | ||
564 | .vmux = CX231XX_VIN_1_1 | | ||
565 | (CX231XX_VIN_1_2 << 8) | | ||
566 | CX25840_SVIDEO_ON, | ||
567 | .amux = CX231XX_AMUX_LINE_IN, | ||
568 | .gpio = NULL, | ||
569 | } }, | ||
570 | }, | ||
571 | [CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC] = { | ||
572 | .name = "Hauppauge WinTV USB2 FM (NTSC)", | ||
573 | .tuner_type = TUNER_NXP_TDA18271, | ||
574 | .tuner_addr = 0x60, | ||
575 | .tuner_gpio = RDE250_XCV_TUNER, | ||
576 | .tuner_sif_gpio = 0x05, | ||
577 | .tuner_scl_gpio = 0x1a, | ||
578 | .tuner_sda_gpio = 0x1b, | ||
579 | .decoder = CX231XX_AVDECODER, | ||
580 | .output_mode = OUT_MODE_VIP11, | ||
581 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
582 | .agc_analog_digital_select_gpio = 0x0c, | ||
583 | .gpio_pin_status_mask = 0x4001000, | ||
584 | .tuner_i2c_master = 1, | ||
585 | .norm = V4L2_STD_NTSC, | ||
586 | |||
587 | .input = {{ | ||
588 | .type = CX231XX_VMUX_TELEVISION, | ||
589 | .vmux = CX231XX_VIN_3_1, | ||
590 | .amux = CX231XX_AMUX_VIDEO, | ||
591 | .gpio = NULL, | ||
592 | }, { | ||
593 | .type = CX231XX_VMUX_COMPOSITE1, | ||
594 | .vmux = CX231XX_VIN_2_1, | ||
595 | .amux = CX231XX_AMUX_LINE_IN, | ||
596 | .gpio = NULL, | ||
597 | }, { | ||
598 | .type = CX231XX_VMUX_SVIDEO, | ||
599 | .vmux = CX231XX_VIN_1_1 | | ||
600 | (CX231XX_VIN_1_2 << 8) | | ||
601 | CX25840_SVIDEO_ON, | ||
602 | .amux = CX231XX_AMUX_LINE_IN, | ||
603 | .gpio = NULL, | ||
604 | } }, | ||
605 | }, | ||
606 | }; | ||
607 | const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); | ||
608 | |||
609 | /* table of devices that work with this driver */ | ||
610 | struct usb_device_id cx231xx_id_table[] = { | ||
611 | {USB_DEVICE(0x0572, 0x5A3C), | ||
612 | .driver_info = CX231XX_BOARD_UNKNOWN}, | ||
613 | {USB_DEVICE(0x0572, 0x58A2), | ||
614 | .driver_info = CX231XX_BOARD_CNXT_CARRAERA}, | ||
615 | {USB_DEVICE(0x0572, 0x58A1), | ||
616 | .driver_info = CX231XX_BOARD_CNXT_SHELBY}, | ||
617 | {USB_DEVICE(0x0572, 0x58A4), | ||
618 | .driver_info = CX231XX_BOARD_CNXT_RDE_253S}, | ||
619 | {USB_DEVICE(0x0572, 0x58A5), | ||
620 | .driver_info = CX231XX_BOARD_CNXT_RDU_253S}, | ||
621 | {USB_DEVICE(0x0572, 0x58A6), | ||
622 | .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER}, | ||
623 | {USB_DEVICE(0x0572, 0x589E), | ||
624 | .driver_info = CX231XX_BOARD_CNXT_RDE_250}, | ||
625 | {USB_DEVICE(0x0572, 0x58A0), | ||
626 | .driver_info = CX231XX_BOARD_CNXT_RDU_250}, | ||
627 | {USB_DEVICE(0x2040, 0xb110), | ||
628 | .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL}, | ||
629 | {USB_DEVICE(0x2040, 0xb111), | ||
630 | .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC}, | ||
631 | {USB_DEVICE(0x2040, 0xb120), | ||
632 | .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, | ||
633 | {USB_DEVICE(0x2040, 0xb140), | ||
634 | .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, | ||
635 | {USB_DEVICE(0x2040, 0xc200), | ||
636 | .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2}, | ||
637 | {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001), | ||
638 | .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID}, | ||
639 | {USB_DEVICE(USB_VID_PIXELVIEW, 0x5014), | ||
640 | .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, | ||
641 | {USB_DEVICE(0x1b80, 0xe424), | ||
642 | .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID}, | ||
643 | {USB_DEVICE(0x1f4d, 0x0237), | ||
644 | .driver_info = CX231XX_BOARD_ICONBIT_U100}, | ||
645 | {}, | ||
646 | }; | ||
647 | |||
648 | MODULE_DEVICE_TABLE(usb, cx231xx_id_table); | ||
649 | |||
650 | /* cx231xx_tuner_callback | ||
651 | * will be used to reset XC5000 tuner using GPIO pin | ||
652 | */ | ||
653 | |||
654 | int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) | ||
655 | { | ||
656 | int rc = 0; | ||
657 | struct cx231xx *dev = ptr; | ||
658 | |||
659 | if (dev->tuner_type == TUNER_XC5000) { | ||
660 | if (command == XC5000_TUNER_RESET) { | ||
661 | cx231xx_info | ||
662 | ("Tuner CB: RESET: cmd %d : tuner type %d \n", | ||
663 | command, dev->tuner_type); | ||
664 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, | ||
665 | 1); | ||
666 | msleep(10); | ||
667 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, | ||
668 | 0); | ||
669 | msleep(330); | ||
670 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, | ||
671 | 1); | ||
672 | msleep(10); | ||
673 | } | ||
674 | } else if (dev->tuner_type == TUNER_NXP_TDA18271) { | ||
675 | switch (command) { | ||
676 | case TDA18271_CALLBACK_CMD_AGC_ENABLE: | ||
677 | if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID) | ||
678 | rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg); | ||
679 | break; | ||
680 | default: | ||
681 | rc = -EINVAL; | ||
682 | break; | ||
683 | } | ||
684 | } | ||
685 | return rc; | ||
686 | } | ||
687 | EXPORT_SYMBOL_GPL(cx231xx_tuner_callback); | ||
688 | |||
689 | void cx231xx_reset_out(struct cx231xx *dev) | ||
690 | { | ||
691 | cx231xx_set_gpio_value(dev, CX23417_RESET, 1); | ||
692 | msleep(200); | ||
693 | cx231xx_set_gpio_value(dev, CX23417_RESET, 0); | ||
694 | msleep(200); | ||
695 | cx231xx_set_gpio_value(dev, CX23417_RESET, 1); | ||
696 | } | ||
697 | void cx231xx_enable_OSC(struct cx231xx *dev) | ||
698 | { | ||
699 | cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1); | ||
700 | } | ||
701 | void cx231xx_sleep_s5h1432(struct cx231xx *dev) | ||
702 | { | ||
703 | cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0); | ||
704 | } | ||
705 | |||
706 | static inline void cx231xx_set_model(struct cx231xx *dev) | ||
707 | { | ||
708 | memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board)); | ||
709 | } | ||
710 | |||
711 | /* Since cx231xx_pre_card_setup() requires a proper dev->model, | ||
712 | * this won't work for boards with generic PCI IDs | ||
713 | */ | ||
714 | void cx231xx_pre_card_setup(struct cx231xx *dev) | ||
715 | { | ||
716 | |||
717 | cx231xx_set_model(dev); | ||
718 | |||
719 | cx231xx_info("Identified as %s (card=%d)\n", | ||
720 | dev->board.name, dev->model); | ||
721 | |||
722 | /* set the direction for GPIO pins */ | ||
723 | if (dev->board.tuner_gpio) { | ||
724 | cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); | ||
725 | cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); | ||
726 | } | ||
727 | if (dev->board.tuner_sif_gpio >= 0) | ||
728 | cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); | ||
729 | |||
730 | /* request some modules if any required */ | ||
731 | |||
732 | /* set the mode to Analog mode initially */ | ||
733 | cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); | ||
734 | |||
735 | /* Unlock device */ | ||
736 | /* cx231xx_set_mode(dev, CX231XX_SUSPEND); */ | ||
737 | |||
738 | } | ||
739 | |||
740 | static void cx231xx_config_tuner(struct cx231xx *dev) | ||
741 | { | ||
742 | struct tuner_setup tun_setup; | ||
743 | struct v4l2_frequency f; | ||
744 | |||
745 | if (dev->tuner_type == TUNER_ABSENT) | ||
746 | return; | ||
747 | |||
748 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
749 | tun_setup.type = dev->tuner_type; | ||
750 | tun_setup.addr = dev->tuner_addr; | ||
751 | tun_setup.tuner_callback = cx231xx_tuner_callback; | ||
752 | |||
753 | tuner_call(dev, tuner, s_type_addr, &tun_setup); | ||
754 | |||
755 | #if 0 | ||
756 | if (tun_setup.type == TUNER_XC5000) { | ||
757 | static struct xc2028_ctrl ctrl = { | ||
758 | .fname = XC5000_DEFAULT_FIRMWARE, | ||
759 | .max_len = 64, | ||
760 | .demod = 0; | ||
761 | }; | ||
762 | struct v4l2_priv_tun_config cfg = { | ||
763 | .tuner = dev->tuner_type, | ||
764 | .priv = &ctrl, | ||
765 | }; | ||
766 | tuner_call(dev, tuner, s_config, &cfg); | ||
767 | } | ||
768 | #endif | ||
769 | /* configure tuner */ | ||
770 | f.tuner = 0; | ||
771 | f.type = V4L2_TUNER_ANALOG_TV; | ||
772 | f.frequency = 9076; /* just a magic number */ | ||
773 | dev->ctl_freq = f.frequency; | ||
774 | call_all(dev, tuner, s_frequency, &f); | ||
775 | |||
776 | } | ||
777 | |||
778 | void cx231xx_card_setup(struct cx231xx *dev) | ||
779 | { | ||
780 | |||
781 | cx231xx_set_model(dev); | ||
782 | |||
783 | dev->tuner_type = cx231xx_boards[dev->model].tuner_type; | ||
784 | if (cx231xx_boards[dev->model].tuner_addr) | ||
785 | dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr; | ||
786 | |||
787 | /* request some modules */ | ||
788 | if (dev->board.decoder == CX231XX_AVDECODER) { | ||
789 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, | ||
790 | &dev->i2c_bus[0].i2c_adap, | ||
791 | "cx25840", 0x88 >> 1, NULL); | ||
792 | if (dev->sd_cx25840 == NULL) | ||
793 | cx231xx_info("cx25840 subdev registration failure\n"); | ||
794 | cx25840_call(dev, core, load_fw); | ||
795 | |||
796 | } | ||
797 | |||
798 | /* Initialize the tuner */ | ||
799 | if (dev->board.tuner_type != TUNER_ABSENT) { | ||
800 | dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, | ||
801 | &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, | ||
802 | "tuner", | ||
803 | dev->tuner_addr, NULL); | ||
804 | if (dev->sd_tuner == NULL) | ||
805 | cx231xx_info("tuner subdev registration failure\n"); | ||
806 | else | ||
807 | cx231xx_config_tuner(dev); | ||
808 | } | ||
809 | } | ||
810 | |||
811 | /* | ||
812 | * cx231xx_config() | ||
813 | * inits registers with sane defaults | ||
814 | */ | ||
815 | int cx231xx_config(struct cx231xx *dev) | ||
816 | { | ||
817 | /* TBD need to add cx231xx specific code */ | ||
818 | dev->mute = 1; /* maybe not the right place... */ | ||
819 | dev->volume = 0x1f; | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | /* | ||
825 | * cx231xx_config_i2c() | ||
826 | * configure i2c attached devices | ||
827 | */ | ||
828 | void cx231xx_config_i2c(struct cx231xx *dev) | ||
829 | { | ||
830 | /* u32 input = INPUT(dev->video_input)->vmux; */ | ||
831 | |||
832 | call_all(dev, video, s_stream, 1); | ||
833 | } | ||
834 | |||
835 | /* | ||
836 | * cx231xx_realease_resources() | ||
837 | * unregisters the v4l2,i2c and usb devices | ||
838 | * called when the device gets disconected or at module unload | ||
839 | */ | ||
840 | void cx231xx_release_resources(struct cx231xx *dev) | ||
841 | { | ||
842 | cx231xx_release_analog_resources(dev); | ||
843 | |||
844 | cx231xx_remove_from_devlist(dev); | ||
845 | |||
846 | /* Release I2C buses */ | ||
847 | cx231xx_dev_uninit(dev); | ||
848 | |||
849 | cx231xx_ir_exit(dev); | ||
850 | |||
851 | usb_put_dev(dev->udev); | ||
852 | |||
853 | /* Mark device as unused */ | ||
854 | cx231xx_devused &= ~(1 << dev->devno); | ||
855 | } | ||
856 | |||
857 | /* | ||
858 | * cx231xx_init_dev() | ||
859 | * allocates and inits the device structs, registers i2c bus and v4l device | ||
860 | */ | ||
861 | static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, | ||
862 | int minor) | ||
863 | { | ||
864 | struct cx231xx *dev = *devhandle; | ||
865 | int retval = -ENOMEM; | ||
866 | int errCode; | ||
867 | unsigned int maxh, maxw; | ||
868 | |||
869 | dev->udev = udev; | ||
870 | mutex_init(&dev->lock); | ||
871 | mutex_init(&dev->ctrl_urb_lock); | ||
872 | mutex_init(&dev->gpio_i2c_lock); | ||
873 | mutex_init(&dev->i2c_lock); | ||
874 | |||
875 | spin_lock_init(&dev->video_mode.slock); | ||
876 | spin_lock_init(&dev->vbi_mode.slock); | ||
877 | spin_lock_init(&dev->sliced_cc_mode.slock); | ||
878 | |||
879 | init_waitqueue_head(&dev->open); | ||
880 | init_waitqueue_head(&dev->wait_frame); | ||
881 | init_waitqueue_head(&dev->wait_stream); | ||
882 | |||
883 | dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg; | ||
884 | dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg; | ||
885 | dev->cx231xx_send_usb_command = cx231xx_send_usb_command; | ||
886 | dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read; | ||
887 | dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write; | ||
888 | |||
889 | /* Query cx231xx to find what pcb config it is related to */ | ||
890 | initialize_cx231xx(dev); | ||
891 | |||
892 | /*To workaround error number=-71 on EP0 for VideoGrabber, | ||
893 | need set alt here.*/ | ||
894 | if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER || | ||
895 | dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2) { | ||
896 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3); | ||
897 | cx231xx_set_alt_setting(dev, INDEX_VANC, 1); | ||
898 | } | ||
899 | /* Cx231xx pre card setup */ | ||
900 | cx231xx_pre_card_setup(dev); | ||
901 | |||
902 | errCode = cx231xx_config(dev); | ||
903 | if (errCode) { | ||
904 | cx231xx_errdev("error configuring device\n"); | ||
905 | return -ENOMEM; | ||
906 | } | ||
907 | |||
908 | /* set default norm */ | ||
909 | dev->norm = dev->board.norm; | ||
910 | |||
911 | /* register i2c bus */ | ||
912 | errCode = cx231xx_dev_init(dev); | ||
913 | if (errCode < 0) { | ||
914 | cx231xx_dev_uninit(dev); | ||
915 | cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n", | ||
916 | __func__, errCode); | ||
917 | return errCode; | ||
918 | } | ||
919 | |||
920 | /* Do board specific init */ | ||
921 | cx231xx_card_setup(dev); | ||
922 | |||
923 | /* configure the device */ | ||
924 | cx231xx_config_i2c(dev); | ||
925 | |||
926 | maxw = norm_maxw(dev); | ||
927 | maxh = norm_maxh(dev); | ||
928 | |||
929 | /* set default image size */ | ||
930 | dev->width = maxw; | ||
931 | dev->height = maxh; | ||
932 | dev->interlaced = 0; | ||
933 | dev->video_input = 0; | ||
934 | |||
935 | errCode = cx231xx_config(dev); | ||
936 | if (errCode < 0) { | ||
937 | cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n", | ||
938 | __func__, errCode); | ||
939 | return errCode; | ||
940 | } | ||
941 | |||
942 | /* init video dma queues */ | ||
943 | INIT_LIST_HEAD(&dev->video_mode.vidq.active); | ||
944 | INIT_LIST_HEAD(&dev->video_mode.vidq.queued); | ||
945 | |||
946 | /* init vbi dma queues */ | ||
947 | INIT_LIST_HEAD(&dev->vbi_mode.vidq.active); | ||
948 | INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued); | ||
949 | |||
950 | /* Reset other chips required if they are tied up with GPIO pins */ | ||
951 | cx231xx_add_into_devlist(dev); | ||
952 | |||
953 | if (dev->board.has_417) { | ||
954 | printk(KERN_INFO "attach 417 %d\n", dev->model); | ||
955 | if (cx231xx_417_register(dev) < 0) { | ||
956 | printk(KERN_ERR | ||
957 | "%s() Failed to register 417 on VID_B\n", | ||
958 | __func__); | ||
959 | } | ||
960 | } | ||
961 | |||
962 | retval = cx231xx_register_analog_devices(dev); | ||
963 | if (retval < 0) { | ||
964 | cx231xx_release_resources(dev); | ||
965 | return retval; | ||
966 | } | ||
967 | |||
968 | cx231xx_ir_init(dev); | ||
969 | |||
970 | cx231xx_init_extension(dev); | ||
971 | |||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | #if defined(CONFIG_MODULES) && defined(MODULE) | ||
976 | static void request_module_async(struct work_struct *work) | ||
977 | { | ||
978 | struct cx231xx *dev = container_of(work, | ||
979 | struct cx231xx, request_module_wk); | ||
980 | |||
981 | if (dev->has_alsa_audio) | ||
982 | request_module("cx231xx-alsa"); | ||
983 | |||
984 | if (dev->board.has_dvb) | ||
985 | request_module("cx231xx-dvb"); | ||
986 | |||
987 | } | ||
988 | |||
989 | static void request_modules(struct cx231xx *dev) | ||
990 | { | ||
991 | INIT_WORK(&dev->request_module_wk, request_module_async); | ||
992 | schedule_work(&dev->request_module_wk); | ||
993 | } | ||
994 | |||
995 | static void flush_request_modules(struct cx231xx *dev) | ||
996 | { | ||
997 | flush_work_sync(&dev->request_module_wk); | ||
998 | } | ||
999 | #else | ||
1000 | #define request_modules(dev) | ||
1001 | #define flush_request_modules(dev) | ||
1002 | #endif /* CONFIG_MODULES */ | ||
1003 | |||
1004 | /* | ||
1005 | * cx231xx_usb_probe() | ||
1006 | * checks for supported devices | ||
1007 | */ | ||
1008 | static int cx231xx_usb_probe(struct usb_interface *interface, | ||
1009 | const struct usb_device_id *id) | ||
1010 | { | ||
1011 | struct usb_device *udev; | ||
1012 | struct usb_interface *uif; | ||
1013 | struct cx231xx *dev = NULL; | ||
1014 | int retval = -ENODEV; | ||
1015 | int nr = 0, ifnum; | ||
1016 | int i, isoc_pipe = 0; | ||
1017 | char *speed; | ||
1018 | char descr[255] = ""; | ||
1019 | struct usb_interface *lif = NULL; | ||
1020 | struct usb_interface_assoc_descriptor *assoc_desc; | ||
1021 | |||
1022 | udev = usb_get_dev(interface_to_usbdev(interface)); | ||
1023 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | ||
1024 | |||
1025 | /* | ||
1026 | * Interface number 0 - IR interface (handled by mceusb driver) | ||
1027 | * Interface number 1 - AV interface (handled by this driver) | ||
1028 | */ | ||
1029 | if (ifnum != 1) | ||
1030 | return -ENODEV; | ||
1031 | |||
1032 | /* Check to see next free device and mark as used */ | ||
1033 | nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); | ||
1034 | cx231xx_devused |= 1 << nr; | ||
1035 | |||
1036 | if (nr >= CX231XX_MAXBOARDS) { | ||
1037 | cx231xx_err(DRIVER_NAME | ||
1038 | ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS); | ||
1039 | cx231xx_devused &= ~(1 << nr); | ||
1040 | return -ENOMEM; | ||
1041 | } | ||
1042 | |||
1043 | /* allocate memory for our device state and initialize it */ | ||
1044 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1045 | if (dev == NULL) { | ||
1046 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); | ||
1047 | cx231xx_devused &= ~(1 << nr); | ||
1048 | return -ENOMEM; | ||
1049 | } | ||
1050 | |||
1051 | snprintf(dev->name, 29, "cx231xx #%d", nr); | ||
1052 | dev->devno = nr; | ||
1053 | dev->model = id->driver_info; | ||
1054 | dev->video_mode.alt = -1; | ||
1055 | |||
1056 | dev->interface_count++; | ||
1057 | /* reset gpio dir and value */ | ||
1058 | dev->gpio_dir = 0; | ||
1059 | dev->gpio_val = 0; | ||
1060 | dev->xc_fw_load_done = 0; | ||
1061 | dev->has_alsa_audio = 1; | ||
1062 | dev->power_mode = -1; | ||
1063 | atomic_set(&dev->devlist_count, 0); | ||
1064 | |||
1065 | /* 0 - vbi ; 1 -sliced cc mode */ | ||
1066 | dev->vbi_or_sliced_cc_mode = 0; | ||
1067 | |||
1068 | /* get maximum no.of IAD interfaces */ | ||
1069 | assoc_desc = udev->actconfig->intf_assoc[0]; | ||
1070 | dev->max_iad_interface_count = assoc_desc->bInterfaceCount; | ||
1071 | |||
1072 | /* init CIR module TBD */ | ||
1073 | |||
1074 | /* store the current interface */ | ||
1075 | lif = interface; | ||
1076 | |||
1077 | /*mode_tv: digital=1 or analog=0*/ | ||
1078 | dev->mode_tv = 0; | ||
1079 | |||
1080 | dev->USE_ISO = transfer_mode; | ||
1081 | |||
1082 | switch (udev->speed) { | ||
1083 | case USB_SPEED_LOW: | ||
1084 | speed = "1.5"; | ||
1085 | break; | ||
1086 | case USB_SPEED_UNKNOWN: | ||
1087 | case USB_SPEED_FULL: | ||
1088 | speed = "12"; | ||
1089 | break; | ||
1090 | case USB_SPEED_HIGH: | ||
1091 | speed = "480"; | ||
1092 | break; | ||
1093 | default: | ||
1094 | speed = "unknown"; | ||
1095 | } | ||
1096 | |||
1097 | if (udev->manufacturer) | ||
1098 | strlcpy(descr, udev->manufacturer, sizeof(descr)); | ||
1099 | |||
1100 | if (udev->product) { | ||
1101 | if (*descr) | ||
1102 | strlcat(descr, " ", sizeof(descr)); | ||
1103 | strlcat(descr, udev->product, sizeof(descr)); | ||
1104 | } | ||
1105 | if (*descr) | ||
1106 | strlcat(descr, " ", sizeof(descr)); | ||
1107 | |||
1108 | cx231xx_info("New device %s@ %s Mbps " | ||
1109 | "(%04x:%04x) with %d interfaces\n", | ||
1110 | descr, | ||
1111 | speed, | ||
1112 | le16_to_cpu(udev->descriptor.idVendor), | ||
1113 | le16_to_cpu(udev->descriptor.idProduct), | ||
1114 | dev->max_iad_interface_count); | ||
1115 | |||
1116 | /* store the interface 0 back */ | ||
1117 | lif = udev->actconfig->interface[0]; | ||
1118 | |||
1119 | /* increment interface count */ | ||
1120 | dev->interface_count++; | ||
1121 | |||
1122 | /* get device number */ | ||
1123 | nr = dev->devno; | ||
1124 | |||
1125 | assoc_desc = udev->actconfig->intf_assoc[0]; | ||
1126 | if (assoc_desc->bFirstInterface != ifnum) { | ||
1127 | cx231xx_err(DRIVER_NAME ": Not found " | ||
1128 | "matching IAD interface\n"); | ||
1129 | cx231xx_devused &= ~(1 << nr); | ||
1130 | kfree(dev); | ||
1131 | dev = NULL; | ||
1132 | return -ENODEV; | ||
1133 | } | ||
1134 | |||
1135 | cx231xx_info("registering interface %d\n", ifnum); | ||
1136 | |||
1137 | /* save our data pointer in this interface device */ | ||
1138 | usb_set_intfdata(lif, dev); | ||
1139 | |||
1140 | /* | ||
1141 | * AV device initialization - only done at the last interface | ||
1142 | */ | ||
1143 | |||
1144 | /* Create v4l2 device */ | ||
1145 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); | ||
1146 | if (retval) { | ||
1147 | cx231xx_errdev("v4l2_device_register failed\n"); | ||
1148 | cx231xx_devused &= ~(1 << nr); | ||
1149 | kfree(dev); | ||
1150 | dev = NULL; | ||
1151 | return -EIO; | ||
1152 | } | ||
1153 | /* allocate device struct */ | ||
1154 | retval = cx231xx_init_dev(&dev, udev, nr); | ||
1155 | if (retval) { | ||
1156 | cx231xx_devused &= ~(1 << dev->devno); | ||
1157 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1158 | kfree(dev); | ||
1159 | dev = NULL; | ||
1160 | usb_set_intfdata(lif, NULL); | ||
1161 | |||
1162 | return retval; | ||
1163 | } | ||
1164 | |||
1165 | /* compute alternate max packet sizes for video */ | ||
1166 | uif = udev->actconfig->interface[dev->current_pcb_config. | ||
1167 | hs_config_info[0].interface_info.video_index + 1]; | ||
1168 | |||
1169 | dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0]. | ||
1170 | endpoint[isoc_pipe].desc.bEndpointAddress); | ||
1171 | |||
1172 | dev->video_mode.num_alt = uif->num_altsetting; | ||
1173 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
1174 | dev->video_mode.end_point_addr, | ||
1175 | dev->video_mode.num_alt); | ||
1176 | dev->video_mode.alt_max_pkt_size = | ||
1177 | kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); | ||
1178 | |||
1179 | if (dev->video_mode.alt_max_pkt_size == NULL) { | ||
1180 | cx231xx_errdev("out of memory!\n"); | ||
1181 | cx231xx_devused &= ~(1 << nr); | ||
1182 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1183 | kfree(dev); | ||
1184 | dev = NULL; | ||
1185 | return -ENOMEM; | ||
1186 | } | ||
1187 | |||
1188 | for (i = 0; i < dev->video_mode.num_alt; i++) { | ||
1189 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. | ||
1190 | desc.wMaxPacketSize); | ||
1191 | dev->video_mode.alt_max_pkt_size[i] = | ||
1192 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
1193 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
1194 | dev->video_mode.alt_max_pkt_size[i]); | ||
1195 | } | ||
1196 | |||
1197 | /* compute alternate max packet sizes for vbi */ | ||
1198 | uif = udev->actconfig->interface[dev->current_pcb_config. | ||
1199 | hs_config_info[0].interface_info. | ||
1200 | vanc_index + 1]; | ||
1201 | |||
1202 | dev->vbi_mode.end_point_addr = | ||
1203 | le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. | ||
1204 | bEndpointAddress); | ||
1205 | |||
1206 | dev->vbi_mode.num_alt = uif->num_altsetting; | ||
1207 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
1208 | dev->vbi_mode.end_point_addr, | ||
1209 | dev->vbi_mode.num_alt); | ||
1210 | dev->vbi_mode.alt_max_pkt_size = | ||
1211 | kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); | ||
1212 | |||
1213 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { | ||
1214 | cx231xx_errdev("out of memory!\n"); | ||
1215 | cx231xx_devused &= ~(1 << nr); | ||
1216 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1217 | kfree(dev); | ||
1218 | dev = NULL; | ||
1219 | return -ENOMEM; | ||
1220 | } | ||
1221 | |||
1222 | for (i = 0; i < dev->vbi_mode.num_alt; i++) { | ||
1223 | u16 tmp = | ||
1224 | le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. | ||
1225 | desc.wMaxPacketSize); | ||
1226 | dev->vbi_mode.alt_max_pkt_size[i] = | ||
1227 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
1228 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
1229 | dev->vbi_mode.alt_max_pkt_size[i]); | ||
1230 | } | ||
1231 | |||
1232 | /* compute alternate max packet sizes for sliced CC */ | ||
1233 | uif = udev->actconfig->interface[dev->current_pcb_config. | ||
1234 | hs_config_info[0].interface_info. | ||
1235 | hanc_index + 1]; | ||
1236 | |||
1237 | dev->sliced_cc_mode.end_point_addr = | ||
1238 | le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. | ||
1239 | bEndpointAddress); | ||
1240 | |||
1241 | dev->sliced_cc_mode.num_alt = uif->num_altsetting; | ||
1242 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
1243 | dev->sliced_cc_mode.end_point_addr, | ||
1244 | dev->sliced_cc_mode.num_alt); | ||
1245 | dev->sliced_cc_mode.alt_max_pkt_size = | ||
1246 | kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); | ||
1247 | |||
1248 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { | ||
1249 | cx231xx_errdev("out of memory!\n"); | ||
1250 | cx231xx_devused &= ~(1 << nr); | ||
1251 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1252 | kfree(dev); | ||
1253 | dev = NULL; | ||
1254 | return -ENOMEM; | ||
1255 | } | ||
1256 | |||
1257 | for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { | ||
1258 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. | ||
1259 | desc.wMaxPacketSize); | ||
1260 | dev->sliced_cc_mode.alt_max_pkt_size[i] = | ||
1261 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
1262 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
1263 | dev->sliced_cc_mode.alt_max_pkt_size[i]); | ||
1264 | } | ||
1265 | |||
1266 | if (dev->current_pcb_config.ts1_source != 0xff) { | ||
1267 | /* compute alternate max packet sizes for TS1 */ | ||
1268 | uif = udev->actconfig->interface[dev->current_pcb_config. | ||
1269 | hs_config_info[0]. | ||
1270 | interface_info. | ||
1271 | ts1_index + 1]; | ||
1272 | |||
1273 | dev->ts1_mode.end_point_addr = | ||
1274 | le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe]. | ||
1275 | desc.bEndpointAddress); | ||
1276 | |||
1277 | dev->ts1_mode.num_alt = uif->num_altsetting; | ||
1278 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
1279 | dev->ts1_mode.end_point_addr, | ||
1280 | dev->ts1_mode.num_alt); | ||
1281 | dev->ts1_mode.alt_max_pkt_size = | ||
1282 | kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); | ||
1283 | |||
1284 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { | ||
1285 | cx231xx_errdev("out of memory!\n"); | ||
1286 | cx231xx_devused &= ~(1 << nr); | ||
1287 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1288 | kfree(dev); | ||
1289 | dev = NULL; | ||
1290 | return -ENOMEM; | ||
1291 | } | ||
1292 | |||
1293 | for (i = 0; i < dev->ts1_mode.num_alt; i++) { | ||
1294 | u16 tmp = le16_to_cpu(uif->altsetting[i]. | ||
1295 | endpoint[isoc_pipe].desc. | ||
1296 | wMaxPacketSize); | ||
1297 | dev->ts1_mode.alt_max_pkt_size[i] = | ||
1298 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
1299 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
1300 | dev->ts1_mode.alt_max_pkt_size[i]); | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) { | ||
1305 | cx231xx_enable_OSC(dev); | ||
1306 | cx231xx_reset_out(dev); | ||
1307 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3); | ||
1308 | } | ||
1309 | |||
1310 | if (dev->model == CX231XX_BOARD_CNXT_RDE_253S) | ||
1311 | cx231xx_sleep_s5h1432(dev); | ||
1312 | |||
1313 | /* load other modules required */ | ||
1314 | request_modules(dev); | ||
1315 | |||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1319 | /* | ||
1320 | * cx231xx_usb_disconnect() | ||
1321 | * called when the device gets diconencted | ||
1322 | * video device will be unregistered on v4l2_close in case it is still open | ||
1323 | */ | ||
1324 | static void cx231xx_usb_disconnect(struct usb_interface *interface) | ||
1325 | { | ||
1326 | struct cx231xx *dev; | ||
1327 | |||
1328 | dev = usb_get_intfdata(interface); | ||
1329 | usb_set_intfdata(interface, NULL); | ||
1330 | |||
1331 | if (!dev) | ||
1332 | return; | ||
1333 | |||
1334 | if (!dev->udev) | ||
1335 | return; | ||
1336 | |||
1337 | flush_request_modules(dev); | ||
1338 | |||
1339 | /* delete v4l2 device */ | ||
1340 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1341 | |||
1342 | /* wait until all current v4l2 io is finished then deallocate | ||
1343 | resources */ | ||
1344 | mutex_lock(&dev->lock); | ||
1345 | |||
1346 | wake_up_interruptible_all(&dev->open); | ||
1347 | |||
1348 | if (dev->users) { | ||
1349 | cx231xx_warn | ||
1350 | ("device %s is open! Deregistration and memory " | ||
1351 | "deallocation are deferred on close.\n", | ||
1352 | video_device_node_name(dev->vdev)); | ||
1353 | |||
1354 | dev->state |= DEV_MISCONFIGURED; | ||
1355 | if (dev->USE_ISO) | ||
1356 | cx231xx_uninit_isoc(dev); | ||
1357 | else | ||
1358 | cx231xx_uninit_bulk(dev); | ||
1359 | dev->state |= DEV_DISCONNECTED; | ||
1360 | wake_up_interruptible(&dev->wait_frame); | ||
1361 | wake_up_interruptible(&dev->wait_stream); | ||
1362 | } else { | ||
1363 | dev->state |= DEV_DISCONNECTED; | ||
1364 | cx231xx_release_resources(dev); | ||
1365 | } | ||
1366 | |||
1367 | cx231xx_close_extension(dev); | ||
1368 | |||
1369 | mutex_unlock(&dev->lock); | ||
1370 | |||
1371 | if (!dev->users) { | ||
1372 | kfree(dev->video_mode.alt_max_pkt_size); | ||
1373 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
1374 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
1375 | kfree(dev->ts1_mode.alt_max_pkt_size); | ||
1376 | kfree(dev); | ||
1377 | dev = NULL; | ||
1378 | } | ||
1379 | } | ||
1380 | |||
1381 | static struct usb_driver cx231xx_usb_driver = { | ||
1382 | .name = "cx231xx", | ||
1383 | .probe = cx231xx_usb_probe, | ||
1384 | .disconnect = cx231xx_usb_disconnect, | ||
1385 | .id_table = cx231xx_id_table, | ||
1386 | }; | ||
1387 | |||
1388 | static int __init cx231xx_module_init(void) | ||
1389 | { | ||
1390 | int result; | ||
1391 | |||
1392 | printk(KERN_INFO DRIVER_NAME " v4l2 driver loaded.\n"); | ||
1393 | |||
1394 | /* register this driver with the USB subsystem */ | ||
1395 | result = usb_register(&cx231xx_usb_driver); | ||
1396 | if (result) | ||
1397 | cx231xx_err(DRIVER_NAME | ||
1398 | " usb_register failed. Error number %d.\n", result); | ||
1399 | |||
1400 | return result; | ||
1401 | } | ||
1402 | |||
1403 | static void __exit cx231xx_module_exit(void) | ||
1404 | { | ||
1405 | /* deregister this driver with the USB subsystem */ | ||
1406 | usb_deregister(&cx231xx_usb_driver); | ||
1407 | } | ||
1408 | |||
1409 | module_init(cx231xx_module_init); | ||
1410 | module_exit(cx231xx_module_exit); | ||