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
36struct saa7164_board saa7164_boards[] = {
37	[SAA7164_BOARD_UNKNOWN] = {
38		/* Bridge will not load any firmware, without knowing
39		 * the rev this would be fatal. */
40		.name		= "Unknown",
41	},
42	[SAA7164_BOARD_UNKNOWN_REV2] = {
43		/* Bridge will load the v2 f/w and dump descriptors */
44		/* Required during new board bringup */
45		.name		= "Generic Rev2",
46		.chiprev	= SAA7164_CHIP_REV2,
47	},
48	[SAA7164_BOARD_UNKNOWN_REV3] = {
49		/* Bridge will load the v2 f/w and dump descriptors */
50		/* Required during new board bringup */
51		.name		= "Generic Rev3",
52		.chiprev	= SAA7164_CHIP_REV3,
53	},
54	[SAA7164_BOARD_HAUPPAUGE_HVR2200] = {
55		.name		= "Hauppauge WinTV-HVR2200",
56		.porta		= SAA7164_MPEG_DVB,
57		.portb		= SAA7164_MPEG_DVB,
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};
503const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
504
505/* ------------------------------------------------------------------ */
506/* PCI subsystem IDs                                                  */
507
508struct 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};
551const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
552
553void 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
586void 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
615static 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
660void 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 */
697int 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 */
723int 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.  */
751char *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