1 /*
2  *  Driver for the NXP SAA7164 PCIe bridge
3  *
4  *  Copyright (c) 2010-2015 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 
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/pci.h>
21 #include <linux/delay.h>
22 
23 #include "saa7164.h"
24 
25 /* The Bridge API needs to understand register widths (in bytes) for the
26  * attached I2C devices, so we can simplify the virtual i2c mechansms
27  * and keep the -i2c.c implementation clean.
28  */
29 #define REGLEN_0bit	0
30 #define REGLEN_8bit	1
31 #define REGLEN_16bit	2
32 
33 struct saa7164_board saa7164_boards[] = {
34 	[SAA7164_BOARD_UNKNOWN] = {
35 		/* Bridge will not load any firmware, without knowing
36 		 * the rev this would be fatal. */
37 		.name		= "Unknown",
38 	},
39 	[SAA7164_BOARD_UNKNOWN_REV2] = {
40 		/* Bridge will load the v2 f/w and dump descriptors */
41 		/* Required during new board bringup */
42 		.name		= "Generic Rev2",
43 		.chiprev	= SAA7164_CHIP_REV2,
44 	},
45 	[SAA7164_BOARD_UNKNOWN_REV3] = {
46 		/* Bridge will load the v2 f/w and dump descriptors */
47 		/* Required during new board bringup */
48 		.name		= "Generic Rev3",
49 		.chiprev	= SAA7164_CHIP_REV3,
50 	},
51 	[SAA7164_BOARD_HAUPPAUGE_HVR2200] = {
52 		.name		= "Hauppauge WinTV-HVR2200",
53 		.porta		= SAA7164_MPEG_DVB,
54 		.portb		= SAA7164_MPEG_DVB,
55 		.portc		= SAA7164_MPEG_ENCODER,
56 		.portd		= SAA7164_MPEG_ENCODER,
57 		.porte		= SAA7164_MPEG_VBI,
58 		.portf		= SAA7164_MPEG_VBI,
59 		.chiprev	= SAA7164_CHIP_REV3,
60 		.unit		= {{
61 			.id		= 0x1d,
62 			.type		= SAA7164_UNIT_EEPROM,
63 			.name		= "4K EEPROM",
64 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
65 			.i2c_bus_addr	= 0xa0 >> 1,
66 			.i2c_reg_len	= REGLEN_8bit,
67 		}, {
68 			.id		= 0x04,
69 			.type		= SAA7164_UNIT_TUNER,
70 			.name		= "TDA18271-1",
71 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
72 			.i2c_bus_addr	= 0xc0 >> 1,
73 			.i2c_reg_len	= REGLEN_8bit,
74 		}, {
75 			.id		= 0x1b,
76 			.type		= SAA7164_UNIT_TUNER,
77 			.name		= "TDA18271-2",
78 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
79 			.i2c_bus_addr	= 0xc0 >> 1,
80 			.i2c_reg_len	= REGLEN_8bit,
81 		}, {
82 			.id		= 0x1e,
83 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
84 			.name		= "TDA10048-1",
85 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
86 			.i2c_bus_addr	= 0x10 >> 1,
87 			.i2c_reg_len	= REGLEN_8bit,
88 		}, {
89 			.id		= 0x1f,
90 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
91 			.name		= "TDA10048-2",
92 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
93 			.i2c_bus_addr	= 0x12 >> 1,
94 			.i2c_reg_len	= REGLEN_8bit,
95 		} },
96 	},
97 	[SAA7164_BOARD_HAUPPAUGE_HVR2200_2] = {
98 		.name		= "Hauppauge WinTV-HVR2200",
99 		.porta		= SAA7164_MPEG_DVB,
100 		.portb		= SAA7164_MPEG_DVB,
101 		.portc		= SAA7164_MPEG_ENCODER,
102 		.portd		= SAA7164_MPEG_ENCODER,
103 		.porte		= SAA7164_MPEG_VBI,
104 		.portf		= SAA7164_MPEG_VBI,
105 		.chiprev	= SAA7164_CHIP_REV2,
106 		.unit		= {{
107 			.id		= 0x06,
108 			.type		= SAA7164_UNIT_EEPROM,
109 			.name		= "4K EEPROM",
110 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
111 			.i2c_bus_addr	= 0xa0 >> 1,
112 			.i2c_reg_len	= REGLEN_8bit,
113 		}, {
114 			.id		= 0x04,
115 			.type		= SAA7164_UNIT_TUNER,
116 			.name		= "TDA18271-1",
117 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
118 			.i2c_bus_addr	= 0xc0 >> 1,
119 			.i2c_reg_len	= REGLEN_8bit,
120 		}, {
121 			.id		= 0x05,
122 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
123 			.name		= "TDA10048-1",
124 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
125 			.i2c_bus_addr	= 0x10 >> 1,
126 			.i2c_reg_len	= REGLEN_8bit,
127 		}, {
128 			.id		= 0x1e,
129 			.type		= SAA7164_UNIT_TUNER,
130 			.name		= "TDA18271-2",
131 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
132 			.i2c_bus_addr	= 0xc0 >> 1,
133 			.i2c_reg_len	= REGLEN_8bit,
134 		}, {
135 			.id		= 0x1f,
136 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
137 			.name		= "TDA10048-2",
138 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
139 			.i2c_bus_addr	= 0x12 >> 1,
140 			.i2c_reg_len	= REGLEN_8bit,
141 		} },
142 	},
143 	[SAA7164_BOARD_HAUPPAUGE_HVR2200_3] = {
144 		.name		= "Hauppauge WinTV-HVR2200",
145 		.porta		= SAA7164_MPEG_DVB,
146 		.portb		= SAA7164_MPEG_DVB,
147 		.portc		= SAA7164_MPEG_ENCODER,
148 		.portd		= SAA7164_MPEG_ENCODER,
149 		.porte		= SAA7164_MPEG_VBI,
150 		.portf		= SAA7164_MPEG_VBI,
151 		.chiprev	= SAA7164_CHIP_REV2,
152 		.unit		= {{
153 			.id		= 0x1d,
154 			.type		= SAA7164_UNIT_EEPROM,
155 			.name		= "4K EEPROM",
156 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
157 			.i2c_bus_addr	= 0xa0 >> 1,
158 			.i2c_reg_len	= REGLEN_8bit,
159 		}, {
160 			.id		= 0x04,
161 			.type		= SAA7164_UNIT_TUNER,
162 			.name		= "TDA18271-1",
163 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
164 			.i2c_bus_addr	= 0xc0 >> 1,
165 			.i2c_reg_len	= REGLEN_8bit,
166 		}, {
167 			.id		= 0x05,
168 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
169 			.name		= "TDA8290-1",
170 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
171 			.i2c_bus_addr	= 0x84 >> 1,
172 			.i2c_reg_len	= REGLEN_8bit,
173 		}, {
174 			.id		= 0x1b,
175 			.type		= SAA7164_UNIT_TUNER,
176 			.name		= "TDA18271-2",
177 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
178 			.i2c_bus_addr	= 0xc0 >> 1,
179 			.i2c_reg_len	= REGLEN_8bit,
180 		}, {
181 			.id		= 0x1c,
182 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
183 			.name		= "TDA8290-2",
184 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
185 			.i2c_bus_addr	= 0x84 >> 1,
186 			.i2c_reg_len	= REGLEN_8bit,
187 		}, {
188 			.id		= 0x1e,
189 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
190 			.name		= "TDA10048-1",
191 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
192 			.i2c_bus_addr	= 0x10 >> 1,
193 			.i2c_reg_len	= REGLEN_8bit,
194 		}, {
195 			.id		= 0x1f,
196 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
197 			.name		= "TDA10048-2",
198 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
199 			.i2c_bus_addr	= 0x12 >> 1,
200 			.i2c_reg_len	= REGLEN_8bit,
201 		} },
202 	},
203 	[SAA7164_BOARD_HAUPPAUGE_HVR2200_4] = {
204 		.name		= "Hauppauge WinTV-HVR2200",
205 		.porta		= SAA7164_MPEG_DVB,
206 		.portb		= SAA7164_MPEG_DVB,
207 		.portc		= SAA7164_MPEG_ENCODER,
208 		.portd		= SAA7164_MPEG_ENCODER,
209 		.porte		= SAA7164_MPEG_VBI,
210 		.portf		= SAA7164_MPEG_VBI,
211 		.chiprev	= SAA7164_CHIP_REV3,
212 		.unit		= {{
213 			.id		= 0x1d,
214 			.type		= SAA7164_UNIT_EEPROM,
215 			.name		= "4K EEPROM",
216 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
217 			.i2c_bus_addr	= 0xa0 >> 1,
218 			.i2c_reg_len	= REGLEN_8bit,
219 		}, {
220 			.id		= 0x04,
221 			.type		= SAA7164_UNIT_TUNER,
222 			.name		= "TDA18271-1",
223 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
224 			.i2c_bus_addr	= 0xc0 >> 1,
225 			.i2c_reg_len	= REGLEN_8bit,
226 		}, {
227 			.id		= 0x05,
228 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
229 			.name		= "TDA8290-1",
230 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
231 			.i2c_bus_addr	= 0x84 >> 1,
232 			.i2c_reg_len	= REGLEN_8bit,
233 		}, {
234 			.id		= 0x1b,
235 			.type		= SAA7164_UNIT_TUNER,
236 			.name		= "TDA18271-2",
237 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
238 			.i2c_bus_addr	= 0xc0 >> 1,
239 			.i2c_reg_len	= REGLEN_8bit,
240 		}, {
241 			.id		= 0x1c,
242 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
243 			.name		= "TDA8290-2",
244 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
245 			.i2c_bus_addr	= 0x84 >> 1,
246 			.i2c_reg_len	= REGLEN_8bit,
247 		}, {
248 			.id		= 0x1e,
249 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
250 			.name		= "TDA10048-1",
251 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
252 			.i2c_bus_addr	= 0x10 >> 1,
253 			.i2c_reg_len	= REGLEN_8bit,
254 		}, {
255 			.id		= 0x1f,
256 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
257 			.name		= "TDA10048-2",
258 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
259 			.i2c_bus_addr	= 0x12 >> 1,
260 			.i2c_reg_len	= REGLEN_8bit,
261 		} },
262 	},
263 	[SAA7164_BOARD_HAUPPAUGE_HVR2250] = {
264 		.name		= "Hauppauge WinTV-HVR2250",
265 		.porta		= SAA7164_MPEG_DVB,
266 		.portb		= SAA7164_MPEG_DVB,
267 		.portc		= SAA7164_MPEG_ENCODER,
268 		.portd		= SAA7164_MPEG_ENCODER,
269 		.porte		= SAA7164_MPEG_VBI,
270 		.portf		= SAA7164_MPEG_VBI,
271 		.chiprev	= SAA7164_CHIP_REV3,
272 		.unit		= {{
273 			.id		= 0x22,
274 			.type		= SAA7164_UNIT_EEPROM,
275 			.name		= "4K EEPROM",
276 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
277 			.i2c_bus_addr	= 0xa0 >> 1,
278 			.i2c_reg_len	= REGLEN_8bit,
279 		}, {
280 			.id		= 0x04,
281 			.type		= SAA7164_UNIT_TUNER,
282 			.name		= "TDA18271-1",
283 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
284 			.i2c_bus_addr	= 0xc0 >> 1,
285 			.i2c_reg_len	= REGLEN_8bit,
286 		}, {
287 			.id		= 0x07,
288 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
289 			.name		= "CX24228/S5H1411-1 (TOP)",
290 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
291 			.i2c_bus_addr	= 0x32 >> 1,
292 			.i2c_reg_len	= REGLEN_8bit,
293 		}, {
294 			.id		= 0x08,
295 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
296 			.name		= "CX24228/S5H1411-1 (QAM)",
297 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
298 			.i2c_bus_addr	= 0x34 >> 1,
299 			.i2c_reg_len	= REGLEN_8bit,
300 		}, {
301 			.id		= 0x1e,
302 			.type		= SAA7164_UNIT_TUNER,
303 			.name		= "TDA18271-2",
304 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
305 			.i2c_bus_addr	= 0xc0 >> 1,
306 			.i2c_reg_len	= REGLEN_8bit,
307 		}, {
308 			.id		= 0x20,
309 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
310 			.name		= "CX24228/S5H1411-2 (TOP)",
311 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
312 			.i2c_bus_addr	= 0x32 >> 1,
313 			.i2c_reg_len	= REGLEN_8bit,
314 		}, {
315 			.id		= 0x23,
316 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
317 			.name		= "CX24228/S5H1411-2 (QAM)",
318 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
319 			.i2c_bus_addr	= 0x34 >> 1,
320 			.i2c_reg_len	= REGLEN_8bit,
321 		} },
322 	},
323 	[SAA7164_BOARD_HAUPPAUGE_HVR2250_2] = {
324 		.name		= "Hauppauge WinTV-HVR2250",
325 		.porta		= SAA7164_MPEG_DVB,
326 		.portb		= SAA7164_MPEG_DVB,
327 		.portc		= SAA7164_MPEG_ENCODER,
328 		.portd		= SAA7164_MPEG_ENCODER,
329 		.porte		= SAA7164_MPEG_VBI,
330 		.portf		= SAA7164_MPEG_VBI,
331 		.chiprev	= SAA7164_CHIP_REV3,
332 		.unit		= {{
333 			.id		= 0x28,
334 			.type		= SAA7164_UNIT_EEPROM,
335 			.name		= "4K EEPROM",
336 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
337 			.i2c_bus_addr	= 0xa0 >> 1,
338 			.i2c_reg_len	= REGLEN_8bit,
339 		}, {
340 			.id		= 0x04,
341 			.type		= SAA7164_UNIT_TUNER,
342 			.name		= "TDA18271-1",
343 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
344 			.i2c_bus_addr	= 0xc0 >> 1,
345 			.i2c_reg_len	= REGLEN_8bit,
346 		}, {
347 			.id		= 0x07,
348 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
349 			.name		= "CX24228/S5H1411-1 (TOP)",
350 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
351 			.i2c_bus_addr	= 0x32 >> 1,
352 			.i2c_reg_len	= REGLEN_8bit,
353 		}, {
354 			.id		= 0x08,
355 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
356 			.name		= "CX24228/S5H1411-1 (QAM)",
357 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
358 			.i2c_bus_addr	= 0x34 >> 1,
359 			.i2c_reg_len	= REGLEN_8bit,
360 		}, {
361 			.id		= 0x24,
362 			.type		= SAA7164_UNIT_TUNER,
363 			.name		= "TDA18271-2",
364 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
365 			.i2c_bus_addr	= 0xc0 >> 1,
366 			.i2c_reg_len	= REGLEN_8bit,
367 		}, {
368 			.id		= 0x26,
369 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
370 			.name		= "CX24228/S5H1411-2 (TOP)",
371 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
372 			.i2c_bus_addr	= 0x32 >> 1,
373 			.i2c_reg_len	= REGLEN_8bit,
374 		}, {
375 			.id		= 0x29,
376 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
377 			.name		= "CX24228/S5H1411-2 (QAM)",
378 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
379 			.i2c_bus_addr	= 0x34 >> 1,
380 			.i2c_reg_len	= REGLEN_8bit,
381 		} },
382 	},
383 	[SAA7164_BOARD_HAUPPAUGE_HVR2250_3] = {
384 		.name		= "Hauppauge WinTV-HVR2250",
385 		.porta		= SAA7164_MPEG_DVB,
386 		.portb		= SAA7164_MPEG_DVB,
387 		.portc		= SAA7164_MPEG_ENCODER,
388 		.portd		= SAA7164_MPEG_ENCODER,
389 		.porte		= SAA7164_MPEG_VBI,
390 		.portf		= SAA7164_MPEG_VBI,
391 		.chiprev	= SAA7164_CHIP_REV3,
392 		.unit		= {{
393 			.id		= 0x26,
394 			.type		= SAA7164_UNIT_EEPROM,
395 			.name		= "4K EEPROM",
396 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
397 			.i2c_bus_addr	= 0xa0 >> 1,
398 			.i2c_reg_len	= REGLEN_8bit,
399 		}, {
400 			.id		= 0x04,
401 			.type		= SAA7164_UNIT_TUNER,
402 			.name		= "TDA18271-1",
403 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
404 			.i2c_bus_addr	= 0xc0 >> 1,
405 			.i2c_reg_len	= REGLEN_8bit,
406 		}, {
407 			.id		= 0x07,
408 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
409 			.name		= "CX24228/S5H1411-1 (TOP)",
410 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
411 			.i2c_bus_addr	= 0x32 >> 1,
412 			.i2c_reg_len	= REGLEN_8bit,
413 		}, {
414 			.id		= 0x08,
415 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
416 			.name		= "CX24228/S5H1411-1 (QAM)",
417 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
418 			.i2c_bus_addr	= 0x34 >> 1,
419 			.i2c_reg_len	= REGLEN_8bit,
420 		}, {
421 			.id		= 0x22,
422 			.type		= SAA7164_UNIT_TUNER,
423 			.name		= "TDA18271-2",
424 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
425 			.i2c_bus_addr	= 0xc0 >> 1,
426 			.i2c_reg_len	= REGLEN_8bit,
427 		}, {
428 			.id		= 0x24,
429 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
430 			.name		= "CX24228/S5H1411-2 (TOP)",
431 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
432 			.i2c_bus_addr	= 0x32 >> 1,
433 			.i2c_reg_len	= REGLEN_8bit,
434 		}, {
435 			.id		= 0x27,
436 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
437 			.name		= "CX24228/S5H1411-2 (QAM)",
438 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
439 			.i2c_bus_addr	= 0x34 >> 1,
440 			.i2c_reg_len	= REGLEN_8bit,
441 		} },
442 	},
443 	[SAA7164_BOARD_HAUPPAUGE_HVR2200_5] = {
444 		.name		= "Hauppauge WinTV-HVR2200",
445 		.porta		= SAA7164_MPEG_DVB,
446 		.portb		= SAA7164_MPEG_DVB,
447 		.chiprev	= SAA7164_CHIP_REV3,
448 		.unit		= {{
449 			.id		= 0x23,
450 			.type		= SAA7164_UNIT_EEPROM,
451 			.name		= "4K EEPROM",
452 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
453 			.i2c_bus_addr	= 0xa0 >> 1,
454 			.i2c_reg_len	= REGLEN_8bit,
455 		}, {
456 			.id		= 0x04,
457 			.type		= SAA7164_UNIT_TUNER,
458 			.name		= "TDA18271-1",
459 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
460 			.i2c_bus_addr	= 0xc0 >> 1,
461 			.i2c_reg_len	= REGLEN_8bit,
462 		}, {
463 			.id		= 0x05,
464 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
465 			.name		= "TDA8290-1",
466 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
467 			.i2c_bus_addr	= 0x84 >> 1,
468 			.i2c_reg_len	= REGLEN_8bit,
469 		}, {
470 			.id		= 0x21,
471 			.type		= SAA7164_UNIT_TUNER,
472 			.name		= "TDA18271-2",
473 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
474 			.i2c_bus_addr	= 0xc0 >> 1,
475 			.i2c_reg_len	= REGLEN_8bit,
476 		}, {
477 			.id		= 0x22,
478 			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
479 			.name		= "TDA8290-2",
480 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
481 			.i2c_bus_addr	= 0x84 >> 1,
482 			.i2c_reg_len	= REGLEN_8bit,
483 		}, {
484 			.id		= 0x24,
485 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
486 			.name		= "TDA10048-1",
487 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
488 			.i2c_bus_addr	= 0x10 >> 1,
489 			.i2c_reg_len	= REGLEN_8bit,
490 		}, {
491 			.id		= 0x25,
492 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
493 			.name		= "TDA10048-2",
494 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
495 			.i2c_bus_addr	= 0x12 >> 1,
496 			.i2c_reg_len	= REGLEN_8bit,
497 		} },
498 	},
499 	[SAA7164_BOARD_HAUPPAUGE_HVR2255proto] = {
500 		.name		= "Hauppauge WinTV-HVR2255(proto)",
501 		.porta		= SAA7164_MPEG_DVB,
502 		.portb		= SAA7164_MPEG_DVB,
503 		.portc		= SAA7164_MPEG_ENCODER,
504 		.portd		= SAA7164_MPEG_ENCODER,
505 		.porte		= SAA7164_MPEG_VBI,
506 		.portf		= SAA7164_MPEG_VBI,
507 		.chiprev	= SAA7164_CHIP_REV3,
508 		.unit		= {{
509 			.id		= 0x27,
510 			.type		= SAA7164_UNIT_EEPROM,
511 			.name		= "4K EEPROM",
512 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
513 			.i2c_bus_addr	= 0xa0 >> 1,
514 			.i2c_reg_len	= REGLEN_8bit,
515 		}, {
516 			.id		= 0x04,
517 			.type		= SAA7164_UNIT_TUNER,
518 			.name		= "SI2157-1",
519 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
520 			.i2c_bus_addr	= 0xc0 >> 1,
521 			.i2c_reg_len	= REGLEN_0bit,
522 		}, {
523 			.id		= 0x06,
524 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
525 			.name		= "LGDT3306",
526 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
527 			.i2c_bus_addr	= 0xb2 >> 1,
528 			.i2c_reg_len	= REGLEN_8bit,
529 		}, {
530 			.id		= 0x24,
531 			.type		= SAA7164_UNIT_TUNER,
532 			.name		= "SI2157-2",
533 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
534 			.i2c_bus_addr	= 0xc0 >> 1,
535 			.i2c_reg_len	= REGLEN_0bit,
536 		}, {
537 			.id		= 0x26,
538 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
539 			.name		= "LGDT3306-2",
540 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
541 			.i2c_bus_addr	= 0x1c >> 1,
542 			.i2c_reg_len	= REGLEN_8bit,
543 		} },
544 	},
545 	[SAA7164_BOARD_HAUPPAUGE_HVR2255] = {
546 		.name		= "Hauppauge WinTV-HVR2255",
547 		.porta		= SAA7164_MPEG_DVB,
548 		.portb		= SAA7164_MPEG_DVB,
549 		.portc		= SAA7164_MPEG_ENCODER,
550 		.portd		= SAA7164_MPEG_ENCODER,
551 		.porte		= SAA7164_MPEG_VBI,
552 		.portf		= SAA7164_MPEG_VBI,
553 		.chiprev	= SAA7164_CHIP_REV3,
554 		.unit		= {{
555 			.id		= 0x28,
556 			.type		= SAA7164_UNIT_EEPROM,
557 			.name		= "4K EEPROM",
558 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
559 			.i2c_bus_addr	= 0xa0 >> 1,
560 			.i2c_reg_len	= REGLEN_8bit,
561 		}, {
562 			.id		= 0x04,
563 			.type		= SAA7164_UNIT_TUNER,
564 			.name		= "SI2157-1",
565 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
566 			.i2c_bus_addr	= 0xc0 >> 1,
567 			.i2c_reg_len	= REGLEN_0bit,
568 		}, {
569 			.id		= 0x06,
570 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
571 			.name		= "LGDT3306-1",
572 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
573 			.i2c_bus_addr	= 0xb2 >> 1,
574 			.i2c_reg_len	= REGLEN_8bit,
575 		}, {
576 			.id		= 0x25,
577 			.type		= SAA7164_UNIT_TUNER,
578 			.name		= "SI2157-2",
579 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
580 			.i2c_bus_addr	= 0xc0 >> 1,
581 			.i2c_reg_len	= REGLEN_0bit,
582 		}, {
583 			.id		= 0x27,
584 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
585 			.name		= "LGDT3306-2",
586 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
587 			.i2c_bus_addr	= 0x1c >> 1,
588 			.i2c_reg_len	= REGLEN_8bit,
589 		} },
590 	},
591 	[SAA7164_BOARD_HAUPPAUGE_HVR2205] = {
592 		.name		= "Hauppauge WinTV-HVR2205",
593 		.porta		= SAA7164_MPEG_DVB,
594 		.portb		= SAA7164_MPEG_DVB,
595 		.portc		= SAA7164_MPEG_ENCODER,
596 		.portd		= SAA7164_MPEG_ENCODER,
597 		.porte		= SAA7164_MPEG_VBI,
598 		.portf		= SAA7164_MPEG_VBI,
599 		.chiprev	= SAA7164_CHIP_REV3,
600 		.unit		= {{
601 			.id		= 0x28,
602 			.type		= SAA7164_UNIT_EEPROM,
603 			.name		= "4K EEPROM",
604 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
605 			.i2c_bus_addr	= 0xa0 >> 1,
606 			.i2c_reg_len	= REGLEN_8bit,
607 		}, {
608 			.id		= 0x04,
609 			.type		= SAA7164_UNIT_TUNER,
610 			.name		= "SI2157-1",
611 			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
612 			.i2c_bus_addr	= 0xc0 >> 1,
613 			.i2c_reg_len	= REGLEN_0bit,
614 		}, {
615 			.id		= 0x06,
616 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
617 			.name		= "SI2168-1",
618 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
619 			.i2c_bus_addr	= 0xc8 >> 1,
620 			.i2c_reg_len	= REGLEN_0bit,
621 		}, {
622 			.id		= 0x25,
623 			.type		= SAA7164_UNIT_TUNER,
624 			.name		= "SI2157-2",
625 			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
626 			.i2c_bus_addr	= 0xc0 >> 1,
627 			.i2c_reg_len	= REGLEN_0bit,
628 		}, {
629 			.id		= 0x27,
630 			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
631 			.name		= "SI2168-2",
632 			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
633 			.i2c_bus_addr	= 0xcc >> 1,
634 			.i2c_reg_len	= REGLEN_0bit,
635 		} },
636 	},
637 };
638 const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
639 
640 /* ------------------------------------------------------------------ */
641 /* PCI subsystem IDs                                                  */
642 
643 struct saa7164_subid saa7164_subids[] = {
644 	{
645 		.subvendor = 0x0070,
646 		.subdevice = 0x8880,
647 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
648 	}, {
649 		.subvendor = 0x0070,
650 		.subdevice = 0x8810,
651 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
652 	}, {
653 		.subvendor = 0x0070,
654 		.subdevice = 0x8980,
655 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200,
656 	}, {
657 		.subvendor = 0x0070,
658 		.subdevice = 0x8900,
659 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_2,
660 	}, {
661 		.subvendor = 0x0070,
662 		.subdevice = 0x8901,
663 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_3,
664 	}, {
665 		.subvendor = 0x0070,
666 		.subdevice = 0x88A1,
667 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_3,
668 	}, {
669 		.subvendor = 0x0070,
670 		.subdevice = 0x8891,
671 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
672 	}, {
673 		.subvendor = 0x0070,
674 		.subdevice = 0x8851,
675 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
676 	}, {
677 		.subvendor = 0x0070,
678 		.subdevice = 0x8940,
679 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_4,
680 	}, {
681 		.subvendor = 0x0070,
682 		.subdevice = 0x8953,
683 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
684 	}, {
685 		.subvendor = 0x0070,
686 		.subdevice = 0xf111,
687 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2255,
688 		/* Prototype card left here for documentation purposes.
689 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2255proto,
690 		*/
691 	}, {
692 		.subvendor = 0x0070,
693 		.subdevice = 0xf123,
694 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2205,
695 	}, {
696 		.subvendor = 0x0070,
697 		.subdevice = 0xf120,
698 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2205,
699 	},
700 };
701 const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
702 
703 void saa7164_card_list(struct saa7164_dev *dev)
704 {
705 	int i;
706 
707 	if (0 == dev->pci->subsystem_vendor &&
708 	    0 == dev->pci->subsystem_device) {
709 		printk(KERN_ERR
710 			"%s: Board has no valid PCIe Subsystem ID and can't\n"
711 			"%s: be autodetected. Pass card=<n> insmod option to\n"
712 			"%s: workaround that. Send complaints to the vendor\n"
713 			"%s: of the TV card. Best regards,\n"
714 			"%s:         -- tux\n",
715 			dev->name, dev->name, dev->name, dev->name, dev->name);
716 	} else {
717 		printk(KERN_ERR
718 			"%s: Your board isn't known (yet) to the driver.\n"
719 			"%s: Try to pick one of the existing card configs via\n"
720 			"%s: card=<n> insmod option.  Updating to the latest\n"
721 			"%s: version might help as well.\n",
722 			dev->name, dev->name, dev->name, dev->name);
723 	}
724 
725 	printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod option:\n",
726 	       dev->name);
727 
728 	for (i = 0; i < saa7164_bcount; i++)
729 		printk(KERN_ERR "%s:    card=%d -> %s\n",
730 		       dev->name, i, saa7164_boards[i].name);
731 }
732 
733 /* TODO: clean this define up into the -cards.c structs */
734 #define PCIEBRIDGE_UNITID 2
735 
736 void saa7164_gpio_setup(struct saa7164_dev *dev)
737 {
738 	switch (dev->board) {
739 	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
740 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
741 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
742 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
743 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
744 	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
745 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
746 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
747 	case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
748 	case SAA7164_BOARD_HAUPPAUGE_HVR2255:
749 	case SAA7164_BOARD_HAUPPAUGE_HVR2205:
750 		/*
751 		HVR2200 / HVR2250
752 		GPIO 2: s5h1411 / tda10048-1 demod reset
753 		GPIO 3: s5h1411 / tda10048-2 demod reset
754 		GPIO 7: IRBlaster Zilog reset
755 		 */
756 
757 		/* HVR2255
758 		 * GPIO 2: lgdg3306-1 demod reset
759 		 * GPIO 3: lgdt3306-2 demod reset
760 		 */
761 
762 		/* HVR2205
763 		 * GPIO 2: si2168-1 demod reset
764 		 * GPIO 3: si2168-2 demod reset
765 		 */
766 
767 		/* Reset parts by going in and out of reset */
768 		saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
769 		saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
770 
771 		msleep(20);
772 
773 		saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
774 		saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
775 		break;
776 	}
777 }
778 
779 static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data)
780 {
781 	struct tveeprom tv;
782 
783 	tveeprom_hauppauge_analog(&tv, eeprom_data);
784 
785 	/* Make sure we support the board model */
786 	switch (tv.model) {
787 	case 88001:
788 		/* Development board - Limit circulation */
789 		/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
790 		 * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
791 	case 88021:
792 		/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
793 		 * ATSC/QAM (TDA18271/S5H1411) and basic analog, MCE CIR, FM */
794 		break;
795 	case 88041:
796 		/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
797 		 * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
798 		break;
799 	case 88061:
800 		/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
801 		 * ATSC/QAM (TDA18271/S5H1411) and basic analog, FM */
802 		break;
803 	case 89519:
804 	case 89609:
805 		/* WinTV-HVR2200 (PCIe, Retail, full-height)
806 		 * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
807 		break;
808 	case 89619:
809 		/* WinTV-HVR2200 (PCIe, Retail, half-height)
810 		 * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
811 		break;
812 	case 151009:
813 		/* First production board rev B2I6 */
814 		/* WinTV-HVR2205 (PCIe, Retail, full-height bracket)
815 		 * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */
816 		break;
817 	case 151609:
818 		/* First production board rev B2I6 */
819 		/* WinTV-HVR2205 (PCIe, Retail, half-height bracket)
820 		 * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */
821 		break;
822 	case 151061:
823 		/* First production board rev B1I6 */
824 		/* WinTV-HVR2255 (PCIe, Retail, full-height bracket)
825 		 * ATSC/QAM (SI2157/LGDT3306) and basic analog, FM */
826 		break;
827 	default:
828 		printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n",
829 			dev->name, tv.model);
830 		break;
831 	}
832 
833 	printk(KERN_INFO "%s: Hauppauge eeprom: model=%d\n", dev->name,
834 		tv.model);
835 }
836 
837 void saa7164_card_setup(struct saa7164_dev *dev)
838 {
839 	static u8 eeprom[256];
840 
841 	if (dev->i2c_bus[0].i2c_rc == 0) {
842 		if (saa7164_api_read_eeprom(dev, &eeprom[0],
843 			sizeof(eeprom)) < 0)
844 			return;
845 	}
846 
847 	switch (dev->board) {
848 	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
849 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
850 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
851 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
852 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
853 	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
854 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
855 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
856 	case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
857 	case SAA7164_BOARD_HAUPPAUGE_HVR2255:
858 	case SAA7164_BOARD_HAUPPAUGE_HVR2205:
859 		hauppauge_eeprom(dev, &eeprom[0]);
860 		break;
861 	}
862 }
863 
864 /* With most other drivers, the kernel expects to communicate with subdrivers
865  * through i2c. This bridge does not allow that, it does not expose any direct
866  * access to I2C. Instead we have to communicate through the device f/w for
867  * register access to 'processing units'. Each unit has a unique
868  * id, regardless of how the physical implementation occurs across
869  * the three physical i2c buses. The being said if we want leverge of
870  * the existing kernel drivers for tuners and demods we have to 'speak i2c',
871  * to this bridge implements 3 virtual i2c buses. This is a helper function
872  * for those.
873  *
874  * Description: Translate the kernels notion of an i2c address and bus into
875  * the appropriate unitid.
876  */
877 int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr)
878 {
879 	/* For a given bus and i2c device address, return the saa7164 unique
880 	 * unitid. < 0 on error */
881 
882 	struct saa7164_dev *dev = bus->dev;
883 	struct saa7164_unit *unit;
884 	int i;
885 
886 	for (i = 0; i < SAA7164_MAX_UNITS; i++) {
887 		unit = &saa7164_boards[dev->board].unit[i];
888 
889 		if (unit->type == SAA7164_UNIT_UNDEFINED)
890 			continue;
891 		if ((bus->nr == unit->i2c_bus_nr) &&
892 			(addr == unit->i2c_bus_addr))
893 			return unit->id;
894 	}
895 
896 	return -1;
897 }
898 
899 /* The 7164 API needs to know the i2c register length in advance.
900  * this is a helper function. Based on a specific chip addr and bus return the
901  * reg length.
902  */
903 int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr)
904 {
905 	/* For a given bus and i2c device address, return the
906 	 * saa7164 registry address width. < 0 on error
907 	 */
908 
909 	struct saa7164_dev *dev = bus->dev;
910 	struct saa7164_unit *unit;
911 	int i;
912 
913 	for (i = 0; i < SAA7164_MAX_UNITS; i++) {
914 		unit = &saa7164_boards[dev->board].unit[i];
915 
916 		if (unit->type == SAA7164_UNIT_UNDEFINED)
917 			continue;
918 
919 		if ((bus->nr == unit->i2c_bus_nr) &&
920 			(addr == unit->i2c_bus_addr))
921 			return unit->i2c_reg_len;
922 	}
923 
924 	return -1;
925 }
926 /* TODO: implement a 'findeeprom' functio like the above and fix any other
927  * eeprom related todo's in -api.c.
928  */
929 
930 /* Translate a unitid into a x readable device name, for display purposes.  */
931 char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid)
932 {
933 	char *undefed = "UNDEFINED";
934 	char *bridge = "BRIDGE";
935 	struct saa7164_unit *unit;
936 	int i;
937 
938 	if (unitid == 0)
939 		return bridge;
940 
941 	for (i = 0; i < SAA7164_MAX_UNITS; i++) {
942 		unit = &saa7164_boards[dev->board].unit[i];
943 
944 		if (unit->type == SAA7164_UNIT_UNDEFINED)
945 			continue;
946 
947 		if (unitid == unit->id)
948 				return unit->name;
949 	}
950 
951 	return undefed;
952 }
953 
954