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