]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/media/video/tveeprom.c
Merge master.kernel.org:/home/rmk/linux-2.6-serial
[karo-tx-linux.git] / drivers / media / video / tveeprom.c
1 /*
2  * tveeprom - eeprom decoder for tvcard configuration eeproms
3  *
4  * Data and decoding routines shamelessly borrowed from bttv-cards.c
5  * eeprom access routine shamelessly borrowed from bttv-if.c
6  * which are:
7
8     Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
9                            & Marcus Metzler (mocm@thp.uni-koeln.de)
10     (c) 1999-2001 Gerd Knorr <kraxel@goldbach.in-berlin.de>
11
12  * Adjustments to fit a more general model and all bugs:
13
14         Copyright (C) 2003 John Klar <linpvr at projectplasma.com>
15
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29  */
30
31
32 #include <linux/module.h>
33 #include <linux/moduleparam.h>
34 #include <linux/errno.h>
35 #include <linux/kernel.h>
36 #include <linux/init.h>
37 #include <linux/types.h>
38 #include <linux/videodev.h>
39 #include <linux/i2c.h>
40
41 #include <media/tuner.h>
42 #include <media/tveeprom.h>
43
44 MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver");
45 MODULE_AUTHOR("John Klar");
46 MODULE_LICENSE("GPL");
47
48 static int debug = 0;
49 module_param(debug, int, 0644);
50 MODULE_PARM_DESC(debug, "Debug level (0-1)");
51
52 #define STRM(array,i) (i < sizeof(array)/sizeof(char*) ? array[i] : "unknown")
53
54 #define tveeprom_info(fmt, arg...) do {\
55         printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
56                         c->adapter->nr, c->addr , ##arg); } while (0)
57 #define tveeprom_warn(fmt, arg...) do {\
58         printk(KERN_WARNING "tveeprom %d-%04x: " fmt, \
59                         c->adapter->nr, c->addr , ##arg); } while (0)
60 #define tveeprom_dbg(fmt, arg...) do {\
61         if (debug) \
62                 printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
63                         c->adapter->nr, c->addr , ##arg); } while (0)
64
65
66 /* ----------------------------------------------------------------------- */
67 /* some hauppauge specific stuff                                           */
68
69 static struct HAUPPAUGE_TUNER_FMT
70 {
71         int     id;
72         char *name;
73 }
74 hauppauge_tuner_fmt[] =
75 {
76         { 0x00000000, " unknown1" },
77         { 0x00000000, " unknown2" },
78         { 0x00000007, " PAL(B/G)" },
79         { 0x00001000, " NTSC(M)" },
80         { 0x00000010, " PAL(I)" },
81         { 0x00400000, " SECAM(L/L')" },
82         { 0x00000e00, " PAL(D/K)" },
83         { 0x03000000, " ATSC Digital" },
84 };
85
86 /* This is the full list of possible tuners. Many thanks to Hauppauge for
87    supplying this information. Note that many tuners where only used for
88    testing and never made it to the outside world. So you will only see
89    a subset in actual produced cards. */
90 static struct HAUPPAUGE_TUNER
91 {
92         int  id;
93         char *name;
94 }
95 hauppauge_tuner[] =
96 {
97         /* 0-9 */
98         { TUNER_ABSENT,        "None" },
99         { TUNER_ABSENT,        "External" },
100         { TUNER_ABSENT,        "Unspecified" },
101         { TUNER_PHILIPS_PAL,   "Philips FI1216" },
102         { TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
103         { TUNER_PHILIPS_NTSC,  "Philips FI1236" },
104         { TUNER_PHILIPS_PAL_I, "Philips FI1246" },
105         { TUNER_PHILIPS_PAL_DK,"Philips FI1256" },
106         { TUNER_PHILIPS_PAL,   "Philips FI1216 MK2" },
107         { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
108         /* 10-19 */
109         { TUNER_PHILIPS_NTSC,  "Philips FI1236 MK2" },
110         { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
111         { TUNER_PHILIPS_PAL_DK,"Philips FI1256 MK2" },
112         { TUNER_TEMIC_NTSC,    "Temic 4032FY5" },
113         { TUNER_TEMIC_PAL,     "Temic 4002FH5" },
114         { TUNER_TEMIC_PAL_I,   "Temic 4062FY5" },
115         { TUNER_PHILIPS_PAL,   "Philips FR1216 MK2" },
116         { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
117         { TUNER_PHILIPS_NTSC,  "Philips FR1236 MK2" },
118         { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
119         /* 20-29 */
120         { TUNER_PHILIPS_PAL_DK,"Philips FR1256 MK2" },
121         { TUNER_PHILIPS_PAL,   "Philips FM1216" },
122         { TUNER_PHILIPS_SECAM, "Philips FM1216MF" },
123         { TUNER_PHILIPS_NTSC,  "Philips FM1236" },
124         { TUNER_PHILIPS_PAL_I, "Philips FM1246" },
125         { TUNER_PHILIPS_PAL_DK,"Philips FM1256" },
126         { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
127         { TUNER_ABSENT,        "Samsung TCPN9082D" },
128         { TUNER_ABSENT,        "Samsung TCPM9092P" },
129         { TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" },
130         /* 30-39 */
131         { TUNER_ABSENT,        "Samsung TCPN9085D" },
132         { TUNER_ABSENT,        "Samsung TCPB9085P" },
133         { TUNER_ABSENT,        "Samsung TCPL9091P" },
134         { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" },
135         { TUNER_PHILIPS_FQ1216ME,   "Philips FQ1216 ME" },
136         { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" },
137         { TUNER_PHILIPS_NTSC,        "Philips TD1536" },
138         { TUNER_PHILIPS_NTSC,        "Philips TD1536D" },
139         { TUNER_PHILIPS_NTSC,  "Philips FMR1236" }, /* mono radio */
140         { TUNER_ABSENT,        "Philips FI1256MP" },
141         /* 40-49 */
142         { TUNER_ABSENT,        "Samsung TCPQ9091P" },
143         { TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
144         { TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" },
145         { TUNER_TEMIC_4046FM5,     "Temic 4046FM5" },
146         { TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
147         { TUNER_ABSENT,        "Philips TD1536D FH 44"},
148         { TUNER_LG_NTSC_FM,    "LG TP18NSR01F"},
149         { TUNER_LG_PAL_FM,     "LG TP18PSB01D"},
150         { TUNER_LG_PAL,        "LG TP18PSB11D"},
151         { TUNER_LG_PAL_I_FM,   "LG TAPC-I001D"},
152         /* 50-59 */
153         { TUNER_LG_PAL_I,      "LG TAPC-I701D"},
154         { TUNER_ABSENT,        "Temic 4042FI5"},
155         { TUNER_MICROTUNE_4049FM5, "Microtune 4049 FM5"},
156         { TUNER_ABSENT,        "LG TPI8NSR11F"},
157         { TUNER_ABSENT,        "Microtune 4049 FM5 Alt I2C"},
158         { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216ME MK3"},
159         { TUNER_ABSENT,        "Philips FI1236 MK3"},
160         { TUNER_PHILIPS_FM1216ME_MK3, "Philips FM1216 ME MK3"},
161         { TUNER_PHILIPS_FM1236_MK3, "Philips FM1236 MK3"},
162         { TUNER_ABSENT,        "Philips FM1216MP MK3"},
163         /* 60-69 */
164         { TUNER_PHILIPS_FM1216ME_MK3, "LG S001D MK3"},
165         { TUNER_ABSENT,        "LG M001D MK3"},
166         { TUNER_ABSENT,        "LG S701D MK3"},
167         { TUNER_ABSENT,        "LG M701D MK3"},
168         { TUNER_ABSENT,        "Temic 4146FM5"},
169         { TUNER_ABSENT,        "Temic 4136FY5"},
170         { TUNER_ABSENT,        "Temic 4106FH5"},
171         { TUNER_ABSENT,        "Philips FQ1216LMP MK3"},
172         { TUNER_LG_NTSC_TAPE,  "LG TAPE H001F MK3"},
173         { TUNER_LG_NTSC_TAPE,  "LG TAPE H701F MK3"},
174         /* 70-79 */
175         { TUNER_ABSENT,        "LG TALN H200T"},
176         { TUNER_ABSENT,        "LG TALN H250T"},
177         { TUNER_ABSENT,        "LG TALN M200T"},
178         { TUNER_ABSENT,        "LG TALN Z200T"},
179         { TUNER_ABSENT,        "LG TALN S200T"},
180         { TUNER_ABSENT,        "Thompson DTT7595"},
181         { TUNER_ABSENT,        "Thompson DTT7592"},
182         { TUNER_ABSENT,        "Silicon TDA8275C1 8290"},
183         { TUNER_ABSENT,        "Silicon TDA8275C1 8290 FM"},
184         { TUNER_ABSENT,        "Thompson DTT757"},
185         /* 80-89 */
186         { TUNER_ABSENT,        "Philips FQ1216LME MK3"},
187         { TUNER_ABSENT,        "LG TAPC G701D"},
188         { TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
189         { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
190         { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
191         { TUNER_TCL_2002N,     "TCL 2002N 6A"},
192         { TUNER_ABSENT,        "Philips FQ1236 MK3"},
193         { TUNER_ABSENT,        "Samsung TCPN 2121P30A"},
194         { TUNER_ABSENT,        "Samsung TCPE 4121P30A"},
195         { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"},
196         /* 90-99 */
197         { TUNER_ABSENT,        "LG TALN H202T"},
198         { TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"},
199         { TUNER_PHILIPS_FQ1236A_MK4, "Philips FQ1236A MK4"},
200         { TUNER_ABSENT,        "Philips FQ1286A MK4"},
201         { TUNER_ABSENT,        "Philips FQ1216ME MK5"},
202         { TUNER_ABSENT,        "Philips FQ1236 MK5"},
203         { TUNER_ABSENT,        "Unspecified"},
204         { TUNER_LG_PAL_TAPE,   "LG PAL (TAPE Series)"},
205         { TUNER_ABSENT,        "Unspecified"},
206         { TUNER_TCL_2002N,     "TCL 2002N 5H"},
207         /* 100-103 */
208         { TUNER_ABSENT,        "Unspecified"},
209         { TUNER_TEA5767,       "Philips TEA5767HN FM Radio"},
210         { TUNER_ABSENT,        "Unspecified"},
211         { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05 4"},
212 };
213
214 /* This list is supplied by Hauppauge. Thanks! */
215 static const char *audioIC[] = {
216         /* 0-4 */
217         "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C",
218         /* 5-9 */
219         "MSP3410D", "MSP3415", "MSP3430", "MSP3438", "CS5331",
220         /* 10-14 */
221         "MSP3435", "MSP3440", "MSP3445", "MSP3411", "MSP3416",
222         /* 15-19 */
223         "MSP3425", "MSP3451", "MSP3418", "Type 0x12", "OKI7716",
224         /* 20-24 */
225         "MSP4410", "MSP4420", "MSP4440", "MSP4450", "MSP4408",
226         /* 25-29 */
227         "MSP4418", "MSP4428", "MSP4448", "MSP4458", "Type 0x1d",
228         /* 30-34 */
229         "CX880", "CX881", "CX883", "CX882", "CX25840",
230         /* 35-38 */
231         "CX25841", "CX25842", "CX25843", "CX23418",
232 };
233
234 /* This list is supplied by Hauppauge. Thanks! */
235 static const char *decoderIC[] = {
236         /* 0-4 */
237         "None", "BT815", "BT817", "BT819", "BT815A",
238         /* 5-9 */
239         "BT817A", "BT819A", "BT827", "BT829", "BT848",
240         /* 10-14 */
241         "BT848A", "BT849A", "BT829A", "BT827A", "BT878",
242         /* 15-19 */
243         "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115",
244         /* 20-24 */
245         "CX880", "CX881", "CX883", "SAA7111", "SAA7113",
246         /* 25-29 */
247         "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842",
248         /* 30-31 */
249         "CX25843", "CX23418",
250 };
251
252 static int hasRadioTuner(int tunerType)
253 {
254         switch (tunerType) {
255                 case 18: //PNPEnv_TUNER_FR1236_MK2:
256                 case 23: //PNPEnv_TUNER_FM1236:
257                 case 38: //PNPEnv_TUNER_FMR1236:
258                 case 16: //PNPEnv_TUNER_FR1216_MK2:
259                 case 19: //PNPEnv_TUNER_FR1246_MK2:
260                 case 21: //PNPEnv_TUNER_FM1216:
261                 case 24: //PNPEnv_TUNER_FM1246:
262                 case 17: //PNPEnv_TUNER_FR1216MF_MK2:
263                 case 22: //PNPEnv_TUNER_FM1216MF:
264                 case 20: //PNPEnv_TUNER_FR1256_MK2:
265                 case 25: //PNPEnv_TUNER_FM1256:
266                 case 33: //PNPEnv_TUNER_4039FR5:
267                 case 42: //PNPEnv_TUNER_4009FR5:
268                 case 52: //PNPEnv_TUNER_4049FM5:
269                 case 54: //PNPEnv_TUNER_4049FM5_AltI2C:
270                 case 44: //PNPEnv_TUNER_4009FN5:
271                 case 31: //PNPEnv_TUNER_TCPB9085P:
272                 case 30: //PNPEnv_TUNER_TCPN9085D:
273                 case 46: //PNPEnv_TUNER_TP18NSR01F:
274                 case 47: //PNPEnv_TUNER_TP18PSB01D:
275                 case 49: //PNPEnv_TUNER_TAPC_I001D:
276                 case 60: //PNPEnv_TUNER_TAPE_S001D_MK3:
277                 case 57: //PNPEnv_TUNER_FM1216ME_MK3:
278                 case 59: //PNPEnv_TUNER_FM1216MP_MK3:
279                 case 58: //PNPEnv_TUNER_FM1236_MK3:
280                 case 68: //PNPEnv_TUNER_TAPE_H001F_MK3:
281                 case 61: //PNPEnv_TUNER_TAPE_M001D_MK3:
282                 case 78: //PNPEnv_TUNER_TDA8275C1_8290_FM:
283                 case 89: //PNPEnv_TUNER_TCL_MFPE05_2:
284                 case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4:
285                     return 1;
286         }
287         return 0;
288 }
289
290 void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
291                                 unsigned char *eeprom_data)
292 {
293         /* ----------------------------------------------
294         ** The hauppauge eeprom format is tagged
295         **
296         ** if packet[0] == 0x84, then packet[0..1] == length
297         ** else length = packet[0] & 3f;
298         ** if packet[0] & f8 == f8, then EOD and packet[1] == checksum
299         **
300         ** In our (ivtv) case we're interested in the following:
301         ** tuner type:   tag [00].05 or [0a].01 (index into hauppauge_tuner)
302         ** tuner fmts:   tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt)
303         ** radio:        tag [00].{last} or [0e].00  (bitmask.  bit2=FM)
304         ** audio proc:   tag [02].01 or [05].00 (mask with 0x7f)
305         ** decoder proc: tag [09].01)
306
307         ** Fun info:
308         ** model:      tag [00].07-08 or [06].00-01
309         ** revision:   tag [00].09-0b or [06].04-06
310         ** serial#:    tag [01].05-07 or [04].04-06
311
312         ** # of inputs/outputs ???
313         */
314
315         int i, j, len, done, beenhere, tag;
316
317         int tuner1 = 0, t_format1 = 0;
318         char *t_name1 = NULL;
319         const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" };
320
321         int tuner2 = 0, t_format2 = 0;
322         char *t_name2 = NULL;
323         const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
324
325         memset(tvee, 0, sizeof(*tvee));
326         done = len = beenhere = 0;
327         for (i = 0; !done && i < 256; i += len) {
328                 if (eeprom_data[i] == 0x84) {
329                         len = eeprom_data[i + 1] + (eeprom_data[i + 2] << 8);
330                         i += 3;
331                 } else if ((eeprom_data[i] & 0xf0) == 0x70) {
332                         if (eeprom_data[i] & 0x08) {
333                                 /* verify checksum! */
334                                 done = 1;
335                                 break;
336                         }
337                         len = eeprom_data[i] & 0x07;
338                         ++i;
339                 } else {
340                         tveeprom_warn("Encountered bad packet header [%02x]. "
341                                    "Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]);
342                         return;
343                 }
344
345                 if (debug) {
346                         tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1);
347                         for(j = 1; j < len; j++) {
348                                 printk(" %02x", eeprom_data[i + j]);
349                         }
350                         printk("\n");
351                 }
352
353                 /* process by tag */
354                 tag = eeprom_data[i];
355                 switch (tag) {
356                 case 0x00:
357                         /* tag: 'Comprehensive' */
358                         tuner1 = eeprom_data[i+6];
359                         t_format1 = eeprom_data[i+5];
360                         tvee->has_radio = eeprom_data[i+len-1];
361                         /* old style tag, don't know how to detect
362                            IR presence, mark as unknown. */
363                         tvee->has_ir = 2;
364                         tvee->model =
365                                 eeprom_data[i+8] +
366                                 (eeprom_data[i+9] << 8);
367                         tvee->revision = eeprom_data[i+10] +
368                                 (eeprom_data[i+11] << 8) +
369                                 (eeprom_data[i+12] << 16);
370                         break;
371
372                 case 0x01:
373                         /* tag: 'SerialID' */
374                         tvee->serial_number =
375                                 eeprom_data[i+6] +
376                                 (eeprom_data[i+7] << 8) +
377                                 (eeprom_data[i+8] << 16);
378                         break;
379
380                 case 0x02:
381                         /* tag 'AudioInfo'
382                            Note mask with 0x7F, high bit used on some older models
383                            to indicate 4052 mux was removed in favor of using MSP
384                            inputs directly. */
385                         tvee->audio_processor = eeprom_data[i+2] & 0x7f;
386                         break;
387
388                 /* case 0x03: tag 'EEInfo' */
389
390                 case 0x04:
391                         /* tag 'SerialID2' */
392                         tvee->serial_number =
393                                 eeprom_data[i+5] +
394                                 (eeprom_data[i+6] << 8) +
395                                 (eeprom_data[i+7] << 16);
396                         break;
397
398                 case 0x05:
399                         /* tag 'Audio2'
400                            Note mask with 0x7F, high bit used on some older models
401                            to indicate 4052 mux was removed in favor of using MSP
402                            inputs directly. */
403                         tvee->audio_processor = eeprom_data[i+1] & 0x7f;
404                         break;
405
406                 case 0x06:
407                         /* tag 'ModelRev' */
408                         tvee->model =
409                                 eeprom_data[i+1] +
410                                 (eeprom_data[i+2] << 8);
411                         tvee->revision = eeprom_data[i+5] +
412                                 (eeprom_data[i+6] << 8) +
413                                 (eeprom_data[i+7] << 16);
414                         break;
415
416                 case 0x07:
417                         /* tag 'Details': according to Hauppauge not interesting
418                            on any PCI-era or later boards. */
419                         break;
420
421                 /* there is no tag 0x08 defined */
422
423                 case 0x09:
424                         /* tag 'Video' */
425                         tvee->decoder_processor = eeprom_data[i + 1];
426                         break;
427
428                 case 0x0a:
429                         /* tag 'Tuner' */
430                         if (beenhere == 0) {
431                                 tuner1 = eeprom_data[i+2];
432                                 t_format1 = eeprom_data[i+1];
433                                 beenhere = 1;
434                         } else {
435                                 /* a second (radio) tuner may be present */
436                                 tuner2 = eeprom_data[i+2];
437                                 t_format2 = eeprom_data[i+1];
438                                 if (t_format2 == 0) {  /* not a TV tuner? */
439                                         tvee->has_radio = 1; /* must be radio */
440                                 }
441                         }
442                         break;
443
444                 case 0x0b:
445                         /* tag 'Inputs': according to Hauppauge this is specific
446                            to each driver family, so no good assumptions can be
447                            made. */
448                         break;
449
450                 /* case 0x0c: tag 'Balun' */
451                 /* case 0x0d: tag 'Teletext' */
452
453                 case 0x0e:
454                         /* tag: 'Radio' */
455                         tvee->has_radio = eeprom_data[i+1];
456                         break;
457
458                 case 0x0f:
459                         /* tag 'IRInfo' */
460                         tvee->has_ir = eeprom_data[i+1];
461                         break;
462
463                 /* case 0x10: tag 'VBIInfo' */
464                 /* case 0x11: tag 'QCInfo' */
465                 /* case 0x12: tag 'InfoBits' */
466
467                 default:
468                         tveeprom_dbg("Not sure what to do with tag [%02x]\n", tag);
469                         /* dump the rest of the packet? */
470                 }
471         }
472
473         if (!done) {
474                 tveeprom_warn("Ran out of data!\n");
475                 return;
476         }
477
478         if (tvee->revision != 0) {
479                 tvee->rev_str[0] = 32 + ((tvee->revision >> 18) & 0x3f);
480                 tvee->rev_str[1] = 32 + ((tvee->revision >> 12) & 0x3f);
481                 tvee->rev_str[2] = 32 + ((tvee->revision >>  6) & 0x3f);
482                 tvee->rev_str[3] = 32 + ( tvee->revision        & 0x3f);
483                 tvee->rev_str[4] = 0;
484         }
485
486         if (hasRadioTuner(tuner1) && !tvee->has_radio) {
487             tveeprom_info("The eeprom says no radio is present, but the tuner type\n");
488             tveeprom_info("indicates otherwise. I will assume that radio is present.\n");
489             tvee->has_radio = 1;
490         }
491
492         if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
493                 tvee->tuner_type = hauppauge_tuner[tuner1].id;
494                 t_name1 = hauppauge_tuner[tuner1].name;
495         } else {
496                 t_name1 = "unknown";
497         }
498
499         if (tuner2 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
500                 tvee->tuner2_type = hauppauge_tuner[tuner2].id;
501                 t_name2 = hauppauge_tuner[tuner2].name;
502         } else {
503                 t_name2 = "unknown";
504         }
505
506         tvee->tuner_formats = 0;
507         tvee->tuner2_formats = 0;
508         for (i = j = 0; i < 8; i++) {
509                 if (t_format1 & (1 << i)) {
510                         tvee->tuner_formats |= hauppauge_tuner_fmt[i].id;
511                         t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name;
512                 }
513                 if (t_format2 & (1 << i)) {
514                         tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id;
515                         t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name;
516                 }
517         }
518
519         tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",
520                    tvee->model, tvee->rev_str, tvee->serial_number);
521         tveeprom_info("tuner model is %s (idx %d, type %d)\n",
522                    t_name1, tuner1, tvee->tuner_type);
523         tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
524                    t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3],
525                    t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7],
526                    t_format1);
527         if (tuner2) {
528                 tveeprom_info("second tuner model is %s (idx %d, type %d)\n",
529                            t_name2, tuner2, tvee->tuner2_type);
530         }
531         if (t_format2) {
532                 tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
533                            t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3],
534                            t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7],
535                            t_format2);
536         }
537         tveeprom_info("audio processor is %s (idx %d)\n",
538                    STRM(audioIC, tvee->audio_processor),
539                    tvee->audio_processor);
540         if (tvee->decoder_processor) {
541                 tveeprom_info("decoder processor is %s (idx %d)\n",
542                            STRM(decoderIC, tvee->decoder_processor),
543                            tvee->decoder_processor);
544         }
545         if (tvee->has_ir == 2)
546                 tveeprom_info("has %sradio\n",
547                                 tvee->has_radio ? "" : "no ");
548         else
549                 tveeprom_info("has %sradio, has %sIR remote\n",
550                                 tvee->has_radio ? "" : "no ",
551                                 tvee->has_ir ? "" : "no ");
552 }
553 EXPORT_SYMBOL(tveeprom_hauppauge_analog);
554
555 /* ----------------------------------------------------------------------- */
556 /* generic helper functions                                                */
557
558 int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
559 {
560         unsigned char buf;
561         int err;
562
563         buf = 0;
564         if (1 != (err = i2c_master_send(c, &buf, 1))) {
565                 tveeprom_info("Huh, no eeprom present (err=%d)?\n", err);
566                 return -1;
567         }
568         if (len != (err = i2c_master_recv(c, eedata, len))) {
569                 tveeprom_warn("i2c eeprom read error (err=%d)\n", err);
570                 return -1;
571         }
572         if (debug) {
573                 int i;
574
575                 tveeprom_info("full 256-byte eeprom dump:\n");
576                 for (i = 0; i < len; i++) {
577                         if (0 == (i % 16))
578                                 tveeprom_info("%02x:", i);
579                         printk(" %02x", eedata[i]);
580                         if (15 == (i % 16))
581                                 printk("\n");
582                 }
583         }
584         return 0;
585 }
586 EXPORT_SYMBOL(tveeprom_read);
587
588 /* ----------------------------------------------------------------------- */
589 /* needed for ivtv.sf.net at the moment.  Should go away in the long       */
590 /* run, just call the exported tveeprom_* directly, there is no point in   */
591 /* using the indirect way via i2c_driver->command()                        */
592
593 #ifndef I2C_DRIVERID_TVEEPROM
594 # define I2C_DRIVERID_TVEEPROM I2C_DRIVERID_EXP2
595 #endif
596
597 static unsigned short normal_i2c[] = {
598         0xa0 >> 1,
599         I2C_CLIENT_END,
600 };
601
602 I2C_CLIENT_INSMOD;
603
604 static struct i2c_driver i2c_driver_tveeprom;
605
606 static int
607 tveeprom_command(struct i2c_client *client,
608                  unsigned int       cmd,
609                  void              *arg)
610 {
611         struct tveeprom eeprom;
612         u32 *eeprom_props = arg;
613         u8 *buf;
614
615         switch (cmd) {
616         case 0:
617                 buf = kmalloc(256,GFP_KERNEL);
618                 memset(buf,0,256);
619                 tveeprom_read(client,buf,256);
620                 tveeprom_hauppauge_analog(client, &eeprom,buf);
621                 kfree(buf);
622                 eeprom_props[0] = eeprom.tuner_type;
623                 eeprom_props[1] = eeprom.tuner_formats;
624                 eeprom_props[2] = eeprom.model;
625                 eeprom_props[3] = eeprom.revision;
626                 eeprom_props[4] = eeprom.has_radio;
627                 break;
628         default:
629                 return -EINVAL;
630         }
631         return 0;
632 }
633
634 static int
635 tveeprom_detect_client(struct i2c_adapter *adapter,
636                        int                 address,
637                        int                 kind)
638 {
639         struct i2c_client *client;
640
641         client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
642         if (NULL == client)
643                 return -ENOMEM;
644         memset(client, 0, sizeof(struct i2c_client));
645         client->addr = address;
646         client->adapter = adapter;
647         client->driver = &i2c_driver_tveeprom;
648         client->flags = I2C_CLIENT_ALLOW_USE;
649         snprintf(client->name, sizeof(client->name), "tveeprom");
650         i2c_attach_client(client);
651         return 0;
652 }
653
654 static int
655 tveeprom_attach_adapter (struct i2c_adapter *adapter)
656 {
657         if (adapter->id != I2C_HW_B_BT848)
658                 return 0;
659         return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
660 }
661
662 static int
663 tveeprom_detach_client (struct i2c_client *client)
664 {
665         int err;
666
667         err = i2c_detach_client(client);
668         if (err < 0)
669                 return err;
670         kfree(client);
671         return 0;
672 }
673
674 static struct i2c_driver i2c_driver_tveeprom = {
675         .owner          = THIS_MODULE,
676         .name           = "tveeprom",
677         .id             = I2C_DRIVERID_TVEEPROM,
678         .flags          = I2C_DF_NOTIFY,
679         .attach_adapter = tveeprom_attach_adapter,
680         .detach_client  = tveeprom_detach_client,
681         .command        = tveeprom_command,
682 };
683
684 static int __init tveeprom_init(void)
685 {
686         return i2c_add_driver(&i2c_driver_tveeprom);
687 }
688
689 static void __exit tveeprom_exit(void)
690 {
691         i2c_del_driver(&i2c_driver_tveeprom);
692 }
693
694 module_init(tveeprom_init);
695 module_exit(tveeprom_exit);
696
697 /*
698  * Local variables:
699  * c-basic-offset: 8
700  * End:
701  */