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