1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/module.h>
33#include <linux/errno.h>
34#include <linux/kernel.h>
35#include <linux/init.h>
36#include <linux/types.h>
37#include <linux/videodev2.h>
38#include <linux/i2c.h>
39
40#include <media/tuner.h>
41#include <media/tveeprom.h>
42#include <media/v4l2-common.h>
43#include <media/v4l2-chip-ident.h>
44
45MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver");
46MODULE_AUTHOR("John Klar");
47MODULE_LICENSE("GPL");
48
49static int debug;
50module_param(debug, int, 0644);
51MODULE_PARM_DESC(debug, "Debug level (0-1)");
52
53#define STRM(array, i) \
54 (i < sizeof(array) / sizeof(char *) ? array[i] : "unknown")
55
56#define tveeprom_info(fmt, arg...) \
57 v4l_printk(KERN_INFO, "tveeprom", c->adapter, c->addr, fmt , ## arg)
58#define tveeprom_warn(fmt, arg...) \
59 v4l_printk(KERN_WARNING, "tveeprom", c->adapter, c->addr, fmt , ## arg)
60#define tveeprom_dbg(fmt, arg...) do { \
61 if (debug) \
62 v4l_printk(KERN_DEBUG, "tveeprom", \
63 c->adapter, c->addr, fmt , ## arg); \
64 } while (0)
65
66
67
68
69
70static struct HAUPPAUGE_TUNER_FMT
71{
72 int id;
73 char *name;
74}
75hauppauge_tuner_fmt[] =
76{
77 { V4L2_STD_UNKNOWN, " UNKNOWN" },
78 { V4L2_STD_UNKNOWN, " FM" },
79 { V4L2_STD_B|V4L2_STD_GH, " PAL(B/G)" },
80 { V4L2_STD_MN, " NTSC(M)" },
81 { V4L2_STD_PAL_I, " PAL(I)" },
82 { V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC, " SECAM(L/L')" },
83 { V4L2_STD_DK, " PAL(D/D1/K)" },
84 { V4L2_STD_ATSC, " ATSC/DVB Digital" },
85};
86
87
88
89
90
91static struct HAUPPAUGE_TUNER
92{
93 int id;
94 char *name;
95}
96hauppauge_tuner[] =
97{
98
99 { TUNER_ABSENT, "None" },
100 { TUNER_ABSENT, "External" },
101 { TUNER_ABSENT, "Unspecified" },
102 { TUNER_PHILIPS_PAL, "Philips FI1216" },
103 { TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
104 { TUNER_PHILIPS_NTSC, "Philips FI1236" },
105 { TUNER_PHILIPS_PAL_I, "Philips FI1246" },
106 { TUNER_PHILIPS_PAL_DK, "Philips FI1256" },
107 { TUNER_PHILIPS_PAL, "Philips FI1216 MK2" },
108 { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
109
110 { TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" },
111 { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
112 { TUNER_PHILIPS_PAL_DK, "Philips FI1256 MK2" },
113 { TUNER_TEMIC_NTSC, "Temic 4032FY5" },
114 { TUNER_TEMIC_PAL, "Temic 4002FH5" },
115 { TUNER_TEMIC_PAL_I, "Temic 4062FY5" },
116 { TUNER_PHILIPS_PAL, "Philips FR1216 MK2" },
117 { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
118 { TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" },
119 { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
120
121 { TUNER_PHILIPS_PAL_DK, "Philips FR1256 MK2" },
122 { TUNER_PHILIPS_PAL, "Philips FM1216" },
123 { TUNER_PHILIPS_SECAM, "Philips FM1216MF" },
124 { TUNER_PHILIPS_NTSC, "Philips FM1236" },
125 { TUNER_PHILIPS_PAL_I, "Philips FM1246" },
126 { TUNER_PHILIPS_PAL_DK, "Philips FM1256" },
127 { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
128 { TUNER_ABSENT, "Samsung TCPN9082D" },
129 { TUNER_ABSENT, "Samsung TCPM9092P" },
130 { TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" },
131
132 { TUNER_ABSENT, "Samsung TCPN9085D" },
133 { TUNER_ABSENT, "Samsung TCPB9085P" },
134 { TUNER_ABSENT, "Samsung TCPL9091P" },
135 { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" },
136 { TUNER_PHILIPS_FQ1216ME, "Philips FQ1216 ME" },
137 { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" },
138 { TUNER_PHILIPS_NTSC, "Philips TD1536" },
139 { TUNER_PHILIPS_NTSC, "Philips TD1536D" },
140 { TUNER_PHILIPS_NTSC, "Philips FMR1236" },
141 { TUNER_ABSENT, "Philips FI1256MP" },
142
143 { TUNER_ABSENT, "Samsung TCPQ9091P" },
144 { TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
145 { TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" },
146 { TUNER_TEMIC_4046FM5, "Temic 4046FM5" },
147 { TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
148 { TUNER_ABSENT, "Philips TD1536D FH 44"},
149 { TUNER_LG_NTSC_FM, "LG TP18NSR01F"},
150 { TUNER_LG_PAL_FM, "LG TP18PSB01D"},
151 { TUNER_LG_PAL, "LG TP18PSB11D"},
152 { TUNER_LG_PAL_I_FM, "LG TAPC-I001D"},
153
154 { TUNER_LG_PAL_I, "LG TAPC-I701D"},
155 { TUNER_ABSENT, "Temic 4042FI5"},
156 { TUNER_MICROTUNE_4049FM5, "Microtune 4049 FM5"},
157 { TUNER_ABSENT, "LG TPI8NSR11F"},
158 { TUNER_ABSENT, "Microtune 4049 FM5 Alt I2C"},
159 { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216ME MK3"},
160 { TUNER_ABSENT, "Philips FI1236 MK3"},
161 { TUNER_PHILIPS_FM1216ME_MK3, "Philips FM1216 ME MK3"},
162 { TUNER_PHILIPS_FM1236_MK3, "Philips FM1236 MK3"},
163 { TUNER_ABSENT, "Philips FM1216MP MK3"},
164
165 { TUNER_PHILIPS_FM1216ME_MK3, "LG S001D MK3"},
166 { TUNER_ABSENT, "LG M001D MK3"},
167 { TUNER_PHILIPS_FM1216ME_MK3, "LG S701D MK3"},
168 { TUNER_ABSENT, "LG M701D MK3"},
169 { TUNER_ABSENT, "Temic 4146FM5"},
170 { TUNER_ABSENT, "Temic 4136FY5"},
171 { TUNER_ABSENT, "Temic 4106FH5"},
172 { TUNER_ABSENT, "Philips FQ1216LMP MK3"},
173 { TUNER_LG_NTSC_TAPE, "LG TAPE H001F MK3"},
174 { TUNER_LG_NTSC_TAPE, "LG TAPE H701F MK3"},
175
176 { TUNER_ABSENT, "LG TALN H200T"},
177 { TUNER_ABSENT, "LG TALN H250T"},
178 { TUNER_ABSENT, "LG TALN M200T"},
179 { TUNER_ABSENT, "LG TALN Z200T"},
180 { TUNER_ABSENT, "LG TALN S200T"},
181 { TUNER_ABSENT, "Thompson DTT7595"},
182 { TUNER_ABSENT, "Thompson DTT7592"},
183 { TUNER_ABSENT, "Silicon TDA8275C1 8290"},
184 { TUNER_ABSENT, "Silicon TDA8275C1 8290 FM"},
185 { TUNER_ABSENT, "Thompson DTT757"},
186
187 { TUNER_PHILIPS_FQ1216LME_MK3, "Philips FQ1216LME MK3"},
188 { TUNER_LG_PAL_NEW_TAPC, "LG TAPC G701D"},
189 { TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
190 { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
191 { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
192 { TUNER_TCL_2002N, "TCL 2002N 6A"},
193 { TUNER_PHILIPS_FM1236_MK3, "Philips FQ1236 MK3"},
194 { TUNER_SAMSUNG_TCPN_2121P30A, "Samsung TCPN 2121P30A"},
195 { TUNER_ABSENT, "Samsung TCPE 4121P30A"},
196 { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"},
197
198 { TUNER_ABSENT, "LG TALN H202T"},
199 { TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"},
200 { TUNER_PHILIPS_FQ1236A_MK4, "Philips FQ1236A MK4"},
201 { TUNER_ABSENT, "Philips FQ1286A MK4"},
202 { TUNER_ABSENT, "Philips FQ1216ME MK5"},
203 { TUNER_ABSENT, "Philips FQ1236 MK5"},
204 { TUNER_SAMSUNG_TCPG_6121P30A, "Samsung TCPG 6121P30A"},
205 { TUNER_TCL_2002MB, "TCL 2002MB_3H"},
206 { TUNER_ABSENT, "TCL 2002MI_3H"},
207 { TUNER_TCL_2002N, "TCL 2002N 5H"},
208
209 { TUNER_PHILIPS_FMD1216ME_MK3, "Philips FMD1216ME"},
210 { TUNER_TEA5767, "Philips TEA5768HL FM Radio"},
211 { TUNER_ABSENT, "Panasonic ENV57H12D5"},
212 { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05-4"},
213 { TUNER_PHILIPS_FM1236_MK3, "TCL MNM05-4"},
214 { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"},
215 { TUNER_ABSENT, "TCL MQNM05-4"},
216 { TUNER_ABSENT, "LG TAPC-W701D"},
217 { TUNER_ABSENT, "TCL 9886P-WM"},
218 { TUNER_ABSENT, "TCL 1676NM-WM"},
219
220 { TUNER_ABSENT, "Thompson DTT75105"},
221 { TUNER_ABSENT, "Conexant_CX24109"},
222 { TUNER_TCL_2002N, "TCL M2523_5N_E"},
223 { TUNER_TCL_2002MB, "TCL M2523_3DB_E"},
224 { TUNER_ABSENT, "Philips 8275A"},
225 { TUNER_ABSENT, "Microtune MT2060"},
226 { TUNER_PHILIPS_FM1236_MK3, "Philips FM1236 MK5"},
227 { TUNER_PHILIPS_FM1216ME_MK3, "Philips FM1216ME MK5"},
228 { TUNER_ABSENT, "TCL M2523_3DI_E"},
229 { TUNER_ABSENT, "Samsung THPD5222FG30A"},
230
231 { TUNER_XC2028, "Xceive XC3028"},
232 { TUNER_PHILIPS_FQ1216LME_MK3, "Philips FQ1216LME MK5"},
233 { TUNER_ABSENT, "Philips FQD1216LME"},
234 { TUNER_ABSENT, "Conexant CX24118A"},
235 { TUNER_ABSENT, "TCL DMF11WIP"},
236 { TUNER_ABSENT, "TCL MFNM05_4H_E"},
237 { TUNER_ABSENT, "TCL MNM05_4H_E"},
238 { TUNER_ABSENT, "TCL MPE05_2H_E"},
239 { TUNER_ABSENT, "TCL MQNM05_4_U"},
240 { TUNER_ABSENT, "TCL M2523_5NH_E"},
241
242 { TUNER_ABSENT, "TCL M2523_3DBH_E"},
243 { TUNER_ABSENT, "TCL M2523_3DIH_E"},
244 { TUNER_ABSENT, "TCL MFPE05_2_U"},
245 { TUNER_PHILIPS_FMD1216MEX_MK3, "Philips FMD1216MEX"},
246 { TUNER_ABSENT, "Philips FRH2036B"},
247 { TUNER_ABSENT, "Panasonic ENGF75_01GF"},
248 { TUNER_ABSENT, "MaxLinear MXL5005"},
249 { TUNER_ABSENT, "MaxLinear MXL5003"},
250 { TUNER_ABSENT, "Xceive XC2028"},
251 { TUNER_ABSENT, "Microtune MT2131"},
252
253 { TUNER_ABSENT, "Philips 8275A_8295"},
254 { TUNER_ABSENT, "TCL MF02GIP_5N_E"},
255 { TUNER_ABSENT, "TCL MF02GIP_3DB_E"},
256 { TUNER_ABSENT, "TCL MF02GIP_3DI_E"},
257 { TUNER_ABSENT, "Microtune MT2266"},
258 { TUNER_ABSENT, "TCL MF10WPP_4N_E"},
259 { TUNER_ABSENT, "LG TAPQ_H702F"},
260 { TUNER_ABSENT, "TCL M09WPP_4N_E"},
261 { TUNER_ABSENT, "MaxLinear MXL5005_v2"},
262 { TUNER_PHILIPS_TDA8290, "Philips 18271_8295"},
263
264 { TUNER_XC5000, "Xceive XC5000"},
265 { TUNER_ABSENT, "Xceive XC3028L"},
266 { TUNER_ABSENT, "NXP 18271C2_716x"},
267 { TUNER_ABSENT, "Xceive XC4000"},
268 { TUNER_ABSENT, "Dibcom 7070"},
269 { TUNER_PHILIPS_TDA8290, "NXP 18271C2"},
270};
271
272
273
274static struct HAUPPAUGE_AUDIOIC
275{
276 u32 id;
277 char *name;
278}
279audioIC[] =
280{
281
282 { V4L2_IDENT_NONE, "None" },
283 { V4L2_IDENT_UNKNOWN, "TEA6300" },
284 { V4L2_IDENT_UNKNOWN, "TEA6320" },
285 { V4L2_IDENT_UNKNOWN, "TDA9850" },
286 { V4L2_IDENT_MSPX4XX, "MSP3400C" },
287
288 { V4L2_IDENT_MSPX4XX, "MSP3410D" },
289 { V4L2_IDENT_MSPX4XX, "MSP3415" },
290 { V4L2_IDENT_MSPX4XX, "MSP3430" },
291 { V4L2_IDENT_MSPX4XX, "MSP3438" },
292 { V4L2_IDENT_UNKNOWN, "CS5331" },
293
294 { V4L2_IDENT_MSPX4XX, "MSP3435" },
295 { V4L2_IDENT_MSPX4XX, "MSP3440" },
296 { V4L2_IDENT_MSPX4XX, "MSP3445" },
297 { V4L2_IDENT_MSPX4XX, "MSP3411" },
298 { V4L2_IDENT_MSPX4XX, "MSP3416" },
299
300 { V4L2_IDENT_MSPX4XX, "MSP3425" },
301 { V4L2_IDENT_MSPX4XX, "MSP3451" },
302 { V4L2_IDENT_MSPX4XX, "MSP3418" },
303 { V4L2_IDENT_UNKNOWN, "Type 0x12" },
304 { V4L2_IDENT_UNKNOWN, "OKI7716" },
305
306 { V4L2_IDENT_MSPX4XX, "MSP4410" },
307 { V4L2_IDENT_MSPX4XX, "MSP4420" },
308 { V4L2_IDENT_MSPX4XX, "MSP4440" },
309 { V4L2_IDENT_MSPX4XX, "MSP4450" },
310 { V4L2_IDENT_MSPX4XX, "MSP4408" },
311
312 { V4L2_IDENT_MSPX4XX, "MSP4418" },
313 { V4L2_IDENT_MSPX4XX, "MSP4428" },
314 { V4L2_IDENT_MSPX4XX, "MSP4448" },
315 { V4L2_IDENT_MSPX4XX, "MSP4458" },
316 { V4L2_IDENT_MSPX4XX, "Type 0x1d" },
317
318 { V4L2_IDENT_AMBIGUOUS, "CX880" },
319 { V4L2_IDENT_AMBIGUOUS, "CX881" },
320 { V4L2_IDENT_AMBIGUOUS, "CX883" },
321 { V4L2_IDENT_AMBIGUOUS, "CX882" },
322 { V4L2_IDENT_AMBIGUOUS, "CX25840" },
323
324 { V4L2_IDENT_AMBIGUOUS, "CX25841" },
325 { V4L2_IDENT_AMBIGUOUS, "CX25842" },
326 { V4L2_IDENT_AMBIGUOUS, "CX25843" },
327 { V4L2_IDENT_AMBIGUOUS, "CX23418" },
328 { V4L2_IDENT_AMBIGUOUS, "CX23885" },
329
330 { V4L2_IDENT_AMBIGUOUS, "CX23888" },
331 { V4L2_IDENT_AMBIGUOUS, "SAA7131" },
332 { V4L2_IDENT_AMBIGUOUS, "CX23887" },
333 { V4L2_IDENT_AMBIGUOUS, "SAA7164" },
334 { V4L2_IDENT_AMBIGUOUS, "AU8522" },
335};
336
337
338static const char *decoderIC[] = {
339
340 "None", "BT815", "BT817", "BT819", "BT815A",
341
342 "BT817A", "BT819A", "BT827", "BT829", "BT848",
343
344 "BT848A", "BT849A", "BT829A", "BT827A", "BT878",
345
346 "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115",
347
348 "CX880", "CX881", "CX883", "SAA7111", "SAA7113",
349
350 "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842",
351
352 "CX25843", "CX23418", "NEC61153", "CX23885", "CX23888",
353
354 "SAA7131", "CX25837", "CX23887", "CX23885A", "CX23887A",
355
356 "SAA7164", "CX23885B", "AU8522"
357};
358
359static int hasRadioTuner(int tunerType)
360{
361 switch (tunerType) {
362 case 18:
363 case 23:
364 case 38:
365 case 16:
366 case 19:
367 case 21:
368 case 24:
369 case 17:
370 case 22:
371 case 20:
372 case 25:
373 case 33:
374 case 42:
375 case 52:
376 case 54:
377 case 44:
378 case 31:
379 case 30:
380 case 46:
381 case 47:
382 case 49:
383 case 60:
384 case 57:
385 case 59:
386 case 58:
387 case 68:
388 case 61:
389 case 78:
390 case 89:
391 case 92:
392 case 105:
393 return 1;
394 }
395 return 0;
396}
397
398void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
399 unsigned char *eeprom_data)
400{
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424 int i, j, len, done, beenhere, tag, start;
425
426 int tuner1 = 0, t_format1 = 0, audioic = -1;
427 char *t_name1 = NULL;
428 const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" };
429
430 int tuner2 = 0, t_format2 = 0;
431 char *t_name2 = NULL;
432 const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
433
434 memset(tvee, 0, sizeof(*tvee));
435 tvee->tuner_type = TUNER_ABSENT;
436 tvee->tuner2_type = TUNER_ABSENT;
437
438 done = len = beenhere = 0;
439
440
441 if (eeprom_data[0] == 0x1a &&
442 eeprom_data[1] == 0xeb &&
443 eeprom_data[2] == 0x67 &&
444 eeprom_data[3] == 0x95)
445 start = 0xa0;
446 else if ((eeprom_data[0] & 0xe1) == 0x01 &&
447 eeprom_data[1] == 0x00 &&
448 eeprom_data[2] == 0x00 &&
449 eeprom_data[8] == 0x84)
450 start = 8;
451 else if (eeprom_data[1] == 0x70 &&
452 eeprom_data[2] == 0x00 &&
453 eeprom_data[4] == 0x74 &&
454 eeprom_data[8] == 0x84)
455 start = 8;
456 else
457 start = 0;
458
459 for (i = start; !done && i < 256; i += len) {
460 if (eeprom_data[i] == 0x84) {
461 len = eeprom_data[i + 1] + (eeprom_data[i + 2] << 8);
462 i += 3;
463 } else if ((eeprom_data[i] & 0xf0) == 0x70) {
464 if (eeprom_data[i] & 0x08) {
465
466 done = 1;
467 break;
468 }
469 len = eeprom_data[i] & 0x07;
470 ++i;
471 } else {
472 tveeprom_warn("Encountered bad packet header [%02x]. "
473 "Corrupt or not a Hauppauge eeprom.\n",
474 eeprom_data[i]);
475 return;
476 }
477
478 if (debug) {
479 tveeprom_info("Tag [%02x] + %d bytes:",
480 eeprom_data[i], len - 1);
481 for (j = 1; j < len; j++)
482 printk(KERN_CONT " %02x", eeprom_data[i + j]);
483 printk(KERN_CONT "\n");
484 }
485
486
487 tag = eeprom_data[i];
488 switch (tag) {
489 case 0x00:
490
491 tuner1 = eeprom_data[i+6];
492 t_format1 = eeprom_data[i+5];
493 tvee->has_radio = eeprom_data[i+len-1];
494
495
496 tvee->has_ir = 0;
497 tvee->model =
498 eeprom_data[i+8] +
499 (eeprom_data[i+9] << 8);
500 tvee->revision = eeprom_data[i+10] +
501 (eeprom_data[i+11] << 8) +
502 (eeprom_data[i+12] << 16);
503 break;
504
505 case 0x01:
506
507 tvee->serial_number =
508 eeprom_data[i+6] +
509 (eeprom_data[i+7] << 8) +
510 (eeprom_data[i+8] << 16);
511 break;
512
513 case 0x02:
514
515
516
517
518 audioic = eeprom_data[i+2] & 0x7f;
519 if (audioic < ARRAY_SIZE(audioIC))
520 tvee->audio_processor = audioIC[audioic].id;
521 else
522 tvee->audio_processor = V4L2_IDENT_UNKNOWN;
523 break;
524
525
526
527 case 0x04:
528
529 tvee->serial_number =
530 eeprom_data[i+5] +
531 (eeprom_data[i+6] << 8) +
532 (eeprom_data[i+7] << 16);
533
534 if ((eeprom_data[i + 8] & 0xf0) &&
535 (tvee->serial_number < 0xffffff)) {
536 tvee->MAC_address[0] = 0x00;
537 tvee->MAC_address[1] = 0x0D;
538 tvee->MAC_address[2] = 0xFE;
539 tvee->MAC_address[3] = eeprom_data[i + 7];
540 tvee->MAC_address[4] = eeprom_data[i + 6];
541 tvee->MAC_address[5] = eeprom_data[i + 5];
542 tvee->has_MAC_address = 1;
543 }
544 break;
545
546 case 0x05:
547
548
549
550
551 audioic = eeprom_data[i+1] & 0x7f;
552 if (audioic < ARRAY_SIZE(audioIC))
553 tvee->audio_processor = audioIC[audioic].id;
554 else
555 tvee->audio_processor = V4L2_IDENT_UNKNOWN;
556
557 break;
558
559 case 0x06:
560
561 tvee->model =
562 eeprom_data[i + 1] +
563 (eeprom_data[i + 2] << 8) +
564 (eeprom_data[i + 3] << 16) +
565 (eeprom_data[i + 4] << 24);
566 tvee->revision =
567 eeprom_data[i + 5] +
568 (eeprom_data[i + 6] << 8) +
569 (eeprom_data[i + 7] << 16);
570 break;
571
572 case 0x07:
573
574
575 break;
576
577
578
579 case 0x09:
580
581 tvee->decoder_processor = eeprom_data[i + 1];
582 break;
583
584 case 0x0a:
585
586 if (beenhere == 0) {
587 tuner1 = eeprom_data[i + 2];
588 t_format1 = eeprom_data[i + 1];
589 beenhere = 1;
590 } else {
591
592 tuner2 = eeprom_data[i + 2];
593 t_format2 = eeprom_data[i + 1];
594
595 if (t_format2 == 0)
596 tvee->has_radio = 1;
597 }
598 break;
599
600 case 0x0b:
601
602
603
604 break;
605
606
607
608
609 case 0x0e:
610
611 tvee->has_radio = eeprom_data[i+1];
612 break;
613
614 case 0x0f:
615
616 tvee->has_ir = 1 | (eeprom_data[i+1] << 1);
617 break;
618
619
620
621
622
623 default:
624 tveeprom_dbg("Not sure what to do with tag [%02x]\n",
625 tag);
626
627 }
628 }
629
630 if (!done) {
631 tveeprom_warn("Ran out of data!\n");
632 return;
633 }
634
635 if (tvee->revision != 0) {
636 tvee->rev_str[0] = 32 + ((tvee->revision >> 18) & 0x3f);
637 tvee->rev_str[1] = 32 + ((tvee->revision >> 12) & 0x3f);
638 tvee->rev_str[2] = 32 + ((tvee->revision >> 6) & 0x3f);
639 tvee->rev_str[3] = 32 + (tvee->revision & 0x3f);
640 tvee->rev_str[4] = 0;
641 }
642
643 if (hasRadioTuner(tuner1) && !tvee->has_radio) {
644 tveeprom_info("The eeprom says no radio is present, but the tuner type\n");
645 tveeprom_info("indicates otherwise. I will assume that radio is present.\n");
646 tvee->has_radio = 1;
647 }
648
649 if (tuner1 < ARRAY_SIZE(hauppauge_tuner)) {
650 tvee->tuner_type = hauppauge_tuner[tuner1].id;
651 t_name1 = hauppauge_tuner[tuner1].name;
652 } else {
653 t_name1 = "unknown";
654 }
655
656 if (tuner2 < ARRAY_SIZE(hauppauge_tuner)) {
657 tvee->tuner2_type = hauppauge_tuner[tuner2].id;
658 t_name2 = hauppauge_tuner[tuner2].name;
659 } else {
660 t_name2 = "unknown";
661 }
662
663 tvee->tuner_hauppauge_model = tuner1;
664 tvee->tuner2_hauppauge_model = tuner2;
665 tvee->tuner_formats = 0;
666 tvee->tuner2_formats = 0;
667 for (i = j = 0; i < 8; i++) {
668 if (t_format1 & (1 << i)) {
669 tvee->tuner_formats |= hauppauge_tuner_fmt[i].id;
670 t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name;
671 }
672 }
673 for (i = j = 0; i < 8; i++) {
674 if (t_format2 & (1 << i)) {
675 tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id;
676 t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name;
677 }
678 }
679
680 tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",
681 tvee->model, tvee->rev_str, tvee->serial_number);
682 if (tvee->has_MAC_address == 1)
683 tveeprom_info("MAC address is %02X-%02X-%02X-%02X-%02X-%02X\n",
684 tvee->MAC_address[0], tvee->MAC_address[1],
685 tvee->MAC_address[2], tvee->MAC_address[3],
686 tvee->MAC_address[4], tvee->MAC_address[5]);
687 tveeprom_info("tuner model is %s (idx %d, type %d)\n",
688 t_name1, tuner1, tvee->tuner_type);
689 tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
690 t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2],
691 t_fmt_name1[3], t_fmt_name1[4], t_fmt_name1[5],
692 t_fmt_name1[6], t_fmt_name1[7], t_format1);
693 if (tuner2)
694 tveeprom_info("second tuner model is %s (idx %d, type %d)\n",
695 t_name2, tuner2, tvee->tuner2_type);
696 if (t_format2)
697 tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
698 t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2],
699 t_fmt_name2[3], t_fmt_name2[4], t_fmt_name2[5],
700 t_fmt_name2[6], t_fmt_name2[7], t_format2);
701 if (audioic < 0) {
702 tveeprom_info("audio processor is unknown (no idx)\n");
703 tvee->audio_processor = V4L2_IDENT_UNKNOWN;
704 } else {
705 if (audioic < ARRAY_SIZE(audioIC))
706 tveeprom_info("audio processor is %s (idx %d)\n",
707 audioIC[audioic].name, audioic);
708 else
709 tveeprom_info("audio processor is unknown (idx %d)\n",
710 audioic);
711 }
712 if (tvee->decoder_processor)
713 tveeprom_info("decoder processor is %s (idx %d)\n",
714 STRM(decoderIC, tvee->decoder_processor),
715 tvee->decoder_processor);
716 if (tvee->has_ir)
717 tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n",
718 tvee->has_radio ? "" : "no ",
719 (tvee->has_ir & 2) ? "" : "no ",
720 (tvee->has_ir & 4) ? "" : "no ");
721 else
722 tveeprom_info("has %sradio\n",
723 tvee->has_radio ? "" : "no ");
724}
725EXPORT_SYMBOL(tveeprom_hauppauge_analog);
726
727
728
729
730int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
731{
732 unsigned char buf;
733 int err;
734
735 buf = 0;
736 err = i2c_master_send(c, &buf, 1);
737 if (err != 1) {
738 tveeprom_info("Huh, no eeprom present (err=%d)?\n", err);
739 return -1;
740 }
741 err = i2c_master_recv(c, eedata, len);
742 if (err != len) {
743 tveeprom_warn("i2c eeprom read error (err=%d)\n", err);
744 return -1;
745 }
746 if (debug) {
747 int i;
748
749 tveeprom_info("full 256-byte eeprom dump:\n");
750 for (i = 0; i < len; i++) {
751 if (0 == (i % 16))
752 tveeprom_info("%02x:", i);
753 printk(KERN_CONT " %02x", eedata[i]);
754 if (15 == (i % 16))
755 printk(KERN_CONT "\n");
756 }
757 }
758 return 0;
759}
760EXPORT_SYMBOL(tveeprom_read);
761
762
763
764
765
766
767