PageRenderTime 31ms CodeModel.GetById 4ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/media/video/saa7164/saa7164-cards.c

https://bitbucket.org/wisechild/galaxy-nexus
C | 715 lines | 595 code | 40 blank | 80 comment | 30 complexity | 64a420c949ca41ffe07c691dda4390c8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  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		.portc		= SAA7164_MPEG_ENCODER,
273		.portd		= SAA7164_MPEG_ENCODER,
274		.porte		= SAA7164_MPEG_VBI,
275		.portf		= SAA7164_MPEG_VBI,
276		.chiprev	= SAA7164_CHIP_REV3,
277		.unit		= {{
278			.id		= 0x22,
279			.type		= SAA7164_UNIT_EEPROM,
280			.name		= "4K EEPROM",
281			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
282			.i2c_bus_addr	= 0xa0 >> 1,
283			.i2c_reg_len	= REGLEN_8bit,
284		}, {
285			.id		= 0x04,
286			.type		= SAA7164_UNIT_TUNER,
287			.name		= "TDA18271-1",
288			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
289			.i2c_bus_addr	= 0xc0 >> 1,
290			.i2c_reg_len	= REGLEN_8bit,
291		}, {
292			.id		= 0x07,
293			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
294			.name		= "CX24228/S5H1411-1 (TOP)",
295			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
296			.i2c_bus_addr	= 0x32 >> 1,
297			.i2c_reg_len	= REGLEN_8bit,
298		}, {
299			.id		= 0x08,
300			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
301			.name		= "CX24228/S5H1411-1 (QAM)",
302			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
303			.i2c_bus_addr	= 0x34 >> 1,
304			.i2c_reg_len	= REGLEN_8bit,
305		}, {
306			.id		= 0x1e,
307			.type		= SAA7164_UNIT_TUNER,
308			.name		= "TDA18271-2",
309			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
310			.i2c_bus_addr	= 0xc0 >> 1,
311			.i2c_reg_len	= REGLEN_8bit,
312		}, {
313			.id		= 0x20,
314			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
315			.name		= "CX24228/S5H1411-2 (TOP)",
316			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
317			.i2c_bus_addr	= 0x32 >> 1,
318			.i2c_reg_len	= REGLEN_8bit,
319		}, {
320			.id		= 0x23,
321			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
322			.name		= "CX24228/S5H1411-2 (QAM)",
323			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
324			.i2c_bus_addr	= 0x34 >> 1,
325			.i2c_reg_len	= REGLEN_8bit,
326		} },
327	},
328	[SAA7164_BOARD_HAUPPAUGE_HVR2250_2] = {
329		.name		= "Hauppauge WinTV-HVR2250",
330		.porta		= SAA7164_MPEG_DVB,
331		.portb		= SAA7164_MPEG_DVB,
332		.portc		= SAA7164_MPEG_ENCODER,
333		.portd		= SAA7164_MPEG_ENCODER,
334		.porte		= SAA7164_MPEG_VBI,
335		.portf		= SAA7164_MPEG_VBI,
336		.porte		= SAA7164_MPEG_VBI,
337		.portf		= SAA7164_MPEG_VBI,
338		.chiprev	= SAA7164_CHIP_REV3,
339		.unit		= {{
340			.id		= 0x28,
341			.type		= SAA7164_UNIT_EEPROM,
342			.name		= "4K EEPROM",
343			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
344			.i2c_bus_addr	= 0xa0 >> 1,
345			.i2c_reg_len	= REGLEN_8bit,
346		}, {
347			.id		= 0x04,
348			.type		= SAA7164_UNIT_TUNER,
349			.name		= "TDA18271-1",
350			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
351			.i2c_bus_addr	= 0xc0 >> 1,
352			.i2c_reg_len	= REGLEN_8bit,
353		}, {
354			.id		= 0x07,
355			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
356			.name		= "CX24228/S5H1411-1 (TOP)",
357			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
358			.i2c_bus_addr	= 0x32 >> 1,
359			.i2c_reg_len	= REGLEN_8bit,
360		}, {
361			.id		= 0x08,
362			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
363			.name		= "CX24228/S5H1411-1 (QAM)",
364			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
365			.i2c_bus_addr	= 0x34 >> 1,
366			.i2c_reg_len	= REGLEN_8bit,
367		}, {
368			.id		= 0x24,
369			.type		= SAA7164_UNIT_TUNER,
370			.name		= "TDA18271-2",
371			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
372			.i2c_bus_addr	= 0xc0 >> 1,
373			.i2c_reg_len	= REGLEN_8bit,
374		}, {
375			.id		= 0x26,
376			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
377			.name		= "CX24228/S5H1411-2 (TOP)",
378			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
379			.i2c_bus_addr	= 0x32 >> 1,
380			.i2c_reg_len	= REGLEN_8bit,
381		}, {
382			.id		= 0x29,
383			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
384			.name		= "CX24228/S5H1411-2 (QAM)",
385			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
386			.i2c_bus_addr	= 0x34 >> 1,
387			.i2c_reg_len	= REGLEN_8bit,
388		} },
389	},
390	[SAA7164_BOARD_HAUPPAUGE_HVR2250_3] = {
391		.name		= "Hauppauge WinTV-HVR2250",
392		.porta		= SAA7164_MPEG_DVB,
393		.portb		= SAA7164_MPEG_DVB,
394		.portc		= SAA7164_MPEG_ENCODER,
395		.portd		= SAA7164_MPEG_ENCODER,
396		.porte		= SAA7164_MPEG_VBI,
397		.portf		= SAA7164_MPEG_VBI,
398		.chiprev	= SAA7164_CHIP_REV3,
399		.unit		= {{
400			.id		= 0x26,
401			.type		= SAA7164_UNIT_EEPROM,
402			.name		= "4K EEPROM",
403			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
404			.i2c_bus_addr	= 0xa0 >> 1,
405			.i2c_reg_len	= REGLEN_8bit,
406		}, {
407			.id		= 0x04,
408			.type		= SAA7164_UNIT_TUNER,
409			.name		= "TDA18271-1",
410			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
411			.i2c_bus_addr	= 0xc0 >> 1,
412			.i2c_reg_len	= REGLEN_8bit,
413		}, {
414			.id		= 0x07,
415			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
416			.name		= "CX24228/S5H1411-1 (TOP)",
417			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
418			.i2c_bus_addr	= 0x32 >> 1,
419			.i2c_reg_len	= REGLEN_8bit,
420		}, {
421			.id		= 0x08,
422			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
423			.name		= "CX24228/S5H1411-1 (QAM)",
424			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
425			.i2c_bus_addr	= 0x34 >> 1,
426			.i2c_reg_len	= REGLEN_8bit,
427		}, {
428			.id		= 0x22,
429			.type		= SAA7164_UNIT_TUNER,
430			.name		= "TDA18271-2",
431			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
432			.i2c_bus_addr	= 0xc0 >> 1,
433			.i2c_reg_len	= REGLEN_8bit,
434		}, {
435			.id		= 0x24,
436			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
437			.name		= "CX24228/S5H1411-2 (TOP)",
438			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
439			.i2c_bus_addr	= 0x32 >> 1,
440			.i2c_reg_len	= REGLEN_8bit,
441		}, {
442			.id		= 0x27,
443			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
444			.name		= "CX24228/S5H1411-2 (QAM)",
445			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
446			.i2c_bus_addr	= 0x34 >> 1,
447			.i2c_reg_len	= REGLEN_8bit,
448		} },
449	},
450};
451const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
452
453/* ------------------------------------------------------------------ */
454/* PCI subsystem IDs                                                  */
455
456struct saa7164_subid saa7164_subids[] = {
457	{
458		.subvendor = 0x0070,
459		.subdevice = 0x8880,
460		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
461	}, {
462		.subvendor = 0x0070,
463		.subdevice = 0x8810,
464		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
465	}, {
466		.subvendor = 0x0070,
467		.subdevice = 0x8980,
468		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200,
469	}, {
470		.subvendor = 0x0070,
471		.subdevice = 0x8900,
472		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_2,
473	}, {
474		.subvendor = 0x0070,
475		.subdevice = 0x8901,
476		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_3,
477	}, {
478		.subvendor = 0x0070,
479		.subdevice = 0x88A1,
480		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_3,
481	}, {
482		.subvendor = 0x0070,
483		.subdevice = 0x8891,
484		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
485	}, {
486		.subvendor = 0x0070,
487		.subdevice = 0x8851,
488		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
489	}, {
490		.subvendor = 0x0070,
491		.subdevice = 0x8940,
492		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_4,
493	},
494};
495const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
496
497void saa7164_card_list(struct saa7164_dev *dev)
498{
499	int i;
500
501	if (0 == dev->pci->subsystem_vendor &&
502	    0 == dev->pci->subsystem_device) {
503		printk(KERN_ERR
504			"%s: Board has no valid PCIe Subsystem ID and can't\n"
505			"%s: be autodetected. Pass card=<n> insmod option to\n"
506			"%s: workaround that. Send complaints to the vendor\n"
507			"%s: of the TV card. Best regards,\n"
508			"%s:         -- tux\n",
509			dev->name, dev->name, dev->name, dev->name, dev->name);
510	} else {
511		printk(KERN_ERR
512			"%s: Your board isn't known (yet) to the driver.\n"
513			"%s: Try to pick one of the existing card configs via\n"
514			"%s: card=<n> insmod option.  Updating to the latest\n"
515			"%s: version might help as well.\n",
516			dev->name, dev->name, dev->name, dev->name);
517	}
518
519	printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod "
520		"option:\n", dev->name);
521
522	for (i = 0; i < saa7164_bcount; i++)
523		printk(KERN_ERR "%s:    card=%d -> %s\n",
524		       dev->name, i, saa7164_boards[i].name);
525}
526
527/* TODO: clean this define up into the -cards.c structs */
528#define PCIEBRIDGE_UNITID 2
529
530void saa7164_gpio_setup(struct saa7164_dev *dev)
531{
532	switch (dev->board) {
533	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
534	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
535	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
536	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
537	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
538	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
539	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
540		/*
541		GPIO 2: s5h1411 / tda10048-1 demod reset
542		GPIO 3: s5h1411 / tda10048-2 demod reset
543		GPIO 7: IRBlaster Zilog reset
544		 */
545
546		/* Reset parts by going in and out of reset */
547		saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
548		saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
549
550		msleep(20);
551
552		saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
553		saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
554		break;
555	}
556}
557
558static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data)
559{
560	struct tveeprom tv;
561
562	/* TODO: Assumption: eeprom on bus 0 */
563	tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
564		eeprom_data);
565
566	/* Make sure we support the board model */
567	switch (tv.model) {
568	case 88001:
569		/* Development board - Limit circulation */
570		/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
571		 * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
572	case 88021:
573		/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
574		 * ATSC/QAM (TDA18271/S5H1411) and basic analog, MCE CIR, FM */
575		break;
576	case 88041:
577		/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
578		 * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
579		break;
580	case 88061:
581		/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
582		 * ATSC/QAM (TDA18271/S5H1411) and basic analog, FM */
583		break;
584	case 89519:
585	case 89609:
586		/* WinTV-HVR2200 (PCIe, Retail, full-height)
587		 * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
588		break;
589	case 89619:
590		/* WinTV-HVR2200 (PCIe, Retail, half-height)
591		 * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
592		break;
593	default:
594		printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n",
595			dev->name, tv.model);
596		break;
597	}
598
599	printk(KERN_INFO "%s: Hauppauge eeprom: model=%d\n", dev->name,
600		tv.model);
601}
602
603void saa7164_card_setup(struct saa7164_dev *dev)
604{
605	static u8 eeprom[256];
606
607	if (dev->i2c_bus[0].i2c_rc == 0) {
608		if (saa7164_api_read_eeprom(dev, &eeprom[0],
609			sizeof(eeprom)) < 0)
610			return;
611	}
612
613	switch (dev->board) {
614	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
615	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
616	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
617	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
618	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
619	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
620	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
621		hauppauge_eeprom(dev, &eeprom[0]);
622		break;
623	}
624}
625
626/* With most other drivers, the kernel expects to communicate with subdrivers
627 * through i2c. This bridge does not allow that, it does not expose any direct
628 * access to I2C. Instead we have to communicate through the device f/w for
629 * register access to 'processing units'. Each unit has a unique
630 * id, regardless of how the physical implementation occurs across
631 * the three physical i2c busses. The being said if we want leverge of
632 * the existing kernel drivers for tuners and demods we have to 'speak i2c',
633 * to this bridge implements 3 virtual i2c buses. This is a helper function
634 * for those.
635 *
636 * Description: Translate the kernels notion of an i2c address and bus into
637 * the appropriate unitid.
638 */
639int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr)
640{
641	/* For a given bus and i2c device address, return the saa7164 unique
642	 * unitid. < 0 on error */
643
644	struct saa7164_dev *dev = bus->dev;
645	struct saa7164_unit *unit;
646	int i;
647
648	for (i = 0; i < SAA7164_MAX_UNITS; i++) {
649		unit = &saa7164_boards[dev->board].unit[i];
650
651		if (unit->type == SAA7164_UNIT_UNDEFINED)
652			continue;
653		if ((bus->nr == unit->i2c_bus_nr) &&
654			(addr == unit->i2c_bus_addr))
655			return unit->id;
656	}
657
658	return -1;
659}
660
661/* The 7164 API needs to know the i2c register length in advance.
662 * this is a helper function. Based on a specific chip addr and bus return the
663 * reg length.
664 */
665int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr)
666{
667	/* For a given bus and i2c device address, return the
668	 * saa7164 registry address width. < 0 on error
669	 */
670
671	struct saa7164_dev *dev = bus->dev;
672	struct saa7164_unit *unit;
673	int i;
674
675	for (i = 0; i < SAA7164_MAX_UNITS; i++) {
676		unit = &saa7164_boards[dev->board].unit[i];
677
678		if (unit->type == SAA7164_UNIT_UNDEFINED)
679			continue;
680
681		if ((bus->nr == unit->i2c_bus_nr) &&
682			(addr == unit->i2c_bus_addr))
683			return unit->i2c_reg_len;
684	}
685
686	return -1;
687}
688/* TODO: implement a 'findeeprom' functio like the above and fix any other
689 * eeprom related todo's in -api.c.
690 */
691
692/* Translate a unitid into a x readable device name, for display purposes.  */
693char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid)
694{
695	char *undefed = "UNDEFINED";
696	char *bridge = "BRIDGE";
697	struct saa7164_unit *unit;
698	int i;
699
700	if (unitid == 0)
701		return bridge;
702
703	for (i = 0; i < SAA7164_MAX_UNITS; i++) {
704		unit = &saa7164_boards[dev->board].unit[i];
705
706		if (unit->type == SAA7164_UNIT_UNDEFINED)
707			continue;
708
709		if (unitid == unit->id)
710				return unit->name;
711	}
712
713	return undefed;
714}
715