Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
saa7164-cards.c
Go to the documentation of this file.
1 /*
2  * Driver for the NXP SAA7164 PCIe bridge
3  *
4  * Copyright (c) 2010 Steven Toth <[email protected]>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  *
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/pci.h>
25 #include <linux/delay.h>
26 
27 #include "saa7164.h"
28 
29 /* The Bridge API needs to understand register widths (in bytes) for the
30  * attached I2C devices, so we can simplify the virtual i2c mechansms
31  * and keep the -i2c.c implementation clean.
32  */
33 #define REGLEN_8bit 1
34 #define REGLEN_16bit 2
35 
38  /* Bridge will not load any firmware, without knowing
39  * the rev this would be fatal. */
40  .name = "Unknown",
41  },
43  /* Bridge will load the v2 f/w and dump descriptors */
44  /* Required during new board bringup */
45  .name = "Generic Rev2",
46  .chiprev = SAA7164_CHIP_REV2,
47  },
49  /* Bridge will load the v2 f/w and dump descriptors */
50  /* Required during new board bringup */
51  .name = "Generic Rev3",
52  .chiprev = SAA7164_CHIP_REV3,
53  },
55  .name = "Hauppauge WinTV-HVR2200",
56  .porta = SAA7164_MPEG_DVB,
57  .portb = SAA7164_MPEG_DVB,
58  .portc = SAA7164_MPEG_ENCODER,
59  .portd = SAA7164_MPEG_ENCODER,
60  .porte = SAA7164_MPEG_VBI,
61  .portf = SAA7164_MPEG_VBI,
62  .chiprev = SAA7164_CHIP_REV3,
63  .unit = {{
64  .id = 0x1d,
65  .type = SAA7164_UNIT_EEPROM,
66  .name = "4K EEPROM",
67  .i2c_bus_nr = SAA7164_I2C_BUS_0,
68  .i2c_bus_addr = 0xa0 >> 1,
69  .i2c_reg_len = REGLEN_8bit,
70  }, {
71  .id = 0x04,
72  .type = SAA7164_UNIT_TUNER,
73  .name = "TDA18271-1",
74  .i2c_bus_nr = SAA7164_I2C_BUS_1,
75  .i2c_bus_addr = 0xc0 >> 1,
76  .i2c_reg_len = REGLEN_8bit,
77  }, {
78  .id = 0x1b,
79  .type = SAA7164_UNIT_TUNER,
80  .name = "TDA18271-2",
81  .i2c_bus_nr = SAA7164_I2C_BUS_2,
82  .i2c_bus_addr = 0xc0 >> 1,
83  .i2c_reg_len = REGLEN_8bit,
84  }, {
85  .id = 0x1e,
87  .name = "TDA10048-1",
88  .i2c_bus_nr = SAA7164_I2C_BUS_1,
89  .i2c_bus_addr = 0x10 >> 1,
90  .i2c_reg_len = REGLEN_8bit,
91  }, {
92  .id = 0x1f,
94  .name = "TDA10048-2",
95  .i2c_bus_nr = SAA7164_I2C_BUS_2,
96  .i2c_bus_addr = 0x12 >> 1,
97  .i2c_reg_len = REGLEN_8bit,
98  } },
99  },
101  .name = "Hauppauge WinTV-HVR2200",
102  .porta = SAA7164_MPEG_DVB,
103  .portb = SAA7164_MPEG_DVB,
104  .portc = SAA7164_MPEG_ENCODER,
105  .portd = SAA7164_MPEG_ENCODER,
106  .porte = SAA7164_MPEG_VBI,
107  .portf = SAA7164_MPEG_VBI,
108  .chiprev = SAA7164_CHIP_REV2,
109  .unit = {{
110  .id = 0x06,
111  .type = SAA7164_UNIT_EEPROM,
112  .name = "4K EEPROM",
113  .i2c_bus_nr = SAA7164_I2C_BUS_0,
114  .i2c_bus_addr = 0xa0 >> 1,
115  .i2c_reg_len = REGLEN_8bit,
116  }, {
117  .id = 0x04,
118  .type = SAA7164_UNIT_TUNER,
119  .name = "TDA18271-1",
120  .i2c_bus_nr = SAA7164_I2C_BUS_1,
121  .i2c_bus_addr = 0xc0 >> 1,
122  .i2c_reg_len = REGLEN_8bit,
123  }, {
124  .id = 0x05,
126  .name = "TDA10048-1",
127  .i2c_bus_nr = SAA7164_I2C_BUS_1,
128  .i2c_bus_addr = 0x10 >> 1,
129  .i2c_reg_len = REGLEN_8bit,
130  }, {
131  .id = 0x1e,
132  .type = SAA7164_UNIT_TUNER,
133  .name = "TDA18271-2",
134  .i2c_bus_nr = SAA7164_I2C_BUS_2,
135  .i2c_bus_addr = 0xc0 >> 1,
136  .i2c_reg_len = REGLEN_8bit,
137  }, {
138  .id = 0x1f,
140  .name = "TDA10048-2",
141  .i2c_bus_nr = SAA7164_I2C_BUS_2,
142  .i2c_bus_addr = 0x12 >> 1,
143  .i2c_reg_len = REGLEN_8bit,
144  } },
145  },
147  .name = "Hauppauge WinTV-HVR2200",
148  .porta = SAA7164_MPEG_DVB,
149  .portb = SAA7164_MPEG_DVB,
150  .portc = SAA7164_MPEG_ENCODER,
151  .portd = SAA7164_MPEG_ENCODER,
152  .porte = SAA7164_MPEG_VBI,
153  .portf = SAA7164_MPEG_VBI,
154  .chiprev = SAA7164_CHIP_REV2,
155  .unit = {{
156  .id = 0x1d,
157  .type = SAA7164_UNIT_EEPROM,
158  .name = "4K EEPROM",
159  .i2c_bus_nr = SAA7164_I2C_BUS_0,
160  .i2c_bus_addr = 0xa0 >> 1,
161  .i2c_reg_len = REGLEN_8bit,
162  }, {
163  .id = 0x04,
164  .type = SAA7164_UNIT_TUNER,
165  .name = "TDA18271-1",
166  .i2c_bus_nr = SAA7164_I2C_BUS_1,
167  .i2c_bus_addr = 0xc0 >> 1,
168  .i2c_reg_len = REGLEN_8bit,
169  }, {
170  .id = 0x05,
172  .name = "TDA8290-1",
173  .i2c_bus_nr = SAA7164_I2C_BUS_1,
174  .i2c_bus_addr = 0x84 >> 1,
175  .i2c_reg_len = REGLEN_8bit,
176  }, {
177  .id = 0x1b,
178  .type = SAA7164_UNIT_TUNER,
179  .name = "TDA18271-2",
180  .i2c_bus_nr = SAA7164_I2C_BUS_2,
181  .i2c_bus_addr = 0xc0 >> 1,
182  .i2c_reg_len = REGLEN_8bit,
183  }, {
184  .id = 0x1c,
186  .name = "TDA8290-2",
187  .i2c_bus_nr = SAA7164_I2C_BUS_2,
188  .i2c_bus_addr = 0x84 >> 1,
189  .i2c_reg_len = REGLEN_8bit,
190  }, {
191  .id = 0x1e,
193  .name = "TDA10048-1",
194  .i2c_bus_nr = SAA7164_I2C_BUS_1,
195  .i2c_bus_addr = 0x10 >> 1,
196  .i2c_reg_len = REGLEN_8bit,
197  }, {
198  .id = 0x1f,
200  .name = "TDA10048-2",
201  .i2c_bus_nr = SAA7164_I2C_BUS_2,
202  .i2c_bus_addr = 0x12 >> 1,
203  .i2c_reg_len = REGLEN_8bit,
204  } },
205  },
207  .name = "Hauppauge WinTV-HVR2200",
208  .porta = SAA7164_MPEG_DVB,
209  .portb = SAA7164_MPEG_DVB,
210  .portc = SAA7164_MPEG_ENCODER,
211  .portd = SAA7164_MPEG_ENCODER,
212  .porte = SAA7164_MPEG_VBI,
213  .portf = SAA7164_MPEG_VBI,
214  .chiprev = SAA7164_CHIP_REV3,
215  .unit = {{
216  .id = 0x1d,
217  .type = SAA7164_UNIT_EEPROM,
218  .name = "4K EEPROM",
219  .i2c_bus_nr = SAA7164_I2C_BUS_0,
220  .i2c_bus_addr = 0xa0 >> 1,
221  .i2c_reg_len = REGLEN_8bit,
222  }, {
223  .id = 0x04,
224  .type = SAA7164_UNIT_TUNER,
225  .name = "TDA18271-1",
226  .i2c_bus_nr = SAA7164_I2C_BUS_1,
227  .i2c_bus_addr = 0xc0 >> 1,
228  .i2c_reg_len = REGLEN_8bit,
229  }, {
230  .id = 0x05,
232  .name = "TDA8290-1",
233  .i2c_bus_nr = SAA7164_I2C_BUS_1,
234  .i2c_bus_addr = 0x84 >> 1,
235  .i2c_reg_len = REGLEN_8bit,
236  }, {
237  .id = 0x1b,
238  .type = SAA7164_UNIT_TUNER,
239  .name = "TDA18271-2",
240  .i2c_bus_nr = SAA7164_I2C_BUS_2,
241  .i2c_bus_addr = 0xc0 >> 1,
242  .i2c_reg_len = REGLEN_8bit,
243  }, {
244  .id = 0x1c,
246  .name = "TDA8290-2",
247  .i2c_bus_nr = SAA7164_I2C_BUS_2,
248  .i2c_bus_addr = 0x84 >> 1,
249  .i2c_reg_len = REGLEN_8bit,
250  }, {
251  .id = 0x1e,
253  .name = "TDA10048-1",
254  .i2c_bus_nr = SAA7164_I2C_BUS_1,
255  .i2c_bus_addr = 0x10 >> 1,
256  .i2c_reg_len = REGLEN_8bit,
257  }, {
258  .id = 0x1f,
260  .name = "TDA10048-2",
261  .i2c_bus_nr = SAA7164_I2C_BUS_2,
262  .i2c_bus_addr = 0x12 >> 1,
263  .i2c_reg_len = REGLEN_8bit,
264  } },
265  },
267  .name = "Hauppauge WinTV-HVR2250",
268  .porta = SAA7164_MPEG_DVB,
269  .portb = SAA7164_MPEG_DVB,
270  .portc = SAA7164_MPEG_ENCODER,
271  .portd = SAA7164_MPEG_ENCODER,
272  .porte = SAA7164_MPEG_VBI,
273  .portf = SAA7164_MPEG_VBI,
274  .chiprev = SAA7164_CHIP_REV3,
275  .unit = {{
276  .id = 0x22,
277  .type = SAA7164_UNIT_EEPROM,
278  .name = "4K EEPROM",
279  .i2c_bus_nr = SAA7164_I2C_BUS_0,
280  .i2c_bus_addr = 0xa0 >> 1,
281  .i2c_reg_len = REGLEN_8bit,
282  }, {
283  .id = 0x04,
284  .type = SAA7164_UNIT_TUNER,
285  .name = "TDA18271-1",
286  .i2c_bus_nr = SAA7164_I2C_BUS_1,
287  .i2c_bus_addr = 0xc0 >> 1,
288  .i2c_reg_len = REGLEN_8bit,
289  }, {
290  .id = 0x07,
292  .name = "CX24228/S5H1411-1 (TOP)",
293  .i2c_bus_nr = SAA7164_I2C_BUS_1,
294  .i2c_bus_addr = 0x32 >> 1,
295  .i2c_reg_len = REGLEN_8bit,
296  }, {
297  .id = 0x08,
299  .name = "CX24228/S5H1411-1 (QAM)",
300  .i2c_bus_nr = SAA7164_I2C_BUS_1,
301  .i2c_bus_addr = 0x34 >> 1,
302  .i2c_reg_len = REGLEN_8bit,
303  }, {
304  .id = 0x1e,
305  .type = SAA7164_UNIT_TUNER,
306  .name = "TDA18271-2",
307  .i2c_bus_nr = SAA7164_I2C_BUS_2,
308  .i2c_bus_addr = 0xc0 >> 1,
309  .i2c_reg_len = REGLEN_8bit,
310  }, {
311  .id = 0x20,
313  .name = "CX24228/S5H1411-2 (TOP)",
314  .i2c_bus_nr = SAA7164_I2C_BUS_2,
315  .i2c_bus_addr = 0x32 >> 1,
316  .i2c_reg_len = REGLEN_8bit,
317  }, {
318  .id = 0x23,
320  .name = "CX24228/S5H1411-2 (QAM)",
321  .i2c_bus_nr = SAA7164_I2C_BUS_2,
322  .i2c_bus_addr = 0x34 >> 1,
323  .i2c_reg_len = REGLEN_8bit,
324  } },
325  },
327  .name = "Hauppauge WinTV-HVR2250",
328  .porta = SAA7164_MPEG_DVB,
329  .portb = SAA7164_MPEG_DVB,
330  .portc = SAA7164_MPEG_ENCODER,
331  .portd = SAA7164_MPEG_ENCODER,
332  .porte = SAA7164_MPEG_VBI,
333  .portf = SAA7164_MPEG_VBI,
334  .chiprev = SAA7164_CHIP_REV3,
335  .unit = {{
336  .id = 0x28,
337  .type = SAA7164_UNIT_EEPROM,
338  .name = "4K EEPROM",
339  .i2c_bus_nr = SAA7164_I2C_BUS_0,
340  .i2c_bus_addr = 0xa0 >> 1,
341  .i2c_reg_len = REGLEN_8bit,
342  }, {
343  .id = 0x04,
344  .type = SAA7164_UNIT_TUNER,
345  .name = "TDA18271-1",
346  .i2c_bus_nr = SAA7164_I2C_BUS_1,
347  .i2c_bus_addr = 0xc0 >> 1,
348  .i2c_reg_len = REGLEN_8bit,
349  }, {
350  .id = 0x07,
352  .name = "CX24228/S5H1411-1 (TOP)",
353  .i2c_bus_nr = SAA7164_I2C_BUS_1,
354  .i2c_bus_addr = 0x32 >> 1,
355  .i2c_reg_len = REGLEN_8bit,
356  }, {
357  .id = 0x08,
359  .name = "CX24228/S5H1411-1 (QAM)",
360  .i2c_bus_nr = SAA7164_I2C_BUS_1,
361  .i2c_bus_addr = 0x34 >> 1,
362  .i2c_reg_len = REGLEN_8bit,
363  }, {
364  .id = 0x24,
365  .type = SAA7164_UNIT_TUNER,
366  .name = "TDA18271-2",
367  .i2c_bus_nr = SAA7164_I2C_BUS_2,
368  .i2c_bus_addr = 0xc0 >> 1,
369  .i2c_reg_len = REGLEN_8bit,
370  }, {
371  .id = 0x26,
373  .name = "CX24228/S5H1411-2 (TOP)",
374  .i2c_bus_nr = SAA7164_I2C_BUS_2,
375  .i2c_bus_addr = 0x32 >> 1,
376  .i2c_reg_len = REGLEN_8bit,
377  }, {
378  .id = 0x29,
380  .name = "CX24228/S5H1411-2 (QAM)",
381  .i2c_bus_nr = SAA7164_I2C_BUS_2,
382  .i2c_bus_addr = 0x34 >> 1,
383  .i2c_reg_len = REGLEN_8bit,
384  } },
385  },
387  .name = "Hauppauge WinTV-HVR2250",
388  .porta = SAA7164_MPEG_DVB,
389  .portb = SAA7164_MPEG_DVB,
390  .portc = SAA7164_MPEG_ENCODER,
391  .portd = SAA7164_MPEG_ENCODER,
392  .porte = SAA7164_MPEG_VBI,
393  .portf = SAA7164_MPEG_VBI,
394  .chiprev = SAA7164_CHIP_REV3,
395  .unit = {{
396  .id = 0x26,
397  .type = SAA7164_UNIT_EEPROM,
398  .name = "4K EEPROM",
399  .i2c_bus_nr = SAA7164_I2C_BUS_0,
400  .i2c_bus_addr = 0xa0 >> 1,
401  .i2c_reg_len = REGLEN_8bit,
402  }, {
403  .id = 0x04,
404  .type = SAA7164_UNIT_TUNER,
405  .name = "TDA18271-1",
406  .i2c_bus_nr = SAA7164_I2C_BUS_1,
407  .i2c_bus_addr = 0xc0 >> 1,
408  .i2c_reg_len = REGLEN_8bit,
409  }, {
410  .id = 0x07,
412  .name = "CX24228/S5H1411-1 (TOP)",
413  .i2c_bus_nr = SAA7164_I2C_BUS_1,
414  .i2c_bus_addr = 0x32 >> 1,
415  .i2c_reg_len = REGLEN_8bit,
416  }, {
417  .id = 0x08,
419  .name = "CX24228/S5H1411-1 (QAM)",
420  .i2c_bus_nr = SAA7164_I2C_BUS_1,
421  .i2c_bus_addr = 0x34 >> 1,
422  .i2c_reg_len = REGLEN_8bit,
423  }, {
424  .id = 0x22,
425  .type = SAA7164_UNIT_TUNER,
426  .name = "TDA18271-2",
427  .i2c_bus_nr = SAA7164_I2C_BUS_2,
428  .i2c_bus_addr = 0xc0 >> 1,
429  .i2c_reg_len = REGLEN_8bit,
430  }, {
431  .id = 0x24,
433  .name = "CX24228/S5H1411-2 (TOP)",
434  .i2c_bus_nr = SAA7164_I2C_BUS_2,
435  .i2c_bus_addr = 0x32 >> 1,
436  .i2c_reg_len = REGLEN_8bit,
437  }, {
438  .id = 0x27,
440  .name = "CX24228/S5H1411-2 (QAM)",
441  .i2c_bus_nr = SAA7164_I2C_BUS_2,
442  .i2c_bus_addr = 0x34 >> 1,
443  .i2c_reg_len = REGLEN_8bit,
444  } },
445  },
447  .name = "Hauppauge WinTV-HVR2200",
448  .porta = SAA7164_MPEG_DVB,
449  .portb = SAA7164_MPEG_DVB,
450  .chiprev = SAA7164_CHIP_REV3,
451  .unit = {{
452  .id = 0x23,
453  .type = SAA7164_UNIT_EEPROM,
454  .name = "4K EEPROM",
455  .i2c_bus_nr = SAA7164_I2C_BUS_0,
456  .i2c_bus_addr = 0xa0 >> 1,
457  .i2c_reg_len = REGLEN_8bit,
458  }, {
459  .id = 0x04,
460  .type = SAA7164_UNIT_TUNER,
461  .name = "TDA18271-1",
462  .i2c_bus_nr = SAA7164_I2C_BUS_1,
463  .i2c_bus_addr = 0xc0 >> 1,
464  .i2c_reg_len = REGLEN_8bit,
465  }, {
466  .id = 0x05,
468  .name = "TDA8290-1",
469  .i2c_bus_nr = SAA7164_I2C_BUS_1,
470  .i2c_bus_addr = 0x84 >> 1,
471  .i2c_reg_len = REGLEN_8bit,
472  }, {
473  .id = 0x21,
474  .type = SAA7164_UNIT_TUNER,
475  .name = "TDA18271-2",
476  .i2c_bus_nr = SAA7164_I2C_BUS_2,
477  .i2c_bus_addr = 0xc0 >> 1,
478  .i2c_reg_len = REGLEN_8bit,
479  }, {
480  .id = 0x22,
482  .name = "TDA8290-2",
483  .i2c_bus_nr = SAA7164_I2C_BUS_2,
484  .i2c_bus_addr = 0x84 >> 1,
485  .i2c_reg_len = REGLEN_8bit,
486  }, {
487  .id = 0x24,
489  .name = "TDA10048-1",
490  .i2c_bus_nr = SAA7164_I2C_BUS_1,
491  .i2c_bus_addr = 0x10 >> 1,
492  .i2c_reg_len = REGLEN_8bit,
493  }, {
494  .id = 0x25,
496  .name = "TDA10048-2",
497  .i2c_bus_nr = SAA7164_I2C_BUS_2,
498  .i2c_bus_addr = 0x12 >> 1,
499  .i2c_reg_len = REGLEN_8bit,
500  } },
501  },
502 };
503 const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
504 
505 /* ------------------------------------------------------------------ */
506 /* PCI subsystem IDs */
507 
509  {
510  .subvendor = 0x0070,
511  .subdevice = 0x8880,
513  }, {
514  .subvendor = 0x0070,
515  .subdevice = 0x8810,
517  }, {
518  .subvendor = 0x0070,
519  .subdevice = 0x8980,
521  }, {
522  .subvendor = 0x0070,
523  .subdevice = 0x8900,
525  }, {
526  .subvendor = 0x0070,
527  .subdevice = 0x8901,
529  }, {
530  .subvendor = 0x0070,
531  .subdevice = 0x88A1,
533  }, {
534  .subvendor = 0x0070,
535  .subdevice = 0x8891,
537  }, {
538  .subvendor = 0x0070,
539  .subdevice = 0x8851,
541  }, {
542  .subvendor = 0x0070,
543  .subdevice = 0x8940,
545  }, {
546  .subvendor = 0x0070,
547  .subdevice = 0x8953,
549  },
550 };
551 const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
552 
554 {
555  int i;
556 
557  if (0 == dev->pci->subsystem_vendor &&
558  0 == dev->pci->subsystem_device) {
560  "%s: Board has no valid PCIe Subsystem ID and can't\n"
561  "%s: be autodetected. Pass card=<n> insmod option to\n"
562  "%s: workaround that. Send complaints to the vendor\n"
563  "%s: of the TV card. Best regards,\n"
564  "%s: -- tux\n",
565  dev->name, dev->name, dev->name, dev->name, dev->name);
566  } else {
568  "%s: Your board isn't known (yet) to the driver.\n"
569  "%s: Try to pick one of the existing card configs via\n"
570  "%s: card=<n> insmod option. Updating to the latest\n"
571  "%s: version might help as well.\n",
572  dev->name, dev->name, dev->name, dev->name);
573  }
574 
575  printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod "
576  "option:\n", dev->name);
577 
578  for (i = 0; i < saa7164_bcount; i++)
579  printk(KERN_ERR "%s: card=%d -> %s\n",
580  dev->name, i, saa7164_boards[i].name);
581 }
582 
583 /* TODO: clean this define up into the -cards.c structs */
584 #define PCIEBRIDGE_UNITID 2
585 
587 {
588  switch (dev->board) {
597  /*
598  GPIO 2: s5h1411 / tda10048-1 demod reset
599  GPIO 3: s5h1411 / tda10048-2 demod reset
600  GPIO 7: IRBlaster Zilog reset
601  */
602 
603  /* Reset parts by going in and out of reset */
606 
607  msleep(20);
608 
611  break;
612  }
613 }
614 
615 static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data)
616 {
617  struct tveeprom tv;
618 
619  /* TODO: Assumption: eeprom on bus 0 */
620  tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
621  eeprom_data);
622 
623  /* Make sure we support the board model */
624  switch (tv.model) {
625  case 88001:
626  /* Development board - Limit circulation */
627  /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
628  * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
629  case 88021:
630  /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
631  * ATSC/QAM (TDA18271/S5H1411) and basic analog, MCE CIR, FM */
632  break;
633  case 88041:
634  /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
635  * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
636  break;
637  case 88061:
638  /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
639  * ATSC/QAM (TDA18271/S5H1411) and basic analog, FM */
640  break;
641  case 89519:
642  case 89609:
643  /* WinTV-HVR2200 (PCIe, Retail, full-height)
644  * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
645  break;
646  case 89619:
647  /* WinTV-HVR2200 (PCIe, Retail, half-height)
648  * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
649  break;
650  default:
651  printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n",
652  dev->name, tv.model);
653  break;
654  }
655 
656  printk(KERN_INFO "%s: Hauppauge eeprom: model=%d\n", dev->name,
657  tv.model);
658 }
659 
661 {
662  static u8 eeprom[256];
663 
664  if (dev->i2c_bus[0].i2c_rc == 0) {
665  if (saa7164_api_read_eeprom(dev, &eeprom[0],
666  sizeof(eeprom)) < 0)
667  return;
668  }
669 
670  switch (dev->board) {
679  hauppauge_eeprom(dev, &eeprom[0]);
680  break;
681  }
682 }
683 
684 /* With most other drivers, the kernel expects to communicate with subdrivers
685  * through i2c. This bridge does not allow that, it does not expose any direct
686  * access to I2C. Instead we have to communicate through the device f/w for
687  * register access to 'processing units'. Each unit has a unique
688  * id, regardless of how the physical implementation occurs across
689  * the three physical i2c busses. The being said if we want leverge of
690  * the existing kernel drivers for tuners and demods we have to 'speak i2c',
691  * to this bridge implements 3 virtual i2c buses. This is a helper function
692  * for those.
693  *
694  * Description: Translate the kernels notion of an i2c address and bus into
695  * the appropriate unitid.
696  */
698 {
699  /* For a given bus and i2c device address, return the saa7164 unique
700  * unitid. < 0 on error */
701 
702  struct saa7164_dev *dev = bus->dev;
703  struct saa7164_unit *unit;
704  int i;
705 
706  for (i = 0; i < SAA7164_MAX_UNITS; i++) {
707  unit = &saa7164_boards[dev->board].unit[i];
708 
709  if (unit->type == SAA7164_UNIT_UNDEFINED)
710  continue;
711  if ((bus->nr == unit->i2c_bus_nr) &&
712  (addr == unit->i2c_bus_addr))
713  return unit->id;
714  }
715 
716  return -1;
717 }
718 
719 /* The 7164 API needs to know the i2c register length in advance.
720  * this is a helper function. Based on a specific chip addr and bus return the
721  * reg length.
722  */
724 {
725  /* For a given bus and i2c device address, return the
726  * saa7164 registry address width. < 0 on error
727  */
728 
729  struct saa7164_dev *dev = bus->dev;
730  struct saa7164_unit *unit;
731  int i;
732 
733  for (i = 0; i < SAA7164_MAX_UNITS; i++) {
734  unit = &saa7164_boards[dev->board].unit[i];
735 
736  if (unit->type == SAA7164_UNIT_UNDEFINED)
737  continue;
738 
739  if ((bus->nr == unit->i2c_bus_nr) &&
740  (addr == unit->i2c_bus_addr))
741  return unit->i2c_reg_len;
742  }
743 
744  return -1;
745 }
746 /* TODO: implement a 'findeeprom' functio like the above and fix any other
747  * eeprom related todo's in -api.c.
748  */
749 
750 /* Translate a unitid into a x readable device name, for display purposes. */
752 {
753  char *undefed = "UNDEFINED";
754  char *bridge = "BRIDGE";
755  struct saa7164_unit *unit;
756  int i;
757 
758  if (unitid == 0)
759  return bridge;
760 
761  for (i = 0; i < SAA7164_MAX_UNITS; i++) {
762  unit = &saa7164_boards[dev->board].unit[i];
763 
764  if (unit->type == SAA7164_UNIT_UNDEFINED)
765  continue;
766 
767  if (unitid == unit->id)
768  return unit->name;
769  }
770 
771  return undefed;
772 }
773