]>
Commit | Line | Data |
---|---|---|
a6c2ba28 | 1 | /* |
f7abcd38 | 2 | em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices |
a6c2ba28 | 3 | |
f7abcd38 MCC |
4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> |
5 | Markus Rechberger <mrechberger@gmail.com> | |
2e7c6dc3 | 6 | Mauro Carvalho Chehab <mchehab@infradead.org> |
f7abcd38 | 7 | Sascha Sommer <saschasommer@freenet.de> |
a6c2ba28 | 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/init.h> | |
25 | #include <linux/module.h> | |
a6c2ba28 | 26 | #include <linux/delay.h> |
27 | #include <linux/i2c.h> | |
28 | #include <linux/usb.h> | |
29 | #include <media/tuner.h> | |
2474ed44 | 30 | #include <media/msp3400.h> |
c7c0b34c HV |
31 | #include <media/saa7115.h> |
32 | #include <media/tvp5150.h> | |
1f6173ed | 33 | #include <media/tveeprom.h> |
2474ed44 | 34 | #include <media/audiochip.h> |
9bb13a6d | 35 | #include <media/v4l2-common.h> |
a6c2ba28 | 36 | |
f7abcd38 | 37 | #include "em28xx.h" |
882876bf | 38 | #include "tuner-xc2028.h" |
a6c2ba28 | 39 | |
03910cc3 MCC |
40 | static int tuner = -1; |
41 | module_param(tuner, int, 0444); | |
42 | MODULE_PARM_DESC(tuner, "tuner type"); | |
43 | ||
44 | struct em28xx_hash_table { | |
45 | unsigned long hash; | |
46 | unsigned int model; | |
47 | unsigned int tuner; | |
48 | }; | |
49 | ||
3acf2809 | 50 | struct em28xx_board em28xx_boards[] = { |
596d92d5 MCC |
51 | [EM2800_BOARD_UNKNOWN] = { |
52 | .name = "Unknown EM2800 video grabber", | |
53 | .is_em2800 = 1, | |
54 | .vchannels = 2, | |
596d92d5 MCC |
55 | .tda9887_conf = TDA9887_PRESENT, |
56 | .has_tuner = 1, | |
3acf2809 | 57 | .decoder = EM28XX_SAA7113, |
596d92d5 | 58 | .input = {{ |
3acf2809 | 59 | .type = EM28XX_VMUX_COMPOSITE1, |
c7c0b34c | 60 | .vmux = SAA7115_COMPOSITE0, |
596d92d5 MCC |
61 | .amux = 1, |
62 | },{ | |
3acf2809 | 63 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 64 | .vmux = SAA7115_SVIDEO3, |
596d92d5 MCC |
65 | .amux = 1, |
66 | }}, | |
67 | }, | |
68 | [EM2820_BOARD_UNKNOWN] = { | |
3dbd85ba | 69 | .name = "Unknown EM2750/28xx video grabber", |
596d92d5 | 70 | .is_em2800 = 0, |
596d92d5 | 71 | }, |
4d17d083 | 72 | [EM2820_BOARD_KWORLD_PVRTV2800RF] = { |
33ccaa3f | 73 | .name = "Kworld PVR TV 2800 RF", |
4d17d083 MR |
74 | .is_em2800 = 0, |
75 | .vchannels = 2, | |
4d17d083 MR |
76 | .tda9887_conf = TDA9887_PRESENT, |
77 | .has_tuner = 1, | |
78 | .decoder = EM28XX_SAA7113, | |
79 | .input = {{ | |
80 | .type = EM28XX_VMUX_COMPOSITE1, | |
c7c0b34c | 81 | .vmux = SAA7115_COMPOSITE0, |
4d17d083 MR |
82 | .amux = 1, |
83 | },{ | |
84 | .type = EM28XX_VMUX_SVIDEO, | |
c7c0b34c | 85 | .vmux = SAA7115_SVIDEO3, |
4d17d083 MR |
86 | .amux = 1, |
87 | }}, | |
88 | }, | |
a6c2ba28 | 89 | [EM2820_BOARD_TERRATEC_CINERGY_250] = { |
90 | .name = "Terratec Cinergy 250 USB", | |
91 | .vchannels = 3, | |
a6c2ba28 | 92 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
93 | .tda9887_conf = TDA9887_PRESENT, | |
94 | .has_tuner = 1, | |
3acf2809 | 95 | .decoder = EM28XX_SAA7113, |
a6c2ba28 | 96 | .input = {{ |
3acf2809 | 97 | .type = EM28XX_VMUX_TELEVISION, |
c7c0b34c | 98 | .vmux = SAA7115_COMPOSITE2, |
9475fb1c | 99 | .amux = 1, |
a6c2ba28 | 100 | },{ |
3acf2809 | 101 | .type = EM28XX_VMUX_COMPOSITE1, |
c7c0b34c | 102 | .vmux = SAA7115_COMPOSITE0, |
a6c2ba28 | 103 | .amux = 1, |
104 | },{ | |
3acf2809 | 105 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 106 | .vmux = SAA7115_SVIDEO3, |
a6c2ba28 | 107 | .amux = 1, |
108 | }}, | |
109 | }, | |
110 | [EM2820_BOARD_PINNACLE_USB_2] = { | |
111 | .name = "Pinnacle PCTV USB 2", | |
112 | .vchannels = 3, | |
a6c2ba28 | 113 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
114 | .tda9887_conf = TDA9887_PRESENT, | |
115 | .has_tuner = 1, | |
3acf2809 | 116 | .decoder = EM28XX_SAA7113, |
a6c2ba28 | 117 | .input = {{ |
3acf2809 | 118 | .type = EM28XX_VMUX_TELEVISION, |
c7c0b34c | 119 | .vmux = SAA7115_COMPOSITE2, |
a6c2ba28 | 120 | .amux = 0, |
121 | },{ | |
3acf2809 | 122 | .type = EM28XX_VMUX_COMPOSITE1, |
c7c0b34c | 123 | .vmux = SAA7115_COMPOSITE0, |
a6c2ba28 | 124 | .amux = 1, |
125 | },{ | |
3acf2809 | 126 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 127 | .vmux = SAA7115_SVIDEO3, |
a6c2ba28 | 128 | .amux = 1, |
129 | }}, | |
130 | }, | |
131 | [EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = { | |
132 | .name = "Hauppauge WinTV USB 2", | |
133 | .vchannels = 3, | |
a6c2ba28 | 134 | .tuner_type = TUNER_PHILIPS_FM1236_MK3, |
135 | .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, | |
136 | .has_tuner = 1, | |
3acf2809 | 137 | .decoder = EM28XX_TVP5150, |
a6c2ba28 | 138 | .has_msp34xx = 1, |
139 | /*FIXME: S-Video not tested */ | |
140 | .input = {{ | |
3acf2809 | 141 | .type = EM28XX_VMUX_TELEVISION, |
c7c0b34c | 142 | .vmux = TVP5150_COMPOSITE0, |
2474ed44 | 143 | .amux = MSP_INPUT_DEFAULT, |
a6c2ba28 | 144 | },{ |
3acf2809 | 145 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 146 | .vmux = TVP5150_SVIDEO, |
07151724 HV |
147 | .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, |
148 | MSP_DSP_IN_SCART, MSP_DSP_IN_SCART), | |
a6c2ba28 | 149 | }}, |
150 | }, | |
12466577 | 151 | [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { |
122d1588 AT |
152 | .name = "Hauppauge WinTV HVR 900", |
153 | .vchannels = 3, | |
154 | .tda9887_conf = TDA9887_PRESENT, | |
155 | .tuner_type = TUNER_XC2028, | |
156 | .has_tuner = 1, | |
157 | .xc2028_type = XC2028_FIRM_MTS, | |
158 | .decoder = EM28XX_TVP5150, | |
159 | .input = {{ | |
160 | .type = EM28XX_VMUX_TELEVISION, | |
161 | .vmux = TVP5150_COMPOSITE0, | |
162 | .amux = 0, | |
163 | },{ | |
164 | .type = EM28XX_VMUX_COMPOSITE1, | |
165 | .vmux = TVP5150_COMPOSITE1, | |
166 | .amux = 1, | |
167 | },{ | |
168 | .type = EM28XX_VMUX_SVIDEO, | |
169 | .vmux = TVP5150_SVIDEO, | |
170 | .amux = 1, | |
171 | }}, | |
172 | }, | |
173 | [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = { | |
174 | .name = "Hauppauge WinTV HVR 950", | |
12466577 | 175 | .vchannels = 3, |
12466577 MCC |
176 | .tda9887_conf = TDA9887_PRESENT, |
177 | .tuner_type = TUNER_XC2028, | |
178 | .has_tuner = 1, | |
179 | .decoder = EM28XX_TVP5150, | |
180 | .input = {{ | |
12466577 MCC |
181 | .type = EM28XX_VMUX_TELEVISION, |
182 | .vmux = TVP5150_COMPOSITE0, | |
183 | .amux = 0, | |
7d070e26 MCC |
184 | },{ |
185 | .type = EM28XX_VMUX_COMPOSITE1, | |
186 | .vmux = TVP5150_COMPOSITE1, | |
187 | .amux = 1, | |
12466577 MCC |
188 | },{ |
189 | .type = EM28XX_VMUX_SVIDEO, | |
190 | .vmux = TVP5150_SVIDEO, | |
191 | .amux = 1, | |
192 | }}, | |
193 | }, | |
194 | [EM2880_BOARD_TERRATEC_HYBRID_XS] = { | |
195 | .name = "Terratec Hybrid XS", | |
196 | .vchannels = 3, | |
12466577 MCC |
197 | .tda9887_conf = TDA9887_PRESENT, |
198 | .has_tuner = 1, | |
199 | .tuner_type = TUNER_XC2028, | |
200 | .decoder = EM28XX_TVP5150, | |
201 | .input = {{ | |
202 | .type = EM28XX_VMUX_TELEVISION, | |
203 | .vmux = TVP5150_COMPOSITE0, | |
204 | .amux = 0, | |
205 | },{ | |
206 | .type = EM28XX_VMUX_COMPOSITE1, | |
207 | .vmux = TVP5150_COMPOSITE1, | |
208 | .amux = 1, | |
209 | },{ | |
210 | .type = EM28XX_VMUX_SVIDEO, | |
211 | .vmux = TVP5150_SVIDEO, | |
212 | .amux = 1, | |
213 | }}, | |
214 | }, | |
215 | /* maybe there's a reason behind it why Terratec sells the Hybrid XS as Prodigy XS with a | |
216 | * different PID, let's keep it separated for now maybe we'll need it lateron */ | |
217 | [EM2880_BOARD_TERRATEC_PRODIGY_XS] = { | |
218 | .name = "Terratec Prodigy XS", | |
219 | .vchannels = 3, | |
12466577 MCC |
220 | .tda9887_conf = TDA9887_PRESENT, |
221 | .has_tuner = 1, | |
222 | .tuner_type = TUNER_XC2028, | |
223 | .decoder = EM28XX_TVP5150, | |
224 | .input = {{ | |
225 | .type = EM28XX_VMUX_TELEVISION, | |
226 | .vmux = TVP5150_COMPOSITE0, | |
227 | .amux = 0, | |
228 | },{ | |
229 | .type = EM28XX_VMUX_COMPOSITE1, | |
230 | .vmux = TVP5150_COMPOSITE1, | |
231 | .amux = 1, | |
232 | },{ | |
233 | .type = EM28XX_VMUX_SVIDEO, | |
234 | .vmux = TVP5150_SVIDEO, | |
235 | .amux = 1, | |
236 | }}, | |
237 | }, | |
a6c2ba28 | 238 | [EM2820_BOARD_MSI_VOX_USB_2] = { |
239 | .name = "MSI VOX USB 2.0", | |
240 | .vchannels = 3, | |
08eca13d | 241 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
a6c2ba28 | 242 | .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, |
243 | .has_tuner = 1, | |
3acf2809 | 244 | .decoder = EM28XX_SAA7114, |
a6c2ba28 | 245 | .input = {{ |
3acf2809 | 246 | .type = EM28XX_VMUX_TELEVISION, |
c7c0b34c | 247 | .vmux = SAA7115_COMPOSITE4, |
a6c2ba28 | 248 | .amux = 0, |
249 | },{ | |
3acf2809 | 250 | .type = EM28XX_VMUX_COMPOSITE1, |
c7c0b34c | 251 | .vmux = SAA7115_COMPOSITE0, |
a6c2ba28 | 252 | .amux = 1, |
253 | },{ | |
3acf2809 | 254 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 255 | .vmux = SAA7115_SVIDEO3, |
a6c2ba28 | 256 | .amux = 1, |
257 | }}, | |
258 | }, | |
596d92d5 MCC |
259 | [EM2800_BOARD_TERRATEC_CINERGY_200] = { |
260 | .name = "Terratec Cinergy 200 USB", | |
596d92d5 MCC |
261 | .is_em2800 = 1, |
262 | .vchannels = 3, | |
596d92d5 MCC |
263 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
264 | .tda9887_conf = TDA9887_PRESENT, | |
265 | .has_tuner = 1, | |
3acf2809 | 266 | .decoder = EM28XX_SAA7113, |
596d92d5 | 267 | .input = {{ |
3acf2809 | 268 | .type = EM28XX_VMUX_TELEVISION, |
c7c0b34c | 269 | .vmux = SAA7115_COMPOSITE2, |
596d92d5 MCC |
270 | .amux = 0, |
271 | },{ | |
3acf2809 | 272 | .type = EM28XX_VMUX_COMPOSITE1, |
c7c0b34c | 273 | .vmux = SAA7115_COMPOSITE0, |
596d92d5 MCC |
274 | .amux = 1, |
275 | },{ | |
3acf2809 | 276 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 277 | .vmux = SAA7115_SVIDEO3, |
596d92d5 MCC |
278 | .amux = 1, |
279 | }}, | |
280 | }, | |
281 | [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { | |
282 | .name = "Leadtek Winfast USB II", | |
596d92d5 MCC |
283 | .is_em2800 = 1, |
284 | .vchannels = 3, | |
596d92d5 MCC |
285 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
286 | .tda9887_conf = TDA9887_PRESENT, | |
287 | .has_tuner = 1, | |
3acf2809 | 288 | .decoder = EM28XX_SAA7113, |
596d92d5 | 289 | .input = {{ |
3acf2809 | 290 | .type = EM28XX_VMUX_TELEVISION, |
c7c0b34c | 291 | .vmux = SAA7115_COMPOSITE2, |
596d92d5 MCC |
292 | .amux = 0, |
293 | },{ | |
3acf2809 | 294 | .type = EM28XX_VMUX_COMPOSITE1, |
c7c0b34c | 295 | .vmux = SAA7115_COMPOSITE0, |
596d92d5 MCC |
296 | .amux = 1, |
297 | },{ | |
3acf2809 | 298 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 299 | .vmux = SAA7115_SVIDEO3, |
596d92d5 MCC |
300 | .amux = 1, |
301 | }}, | |
302 | }, | |
303 | [EM2800_BOARD_KWORLD_USB2800] = { | |
304 | .name = "Kworld USB2800", | |
596d92d5 MCC |
305 | .is_em2800 = 1, |
306 | .vchannels = 3, | |
596d92d5 MCC |
307 | .tuner_type = TUNER_PHILIPS_ATSC, |
308 | .tda9887_conf = TDA9887_PRESENT, | |
309 | .has_tuner = 1, | |
3acf2809 | 310 | .decoder = EM28XX_SAA7113, |
596d92d5 | 311 | .input = {{ |
3acf2809 | 312 | .type = EM28XX_VMUX_TELEVISION, |
c7c0b34c | 313 | .vmux = SAA7115_COMPOSITE2, |
596d92d5 MCC |
314 | .amux = 0, |
315 | },{ | |
3acf2809 | 316 | .type = EM28XX_VMUX_COMPOSITE1, |
c7c0b34c | 317 | .vmux = SAA7115_COMPOSITE0, |
596d92d5 MCC |
318 | .amux = 1, |
319 | },{ | |
3acf2809 | 320 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 321 | .vmux = SAA7115_SVIDEO3, |
596d92d5 MCC |
322 | .amux = 1, |
323 | }}, | |
324 | }, | |
45632c4f MCC |
325 | [EM2820_BOARD_PINNACLE_DVC_90] = { |
326 | .name = "Pinnacle Dazzle DVC 90", | |
327 | .vchannels = 3, | |
45632c4f | 328 | .has_tuner = 0, |
3acf2809 | 329 | .decoder = EM28XX_SAA7113, |
45632c4f | 330 | .input = {{ |
3acf2809 | 331 | .type = EM28XX_VMUX_COMPOSITE1, |
c7c0b34c | 332 | .vmux = SAA7115_COMPOSITE0, |
45632c4f MCC |
333 | .amux = 1, |
334 | },{ | |
3acf2809 | 335 | .type = EM28XX_VMUX_SVIDEO, |
c7c0b34c | 336 | .vmux = SAA7115_SVIDEO3, |
45632c4f MCC |
337 | .amux = 1, |
338 | }}, | |
339 | }, | |
4362559d SS |
340 | [EM2800_BOARD_VGEAR_POCKETTV] = { |
341 | .name = "V-Gear PocketTV", | |
342 | .is_em2800 = 1, | |
343 | .vchannels = 3, | |
4362559d SS |
344 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
345 | .tda9887_conf = TDA9887_PRESENT, | |
346 | .has_tuner = 1, | |
347 | .decoder = EM28XX_SAA7113, | |
348 | .input = {{ | |
349 | .type = EM28XX_VMUX_TELEVISION, | |
350 | .vmux = SAA7115_COMPOSITE2, | |
351 | .amux = 0, | |
352 | },{ | |
353 | .type = EM28XX_VMUX_COMPOSITE1, | |
354 | .vmux = SAA7115_COMPOSITE0, | |
355 | .amux = 1, | |
356 | },{ | |
357 | .type = EM28XX_VMUX_SVIDEO, | |
358 | .vmux = SAA7115_SVIDEO3, | |
359 | .amux = 1, | |
360 | }}, | |
361 | }, | |
ea4fd567 MCC |
362 | [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { |
363 | .name = "Pixelview Prolink PlayTV USB 2.0", | |
364 | .vchannels = 3, | |
365 | .tda9887_conf = TDA9887_PRESENT, | |
366 | .has_tuner = 1, | |
367 | .decoder = EM28XX_SAA7113, | |
368 | .input = {{ | |
369 | .type = EM28XX_VMUX_TELEVISION, | |
370 | .vmux = SAA7115_COMPOSITE2, | |
371 | .amux = 1, | |
372 | },{ | |
373 | .type = EM28XX_VMUX_COMPOSITE1, | |
374 | .vmux = SAA7115_COMPOSITE0, | |
375 | .amux = 1, | |
376 | },{ | |
377 | .type = EM28XX_VMUX_SVIDEO, | |
378 | .vmux = SAA7115_SVIDEO3, | |
379 | .amux = 1, | |
380 | }}, | |
381 | }, | |
a6c2ba28 | 382 | }; |
3acf2809 | 383 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); |
a6c2ba28 | 384 | |
385 | /* table of devices that work with this driver */ | |
3acf2809 | 386 | struct usb_device_id em28xx_id_table [] = { |
3dbd85ba | 387 | { USB_DEVICE(0xeb1a, 0x2750), .driver_info = EM2820_BOARD_UNKNOWN }, |
596d92d5 | 388 | { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN }, |
3dbd85ba MCC |
389 | { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN }, |
390 | { USB_DEVICE(0xeb1a, 0x2821), .driver_info = EM2820_BOARD_UNKNOWN }, | |
391 | { USB_DEVICE(0xeb1a, 0x2860), .driver_info = EM2820_BOARD_UNKNOWN }, | |
392 | { USB_DEVICE(0xeb1a, 0x2861), .driver_info = EM2820_BOARD_UNKNOWN }, | |
393 | { USB_DEVICE(0xeb1a, 0x2870), .driver_info = EM2820_BOARD_UNKNOWN }, | |
394 | { USB_DEVICE(0xeb1a, 0x2881), .driver_info = EM2820_BOARD_UNKNOWN }, | |
395 | { USB_DEVICE(0xeb1a, 0x2883), .driver_info = EM2820_BOARD_UNKNOWN }, | |
a6c2ba28 | 396 | { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, |
397 | { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, | |
398 | { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, | |
45632c4f | 399 | { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, |
12466577 | 400 | { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, |
122d1588 | 401 | { USB_DEVICE(0x2040, 0x6513), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, |
12466577 MCC |
402 | { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, |
403 | { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, | |
a6c2ba28 | 404 | { }, |
405 | }; | |
03910cc3 MCC |
406 | MODULE_DEVICE_TABLE (usb, em28xx_id_table); |
407 | ||
d2ba055d MCC |
408 | /* EEPROM hash table for devices with generic USB IDs */ |
409 | static struct em28xx_hash_table em28xx_eeprom_hash [] = { | |
ea4fd567 MCC |
410 | /* P/N: SA 60002070465 Tuner: TVF7533-MF */ |
411 | { 0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF }, | |
03910cc3 | 412 | }; |
a6c2ba28 | 413 | |
d2ba055d | 414 | /* I2C devicelist hash table for devices with generic USB IDs */ |
fad7b958 SS |
415 | static struct em28xx_hash_table em28xx_i2c_hash[] = { |
416 | { 0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC }, | |
417 | { 0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC }, | |
418 | }; | |
419 | ||
03910cc3 MCC |
420 | /* Since em28xx_pre_card_setup() requires a proper dev->model, |
421 | * this won't work for boards with generic PCI IDs | |
422 | */ | |
a94e95b4 MR |
423 | void em28xx_pre_card_setup(struct em28xx *dev) |
424 | { | |
425 | /* request some modules */ | |
426 | switch(dev->model){ | |
03910cc3 MCC |
427 | case EM2880_BOARD_TERRATEC_PRODIGY_XS: |
428 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | |
122d1588 | 429 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: |
03910cc3 MCC |
430 | case EM2880_BOARD_TERRATEC_HYBRID_XS: |
431 | /* reset through GPIO? */ | |
432 | em28xx_write_regs_req(dev, 0x00, 0x08, "\x7d", 1); | |
433 | break; | |
434 | } | |
435 | } | |
436 | ||
437 | static int em28xx_tuner_callback(void *ptr, int command, int arg) | |
438 | { | |
439 | int rc = 0; | |
440 | struct em28xx *dev = ptr; | |
441 | ||
442 | if (dev->tuner_type != TUNER_XC2028) | |
443 | return 0; | |
444 | ||
445 | switch (command) { | |
446 | case XC2028_TUNER_RESET: | |
447 | /* FIXME: This is device-dependent */ | |
448 | dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); | |
449 | dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); | |
450 | ||
451 | msleep(140); | |
452 | break; | |
a94e95b4 | 453 | } |
03910cc3 | 454 | return rc; |
a94e95b4 MR |
455 | } |
456 | ||
882876bf MCC |
457 | static void em28xx_config_tuner (struct em28xx *dev) |
458 | { | |
459 | struct v4l2_priv_tun_config xc2028_cfg; | |
460 | struct xc2028_ctrl ctl; | |
03910cc3 MCC |
461 | struct tuner_setup tun_setup; |
462 | struct v4l2_frequency f; | |
463 | ||
464 | if (!dev->has_tuner) | |
465 | return; | |
466 | ||
467 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | |
468 | tun_setup.type = dev->tuner_type; | |
469 | tun_setup.addr = dev->tuner_addr; | |
470 | tun_setup.tuner_callback = em28xx_tuner_callback; | |
471 | ||
472 | em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); | |
473 | ||
474 | if (dev->tuner_type == TUNER_XC2028) { | |
475 | memset (&ctl, 0, sizeof(ctl)); | |
476 | ||
477 | ctl.fname = XC2028_DEFAULT_FIRMWARE; | |
478 | ctl.max_len = 64; | |
122d1588 | 479 | ctl.type = em28xx_boards[dev->model].xc2028_type; |
03910cc3 MCC |
480 | |
481 | xc2028_cfg.tuner = TUNER_XC2028; | |
482 | xc2028_cfg.priv = &ctl; | |
882876bf | 483 | |
03910cc3 MCC |
484 | em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); |
485 | } | |
486 | ||
487 | /* configure tuner */ | |
488 | f.tuner = 0; | |
489 | f.type = V4L2_TUNER_ANALOG_TV; | |
490 | f.frequency = 9076; /* just a magic number */ | |
491 | dev->ctl_freq = f.frequency; | |
492 | em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); | |
493 | } | |
494 | ||
495 | static int em28xx_hint_board(struct em28xx *dev) | |
496 | { | |
497 | int i; | |
882876bf | 498 | |
d2ba055d MCC |
499 | /* HINT method: EEPROM |
500 | * | |
501 | * This method works only for boards with eeprom. | |
502 | * Uses a hash of all eeprom bytes. The hash should be | |
503 | * unique for a vendor/tuner pair. | |
504 | * There are a high chance that tuners for different | |
505 | * video standards produce different hashes. | |
506 | */ | |
507 | for (i = 0; i < ARRAY_SIZE(em28xx_eeprom_hash); i++) { | |
508 | if (dev->hash == em28xx_eeprom_hash[i].hash) { | |
509 | dev->model = em28xx_eeprom_hash[i].model; | |
510 | dev->tuner_type = em28xx_eeprom_hash[i].tuner; | |
882876bf | 511 | |
03910cc3 MCC |
512 | em28xx_errdev("Your board has no unique USB ID.\n"); |
513 | em28xx_errdev("A hint were successfully done, " | |
514 | "based on eeprom hash.\n"); | |
515 | em28xx_errdev("This method is not 100%% failproof.\n"); | |
516 | em28xx_errdev("If the board were missdetected, " | |
517 | "please email this log to:\n"); | |
518 | em28xx_errdev("\tV4L Mailing List " | |
519 | " <video4linux-list@redhat.com>\n"); | |
520 | em28xx_errdev("Board detected as %s\n", | |
521 | em28xx_boards[dev->model].name); | |
882876bf | 522 | |
03910cc3 MCC |
523 | return 0; |
524 | } | |
525 | } | |
fad7b958 | 526 | |
d2ba055d MCC |
527 | /* HINT method: I2C attached devices |
528 | * | |
529 | * This method works for all boards. | |
530 | * Uses a hash of i2c scanned devices. | |
531 | * Devices with the same i2c attached chips will | |
532 | * be considered equal. | |
533 | * This method is less precise than the eeprom one. | |
534 | */ | |
535 | ||
fad7b958 SS |
536 | /* user did not request i2c scanning => do it now */ |
537 | if (!dev->i2c_hash) | |
538 | em28xx_do_i2c_scan(dev); | |
539 | ||
540 | for (i = 0; i < ARRAY_SIZE(em28xx_i2c_hash); i++) { | |
541 | if (dev->i2c_hash == em28xx_i2c_hash[i].hash) { | |
542 | dev->model = em28xx_i2c_hash[i].model; | |
543 | dev->tuner_type = em28xx_i2c_hash[i].tuner; | |
544 | em28xx_errdev("Your board has no unique USB ID.\n"); | |
545 | em28xx_errdev("A hint were successfully done, " | |
546 | "based on i2c devicelist hash.\n"); | |
547 | em28xx_errdev("This method is not 100%% failproof.\n"); | |
548 | em28xx_errdev("If the board were missdetected, " | |
549 | "please email this log to:\n"); | |
550 | em28xx_errdev("\tV4L Mailing List " | |
551 | " <video4linux-list@redhat.com>\n"); | |
552 | em28xx_errdev("Board detected as %s\n", | |
553 | em28xx_boards[dev->model].name); | |
554 | ||
555 | return 0; | |
556 | } | |
557 | } | |
558 | ||
03910cc3 MCC |
559 | em28xx_errdev("Your board has no unique USB ID and thus need a " |
560 | "hint to be detected.\n"); | |
561 | em28xx_errdev("You may try to use card=<n> insmod option to " | |
562 | "workaround that.\n"); | |
563 | em28xx_errdev("Please send an email with this log to:\n"); | |
564 | em28xx_errdev("\tV4L Mailing List <video4linux-list@redhat.com>\n"); | |
565 | em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash); | |
fad7b958 | 566 | em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash); |
03910cc3 MCC |
567 | |
568 | em28xx_errdev("Here is a list of valid choices for the card=<n>" | |
569 | " insmod option:\n"); | |
570 | for (i = 0; i < em28xx_bcount; i++) { | |
571 | em28xx_errdev(" card=%d -> %s\n", | |
572 | i, em28xx_boards[i].name); | |
573 | } | |
574 | return -1; | |
882876bf MCC |
575 | } |
576 | ||
f8b6030c MCC |
577 | |
578 | static void em28xx_set_model(struct em28xx *dev) | |
579 | { | |
580 | dev->is_em2800 = em28xx_boards[dev->model].is_em2800; | |
581 | dev->has_tuner = em28xx_boards[dev->model].has_tuner; | |
582 | dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx; | |
583 | dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; | |
584 | dev->decoder = em28xx_boards[dev->model].decoder; | |
585 | dev->video_inputs = em28xx_boards[dev->model].vchannels; | |
586 | ||
587 | if (!em28xx_boards[dev->model].has_tuner) | |
588 | dev->tuner_type = UNSET; | |
589 | } | |
590 | ||
3acf2809 | 591 | void em28xx_card_setup(struct em28xx *dev) |
a6c2ba28 | 592 | { |
f8b6030c MCC |
593 | em28xx_set_model(dev); |
594 | ||
595 | dev->tuner_type = em28xx_boards[dev->model].tuner_type; | |
596 | ||
a6c2ba28 | 597 | /* request some modules */ |
03910cc3 MCC |
598 | switch (dev->model) { |
599 | case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: | |
98ae127c | 600 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
122d1588 | 601 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: |
03910cc3 MCC |
602 | { |
603 | struct tveeprom tv; | |
a6c2ba28 | 604 | #ifdef CONFIG_MODULES |
03910cc3 | 605 | request_module("tveeprom"); |
a6c2ba28 | 606 | #endif |
03910cc3 MCC |
607 | /* Call first TVeeprom */ |
608 | ||
609 | dev->i2c_client.addr = 0xa0 >> 1; | |
610 | tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); | |
4d17d083 | 611 | |
03910cc3 MCC |
612 | dev->tuner_type = tv.tuner_type; |
613 | if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { | |
614 | dev->i2s_speed = 2048000; | |
615 | dev->has_msp34xx = 1; | |
616 | } | |
98ae127c MCC |
617 | #ifdef CONFIG_MODULES |
618 | if (tv.has_ir) | |
619 | request_module("ir-kbd-i2c"); | |
620 | #endif | |
621 | /* FIXME: Should also retrieve decoder processor type */ | |
622 | ||
03910cc3 | 623 | break; |
a6c2ba28 | 624 | } |
03910cc3 MCC |
625 | case EM2820_BOARD_KWORLD_PVRTV2800RF: |
626 | /* GPIO enables sound on KWORLD PVR TV 2800RF */ | |
627 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xf9", 1); | |
628 | break; | |
629 | case EM2820_BOARD_UNKNOWN: | |
630 | case EM2800_BOARD_UNKNOWN: | |
f8b6030c MCC |
631 | if (!em28xx_hint_board(dev)) |
632 | em28xx_set_model(dev); | |
03910cc3 MCC |
633 | } |
634 | ||
f8b6030c | 635 | /* Allow override tuner type by a module parameter */ |
03910cc3 MCC |
636 | if (tuner >= 0) |
637 | dev->tuner_type = tuner; | |
638 | ||
639 | #ifdef CONFIG_MODULES | |
640 | /* request some modules */ | |
641 | if (dev->has_msp34xx) | |
642 | request_module("msp3400"); | |
643 | if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) | |
644 | request_module("saa7115"); | |
645 | if (dev->decoder == EM28XX_TVP5150) | |
646 | request_module("tvp5150"); | |
647 | if (dev->has_tuner) | |
648 | request_module("tuner"); | |
649 | #endif | |
650 | ||
882876bf | 651 | em28xx_config_tuner (dev); |
a6c2ba28 | 652 | } |