1 /*
2  *  Driver for the NXP SAA7164 PCIe bridge
3  *
4  *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
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 
36 struct 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,
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,
86 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
93 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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 	},
100 	[SAA7164_BOARD_HAUPPAUGE_HVR2200_2] = {
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,
125 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
139 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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 	},
146 	[SAA7164_BOARD_HAUPPAUGE_HVR2200_3] = {
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,
171 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
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,
185 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
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,
192 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
199 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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 	},
206 	[SAA7164_BOARD_HAUPPAUGE_HVR2200_4] = {
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,
231 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
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,
245 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
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,
252 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
259 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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 	},
266 	[SAA7164_BOARD_HAUPPAUGE_HVR2250] = {
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,
291 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
298 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
312 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
319 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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 	},
326 	[SAA7164_BOARD_HAUPPAUGE_HVR2250_2] = {
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,
351 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
358 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
372 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
379 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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 	},
386 	[SAA7164_BOARD_HAUPPAUGE_HVR2250_3] = {
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,
411 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
418 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
432 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
439 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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 	},
446 	[SAA7164_BOARD_HAUPPAUGE_HVR2200_5] = {
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,
467 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
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,
481 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
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,
488 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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,
495 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
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 
508 struct saa7164_subid saa7164_subids[] = {
509 	{
510 		.subvendor = 0x0070,
511 		.subdevice = 0x8880,
512 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
513 	}, {
514 		.subvendor = 0x0070,
515 		.subdevice = 0x8810,
516 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
517 	}, {
518 		.subvendor = 0x0070,
519 		.subdevice = 0x8980,
520 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200,
521 	}, {
522 		.subvendor = 0x0070,
523 		.subdevice = 0x8900,
524 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_2,
525 	}, {
526 		.subvendor = 0x0070,
527 		.subdevice = 0x8901,
528 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_3,
529 	}, {
530 		.subvendor = 0x0070,
531 		.subdevice = 0x88A1,
532 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_3,
533 	}, {
534 		.subvendor = 0x0070,
535 		.subdevice = 0x8891,
536 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
537 	}, {
538 		.subvendor = 0x0070,
539 		.subdevice = 0x8851,
540 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
541 	}, {
542 		.subvendor = 0x0070,
543 		.subdevice = 0x8940,
544 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_4,
545 	}, {
546 		.subvendor = 0x0070,
547 		.subdevice = 0x8953,
548 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
549 	},
550 };
551 const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
552 
553 void saa7164_card_list(struct saa7164_dev *dev)
554 {
555 	int i;
556 
557 	if (0 == dev->pci->subsystem_vendor &&
558 	    0 == dev->pci->subsystem_device) {
559 		printk(KERN_ERR
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 {
567 		printk(KERN_ERR
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 
586 void saa7164_gpio_setup(struct saa7164_dev *dev)
587 {
588 	switch (dev->board) {
589 	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
590 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
591 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
592 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
593 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
594 	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
595 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
596 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
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 */
604 		saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
605 		saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
606 
607 		msleep(20);
608 
609 		saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
610 		saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
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 
660 void saa7164_card_setup(struct saa7164_dev *dev)
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) {
671 	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
672 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
673 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
674 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
675 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
676 	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
677 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
678 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
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  */
697 int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr)
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  */
723 int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr)
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.  */
751 char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid)
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 
774