blob: 81baa3662919642b21b7d7a3fabbebfb60cab678 [file] [log] [blame]
Steven Toth443c12282009-05-09 21:17:28 -03001/*
2 * Driver for the NXP SAA7164 PCIe bridge
3 *
Steven Toth9b8b0192010-07-31 14:39:44 -03004 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
Steven Toth443c12282009-05-09 21:17:28 -03005 *
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
36struct saa7164_board saa7164_boards[] = {
37 [SAA7164_BOARD_UNKNOWN] = {
38 /* Bridge will not load any firmware, without knowing
39 * the rev this would be fatal. */
40 .name = "Unknown",
41 },
42 [SAA7164_BOARD_UNKNOWN_REV2] = {
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 },
48 [SAA7164_BOARD_UNKNOWN_REV3] = {
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 },
54 [SAA7164_BOARD_HAUPPAUGE_HVR2200] = {
55 .name = "Hauppauge WinTV-HVR2200",
56 .porta = SAA7164_MPEG_DVB,
57 .portb = SAA7164_MPEG_DVB,
Steven Toth7615e432010-07-31 14:44:53 -030058 .portc = SAA7164_MPEG_ENCODER,
59 .portd = SAA7164_MPEG_ENCODER,
Steven Toth443c12282009-05-09 21:17:28 -030060 .chiprev = SAA7164_CHIP_REV3,
61 .unit = {{
Steven Toth30015c12009-05-14 01:15:15 -030062 .id = 0x1d,
Steven Toth443c12282009-05-09 21:17:28 -030063 .type = SAA7164_UNIT_EEPROM,
64 .name = "4K EEPROM",
65 .i2c_bus_nr = SAA7164_I2C_BUS_0,
66 .i2c_bus_addr = 0xa0 >> 1,
67 .i2c_reg_len = REGLEN_8bit,
68 }, {
69 .id = 0x04,
70 .type = SAA7164_UNIT_TUNER,
71 .name = "TDA18271-1",
72 .i2c_bus_nr = SAA7164_I2C_BUS_1,
73 .i2c_bus_addr = 0xc0 >> 1,
74 .i2c_reg_len = REGLEN_8bit,
75 }, {
76 .id = 0x1b,
77 .type = SAA7164_UNIT_TUNER,
78 .name = "TDA18271-2",
79 .i2c_bus_nr = SAA7164_I2C_BUS_2,
80 .i2c_bus_addr = 0xc0 >> 1,
81 .i2c_reg_len = REGLEN_8bit,
82 }, {
83 .id = 0x1e,
84 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
85 .name = "TDA10048-1",
86 .i2c_bus_nr = SAA7164_I2C_BUS_1,
87 .i2c_bus_addr = 0x10 >> 1,
88 .i2c_reg_len = REGLEN_8bit,
89 }, {
90 .id = 0x1f,
91 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
92 .name = "TDA10048-2",
93 .i2c_bus_nr = SAA7164_I2C_BUS_2,
94 .i2c_bus_addr = 0x12 >> 1,
95 .i2c_reg_len = REGLEN_8bit,
96 } },
97 },
98 [SAA7164_BOARD_HAUPPAUGE_HVR2200_2] = {
99 .name = "Hauppauge WinTV-HVR2200",
100 .porta = SAA7164_MPEG_DVB,
101 .portb = SAA7164_MPEG_DVB,
Steven Toth7615e432010-07-31 14:44:53 -0300102 .portc = SAA7164_MPEG_ENCODER,
103 .portd = SAA7164_MPEG_ENCODER,
Steven Toth443c12282009-05-09 21:17:28 -0300104 .chiprev = SAA7164_CHIP_REV2,
105 .unit = {{
106 .id = 0x06,
107 .type = SAA7164_UNIT_EEPROM,
108 .name = "4K EEPROM",
109 .i2c_bus_nr = SAA7164_I2C_BUS_0,
110 .i2c_bus_addr = 0xa0 >> 1,
111 .i2c_reg_len = REGLEN_8bit,
112 }, {
113 .id = 0x04,
114 .type = SAA7164_UNIT_TUNER,
115 .name = "TDA18271-1",
116 .i2c_bus_nr = SAA7164_I2C_BUS_1,
117 .i2c_bus_addr = 0xc0 >> 1,
118 .i2c_reg_len = REGLEN_8bit,
119 }, {
120 .id = 0x05,
121 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
122 .name = "TDA10048-1",
123 .i2c_bus_nr = SAA7164_I2C_BUS_1,
124 .i2c_bus_addr = 0x10 >> 1,
125 .i2c_reg_len = REGLEN_8bit,
126 }, {
127 .id = 0x1e,
128 .type = SAA7164_UNIT_TUNER,
129 .name = "TDA18271-2",
130 .i2c_bus_nr = SAA7164_I2C_BUS_2,
131 .i2c_bus_addr = 0xc0 >> 1,
132 .i2c_reg_len = REGLEN_8bit,
133 }, {
134 .id = 0x1f,
135 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
136 .name = "TDA10048-2",
137 .i2c_bus_nr = SAA7164_I2C_BUS_2,
138 .i2c_bus_addr = 0x12 >> 1,
139 .i2c_reg_len = REGLEN_8bit,
140 } },
141 },
142 [SAA7164_BOARD_HAUPPAUGE_HVR2200_3] = {
143 .name = "Hauppauge WinTV-HVR2200",
144 .porta = SAA7164_MPEG_DVB,
145 .portb = SAA7164_MPEG_DVB,
Steven Toth7615e432010-07-31 14:44:53 -0300146 .portc = SAA7164_MPEG_ENCODER,
147 .portd = SAA7164_MPEG_ENCODER,
Steven Toth443c12282009-05-09 21:17:28 -0300148 .chiprev = SAA7164_CHIP_REV2,
149 .unit = {{
Steven Toth30015c12009-05-14 01:15:15 -0300150 .id = 0x1d,
Steven Toth443c12282009-05-09 21:17:28 -0300151 .type = SAA7164_UNIT_EEPROM,
152 .name = "4K EEPROM",
153 .i2c_bus_nr = SAA7164_I2C_BUS_0,
154 .i2c_bus_addr = 0xa0 >> 1,
155 .i2c_reg_len = REGLEN_8bit,
156 }, {
157 .id = 0x04,
158 .type = SAA7164_UNIT_TUNER,
159 .name = "TDA18271-1",
160 .i2c_bus_nr = SAA7164_I2C_BUS_1,
161 .i2c_bus_addr = 0xc0 >> 1,
162 .i2c_reg_len = REGLEN_8bit,
163 }, {
164 .id = 0x05,
165 .type = SAA7164_UNIT_ANALOG_DEMODULATOR,
166 .name = "TDA8290-1",
167 .i2c_bus_nr = SAA7164_I2C_BUS_1,
168 .i2c_bus_addr = 0x84 >> 1,
169 .i2c_reg_len = REGLEN_8bit,
170 }, {
171 .id = 0x1b,
172 .type = SAA7164_UNIT_TUNER,
173 .name = "TDA18271-2",
174 .i2c_bus_nr = SAA7164_I2C_BUS_2,
175 .i2c_bus_addr = 0xc0 >> 1,
176 .i2c_reg_len = REGLEN_8bit,
177 }, {
178 .id = 0x1c,
179 .type = SAA7164_UNIT_ANALOG_DEMODULATOR,
180 .name = "TDA8290-2",
181 .i2c_bus_nr = SAA7164_I2C_BUS_2,
182 .i2c_bus_addr = 0x84 >> 1,
183 .i2c_reg_len = REGLEN_8bit,
184 }, {
185 .id = 0x1e,
186 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
187 .name = "TDA10048-1",
188 .i2c_bus_nr = SAA7164_I2C_BUS_1,
189 .i2c_bus_addr = 0x10 >> 1,
190 .i2c_reg_len = REGLEN_8bit,
191 }, {
192 .id = 0x1f,
193 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
194 .name = "TDA10048-2",
195 .i2c_bus_nr = SAA7164_I2C_BUS_2,
196 .i2c_bus_addr = 0x12 >> 1,
197 .i2c_reg_len = REGLEN_8bit,
198 } },
199 },
200 [SAA7164_BOARD_HAUPPAUGE_HVR2250] = {
201 .name = "Hauppauge WinTV-HVR2250",
202 .porta = SAA7164_MPEG_DVB,
203 .portb = SAA7164_MPEG_DVB,
Steven Toth7615e432010-07-31 14:44:53 -0300204 .portc = SAA7164_MPEG_ENCODER,
205 .portd = SAA7164_MPEG_ENCODER,
206 .portc = SAA7164_MPEG_ENCODER,
207 .portd = SAA7164_MPEG_ENCODER,
Steven Toth443c12282009-05-09 21:17:28 -0300208 .chiprev = SAA7164_CHIP_REV3,
209 .unit = {{
210 .id = 0x22,
211 .type = SAA7164_UNIT_EEPROM,
212 .name = "4K EEPROM",
213 .i2c_bus_nr = SAA7164_I2C_BUS_0,
214 .i2c_bus_addr = 0xa0 >> 1,
215 .i2c_reg_len = REGLEN_8bit,
216 }, {
217 .id = 0x04,
218 .type = SAA7164_UNIT_TUNER,
219 .name = "TDA18271-1",
220 .i2c_bus_nr = SAA7164_I2C_BUS_1,
221 .i2c_bus_addr = 0xc0 >> 1,
222 .i2c_reg_len = REGLEN_8bit,
223 }, {
224 .id = 0x07,
225 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
226 .name = "CX24228/S5H1411-1 (TOP)",
227 .i2c_bus_nr = SAA7164_I2C_BUS_1,
228 .i2c_bus_addr = 0x32 >> 1,
229 .i2c_reg_len = REGLEN_8bit,
230 }, {
231 .id = 0x08,
232 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
233 .name = "CX24228/S5H1411-1 (QAM)",
234 .i2c_bus_nr = SAA7164_I2C_BUS_1,
235 .i2c_bus_addr = 0x34 >> 1,
236 .i2c_reg_len = REGLEN_8bit,
237 }, {
238 .id = 0x1e,
239 .type = SAA7164_UNIT_TUNER,
240 .name = "TDA18271-2",
241 .i2c_bus_nr = SAA7164_I2C_BUS_2,
242 .i2c_bus_addr = 0xc0 >> 1,
243 .i2c_reg_len = REGLEN_8bit,
244 }, {
245 .id = 0x20,
246 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
247 .name = "CX24228/S5H1411-2 (TOP)",
248 .i2c_bus_nr = SAA7164_I2C_BUS_2,
249 .i2c_bus_addr = 0x32 >> 1,
250 .i2c_reg_len = REGLEN_8bit,
251 }, {
252 .id = 0x23,
253 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
254 .name = "CX24228/S5H1411-2 (QAM)",
255 .i2c_bus_nr = SAA7164_I2C_BUS_2,
256 .i2c_bus_addr = 0x34 >> 1,
257 .i2c_reg_len = REGLEN_8bit,
258 } },
259 },
260 [SAA7164_BOARD_HAUPPAUGE_HVR2250_2] = {
261 .name = "Hauppauge WinTV-HVR2250",
262 .porta = SAA7164_MPEG_DVB,
263 .portb = SAA7164_MPEG_DVB,
Steven Toth7615e432010-07-31 14:44:53 -0300264 .portc = SAA7164_MPEG_ENCODER,
265 .portd = SAA7164_MPEG_ENCODER,
Steven Toth443c12282009-05-09 21:17:28 -0300266 .chiprev = SAA7164_CHIP_REV3,
267 .unit = {{
Steven Toth30015c12009-05-14 01:15:15 -0300268 .id = 0x28,
Steven Toth443c12282009-05-09 21:17:28 -0300269 .type = SAA7164_UNIT_EEPROM,
270 .name = "4K EEPROM",
271 .i2c_bus_nr = SAA7164_I2C_BUS_0,
272 .i2c_bus_addr = 0xa0 >> 1,
273 .i2c_reg_len = REGLEN_8bit,
274 }, {
275 .id = 0x04,
276 .type = SAA7164_UNIT_TUNER,
277 .name = "TDA18271-1",
278 .i2c_bus_nr = SAA7164_I2C_BUS_1,
279 .i2c_bus_addr = 0xc0 >> 1,
280 .i2c_reg_len = REGLEN_8bit,
281 }, {
282 .id = 0x07,
283 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
284 .name = "CX24228/S5H1411-1 (TOP)",
285 .i2c_bus_nr = SAA7164_I2C_BUS_1,
286 .i2c_bus_addr = 0x32 >> 1,
287 .i2c_reg_len = REGLEN_8bit,
288 }, {
289 .id = 0x08,
290 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
291 .name = "CX24228/S5H1411-1 (QAM)",
292 .i2c_bus_nr = SAA7164_I2C_BUS_1,
293 .i2c_bus_addr = 0x34 >> 1,
294 .i2c_reg_len = REGLEN_8bit,
295 }, {
296 .id = 0x24,
297 .type = SAA7164_UNIT_TUNER,
298 .name = "TDA18271-2",
299 .i2c_bus_nr = SAA7164_I2C_BUS_2,
300 .i2c_bus_addr = 0xc0 >> 1,
301 .i2c_reg_len = REGLEN_8bit,
302 }, {
303 .id = 0x26,
304 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
305 .name = "CX24228/S5H1411-2 (TOP)",
306 .i2c_bus_nr = SAA7164_I2C_BUS_2,
307 .i2c_bus_addr = 0x32 >> 1,
308 .i2c_reg_len = REGLEN_8bit,
309 }, {
310 .id = 0x29,
311 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
312 .name = "CX24228/S5H1411-2 (QAM)",
313 .i2c_bus_nr = SAA7164_I2C_BUS_2,
314 .i2c_bus_addr = 0x34 >> 1,
315 .i2c_reg_len = REGLEN_8bit,
316 } },
317 },
Steven Tothe3335222009-05-11 22:03:07 -0300318 [SAA7164_BOARD_HAUPPAUGE_HVR2250_3] = {
319 .name = "Hauppauge WinTV-HVR2250",
320 .porta = SAA7164_MPEG_DVB,
321 .portb = SAA7164_MPEG_DVB,
Steven Toth7615e432010-07-31 14:44:53 -0300322 .portc = SAA7164_MPEG_ENCODER,
323 .portd = SAA7164_MPEG_ENCODER,
Steven Tothe3335222009-05-11 22:03:07 -0300324 .chiprev = SAA7164_CHIP_REV3,
325 .unit = {{
Steven Toth30015c12009-05-14 01:15:15 -0300326 .id = 0x26,
Steven Tothe3335222009-05-11 22:03:07 -0300327 .type = SAA7164_UNIT_EEPROM,
328 .name = "4K EEPROM",
329 .i2c_bus_nr = SAA7164_I2C_BUS_0,
330 .i2c_bus_addr = 0xa0 >> 1,
331 .i2c_reg_len = REGLEN_8bit,
332 }, {
333 .id = 0x04,
334 .type = SAA7164_UNIT_TUNER,
335 .name = "TDA18271-1",
336 .i2c_bus_nr = SAA7164_I2C_BUS_1,
337 .i2c_bus_addr = 0xc0 >> 1,
338 .i2c_reg_len = REGLEN_8bit,
339 }, {
340 .id = 0x07,
341 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
342 .name = "CX24228/S5H1411-1 (TOP)",
343 .i2c_bus_nr = SAA7164_I2C_BUS_1,
344 .i2c_bus_addr = 0x32 >> 1,
345 .i2c_reg_len = REGLEN_8bit,
346 }, {
347 .id = 0x08,
348 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
349 .name = "CX24228/S5H1411-1 (QAM)",
350 .i2c_bus_nr = SAA7164_I2C_BUS_1,
351 .i2c_bus_addr = 0x34 >> 1,
352 .i2c_reg_len = REGLEN_8bit,
353 }, {
354 .id = 0x22,
355 .type = SAA7164_UNIT_TUNER,
356 .name = "TDA18271-2",
357 .i2c_bus_nr = SAA7164_I2C_BUS_2,
358 .i2c_bus_addr = 0xc0 >> 1,
359 .i2c_reg_len = REGLEN_8bit,
360 }, {
361 .id = 0x24,
362 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
363 .name = "CX24228/S5H1411-2 (TOP)",
364 .i2c_bus_nr = SAA7164_I2C_BUS_2,
365 .i2c_bus_addr = 0x32 >> 1,
366 .i2c_reg_len = REGLEN_8bit,
367 }, {
368 .id = 0x27,
369 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
370 .name = "CX24228/S5H1411-2 (QAM)",
371 .i2c_bus_nr = SAA7164_I2C_BUS_2,
372 .i2c_bus_addr = 0x34 >> 1,
373 .i2c_reg_len = REGLEN_8bit,
374 } },
375 },
Steven Toth443c12282009-05-09 21:17:28 -0300376};
377const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
378
379/* ------------------------------------------------------------------ */
380/* PCI subsystem IDs */
381
382struct saa7164_subid saa7164_subids[] = {
383 {
384 .subvendor = 0x0070,
385 .subdevice = 0x8880,
386 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250,
387 }, {
388 .subvendor = 0x0070,
389 .subdevice = 0x8810,
390 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250,
391 }, {
392 .subvendor = 0x0070,
393 .subdevice = 0x8980,
394 .card = SAA7164_BOARD_HAUPPAUGE_HVR2200,
395 }, {
396 .subvendor = 0x0070,
397 .subdevice = 0x8900,
398 .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_2,
399 }, {
400 .subvendor = 0x0070,
401 .subdevice = 0x8901,
402 .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_3,
403 }, {
404 .subvendor = 0x0070,
405 .subdevice = 0x88A1,
Steven Tothe3335222009-05-11 22:03:07 -0300406 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250_3,
Steven Toth443c12282009-05-09 21:17:28 -0300407 }, {
408 .subvendor = 0x0070,
409 .subdevice = 0x8891,
410 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
Steven Toth3a360ce2009-09-03 23:46:16 -0300411 }, {
412 .subvendor = 0x0070,
413 .subdevice = 0x8851,
414 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
Steven Toth443c12282009-05-09 21:17:28 -0300415 },
416};
417const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
418
419void saa7164_card_list(struct saa7164_dev *dev)
420{
421 int i;
422
423 if (0 == dev->pci->subsystem_vendor &&
424 0 == dev->pci->subsystem_device) {
425 printk(KERN_ERR
426 "%s: Board has no valid PCIe Subsystem ID and can't\n"
427 "%s: be autodetected. Pass card=<n> insmod option to\n"
428 "%s: workaround that. Send complaints to the vendor\n"
429 "%s: of the TV card. Best regards,\n"
430 "%s: -- tux\n",
431 dev->name, dev->name, dev->name, dev->name, dev->name);
432 } else {
433 printk(KERN_ERR
434 "%s: Your board isn't known (yet) to the driver.\n"
435 "%s: Try to pick one of the existing card configs via\n"
436 "%s: card=<n> insmod option. Updating to the latest\n"
437 "%s: version might help as well.\n",
438 dev->name, dev->name, dev->name, dev->name);
439 }
440
441 printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod "
442 "option:\n", dev->name);
443
444 for (i = 0; i < saa7164_bcount; i++)
445 printk(KERN_ERR "%s: card=%d -> %s\n",
446 dev->name, i, saa7164_boards[i].name);
447}
448
449/* TODO: clean this define up into the -cards.c structs */
450#define PCIEBRIDGE_UNITID 2
451
452void saa7164_gpio_setup(struct saa7164_dev *dev)
453{
454
455
456 switch (dev->board) {
457 case SAA7164_BOARD_HAUPPAUGE_HVR2200:
458 case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
459 case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
460 case SAA7164_BOARD_HAUPPAUGE_HVR2250:
461 case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
Steven Tothe3335222009-05-11 22:03:07 -0300462 case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
Steven Toth443c12282009-05-09 21:17:28 -0300463 /*
464 GPIO 2: s5h1411 / tda10048-1 demod reset
465 GPIO 3: s5h1411 / tda10048-2 demod reset
466 GPIO 7: IRBlaster Zilog reset
467 */
468
469 /* Reset parts by going in and out of reset */
470 saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
471 saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
472
473 msleep(10);
474
475 saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
476 saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
477 break;
478 }
479
480}
481
482static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data)
483{
484 struct tveeprom tv;
485
486 /* TODO: Assumption: eeprom on bus 0 */
487 tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
488 eeprom_data);
489
490 /* Make sure we support the board model */
491 switch (tv.model) {
492 case 88001:
493 /* Development board - Limit circulation */
494 /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
495 * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
496 case 88021:
497 /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
498 * ATSC/QAM (TDA18271/S5H1411) and basic analog, MCE CIR, FM */
499 break;
500 case 88041:
501 /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
502 * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
503 break;
504 case 88061:
505 /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
506 * ATSC/QAM (TDA18271/S5H1411) and basic analog, FM */
507 break;
508 case 89519:
509 case 89609:
510 /* WinTV-HVR2200 (PCIe, Retail, full-height)
511 * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
512 break;
513 case 89619:
514 /* WinTV-HVR2200 (PCIe, Retail, half-height)
515 * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
516 break;
517 default:
518 printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n",
519 dev->name, tv.model);
520 break;
521 }
522
523 printk(KERN_INFO "%s: Hauppauge eeprom: model=%d\n", dev->name,
524 tv.model);
525}
526
527void saa7164_card_setup(struct saa7164_dev *dev)
528{
529 static u8 eeprom[256];
530
531 if (dev->i2c_bus[0].i2c_rc == 0) {
532 if (saa7164_api_read_eeprom(dev, &eeprom[0],
533 sizeof(eeprom)) < 0)
534 return;
535 }
536
537 switch (dev->board) {
538 case SAA7164_BOARD_HAUPPAUGE_HVR2200:
539 case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
540 case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
541 case SAA7164_BOARD_HAUPPAUGE_HVR2250:
Steven Tothc303e3e2009-05-12 16:20:37 -0300542 case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
Steven Tothe3335222009-05-11 22:03:07 -0300543 case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
Steven Toth443c12282009-05-09 21:17:28 -0300544 hauppauge_eeprom(dev, &eeprom[0]);
545 break;
546 }
547}
548
549/* With most other drivers, the kernel expects to communicate with subdrivers
550 * through i2c. This bridge does not allow that, it does not expose any direct
551 * access to I2C. Instead we have to communicate through the device f/w for
552 * register access to 'processing units'. Each unit has a unique
553 * id, regardless of how the physical implementation occurs across
554 * the three physical i2c busses. The being said if we want leverge of
555 * the existing kernel drivers for tuners and demods we have to 'speak i2c',
556 * to this bridge implements 3 virtual i2c buses. This is a helper function
557 * for those.
558 *
559 * Description: Translate the kernels notion of an i2c address and bus into
560 * the appropriate unitid.
561 */
562int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr)
563{
564 /* For a given bus and i2c device address, return the saa7164 unique
565 * unitid. < 0 on error */
566
567 struct saa7164_dev *dev = bus->dev;
568 struct saa7164_unit *unit;
569 int i;
570
571 for (i = 0; i < SAA7164_MAX_UNITS; i++) {
572 unit = &saa7164_boards[dev->board].unit[i];
573
574 if (unit->type == SAA7164_UNIT_UNDEFINED)
575 continue;
576 if ((bus->nr == unit->i2c_bus_nr) &&
577 (addr == unit->i2c_bus_addr))
578 return unit->id;
579 }
580
581 return -1;
582}
583
584/* The 7164 API needs to know the i2c register length in advance.
585 * this is a helper function. Based on a specific chip addr and bus return the
586 * reg length.
587 */
588int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr)
589{
590 /* For a given bus and i2c device address, return the
591 * saa7164 registry address width. < 0 on error
592 */
593
594 struct saa7164_dev *dev = bus->dev;
595 struct saa7164_unit *unit;
596 int i;
597
598 for (i = 0; i < SAA7164_MAX_UNITS; i++) {
599 unit = &saa7164_boards[dev->board].unit[i];
600
601 if (unit->type == SAA7164_UNIT_UNDEFINED)
602 continue;
603
604 if ((bus->nr == unit->i2c_bus_nr) &&
605 (addr == unit->i2c_bus_addr))
606 return unit->i2c_reg_len;
607 }
608
609 return -1;
610}
611/* TODO: implement a 'findeeprom' functio like the above and fix any other
612 * eeprom related todo's in -api.c.
613 */
614
615/* Translate a unitid into a x readable device name, for display purposes. */
616char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid)
617{
618 char *undefed = "UNDEFINED";
619 char *bridge = "BRIDGE";
620 struct saa7164_unit *unit;
621 int i;
622
623 if (unitid == 0)
624 return bridge;
625
626 for (i = 0; i < SAA7164_MAX_UNITS; i++) {
627 unit = &saa7164_boards[dev->board].unit[i];
628
629 if (unit->type == SAA7164_UNIT_UNDEFINED)
630 continue;
631
632 if (unitid == unit->id)
633 return unit->name;
634 }
635
636 return undefed;
637}
638