2009-05-09 21:17:28 -03:00
/*
* Driver for the NXP SAA7164 PCIe bridge
*
* Copyright ( c ) 2009 Steven Toth < stoth @ kernellabs . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
*
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/delay.h>
# include "saa7164.h"
/* The Bridge API needs to understand register widths (in bytes) for the
* attached I2C devices , so we can simplify the virtual i2c mechansms
* and keep the - i2c . c implementation clean .
*/
# define REGLEN_8bit 1
# define REGLEN_16bit 2
struct saa7164_board saa7164_boards [ ] = {
[ SAA7164_BOARD_UNKNOWN ] = {
/* Bridge will not load any firmware, without knowing
* the rev this would be fatal . */
. name = " Unknown " ,
} ,
[ SAA7164_BOARD_UNKNOWN_REV2 ] = {
/* Bridge will load the v2 f/w and dump descriptors */
/* Required during new board bringup */
. name = " Generic Rev2 " ,
. chiprev = SAA7164_CHIP_REV2 ,
} ,
[ SAA7164_BOARD_UNKNOWN_REV3 ] = {
/* Bridge will load the v2 f/w and dump descriptors */
/* Required during new board bringup */
. name = " Generic Rev3 " ,
. chiprev = SAA7164_CHIP_REV3 ,
} ,
[ SAA7164_BOARD_HAUPPAUGE_HVR2200 ] = {
. name = " Hauppauge WinTV-HVR2200 " ,
. porta = SAA7164_MPEG_DVB ,
. portb = SAA7164_MPEG_DVB ,
. chiprev = SAA7164_CHIP_REV3 ,
. unit = { {
2009-05-14 01:15:15 -03:00
. id = 0x1d ,
2009-05-09 21:17:28 -03:00
. type = SAA7164_UNIT_EEPROM ,
. name = " 4K EEPROM " ,
. i2c_bus_nr = SAA7164_I2C_BUS_0 ,
. i2c_bus_addr = 0xa0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x04 ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1b ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1e ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " TDA10048-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x10 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1f ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " TDA10048-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x12 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} } ,
} ,
[ SAA7164_BOARD_HAUPPAUGE_HVR2200_2 ] = {
. name = " Hauppauge WinTV-HVR2200 " ,
. porta = SAA7164_MPEG_DVB ,
. portb = SAA7164_MPEG_DVB ,
. chiprev = SAA7164_CHIP_REV2 ,
. unit = { {
. id = 0x06 ,
. type = SAA7164_UNIT_EEPROM ,
. name = " 4K EEPROM " ,
. i2c_bus_nr = SAA7164_I2C_BUS_0 ,
. i2c_bus_addr = 0xa0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x04 ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x05 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " TDA10048-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x10 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1e ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1f ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " TDA10048-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x12 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} } ,
} ,
[ SAA7164_BOARD_HAUPPAUGE_HVR2200_3 ] = {
. name = " Hauppauge WinTV-HVR2200 " ,
. porta = SAA7164_MPEG_DVB ,
. portb = SAA7164_MPEG_DVB ,
. chiprev = SAA7164_CHIP_REV2 ,
. unit = { {
2009-05-14 01:15:15 -03:00
. id = 0x1d ,
2009-05-09 21:17:28 -03:00
. type = SAA7164_UNIT_EEPROM ,
. name = " 4K EEPROM " ,
. i2c_bus_nr = SAA7164_I2C_BUS_0 ,
. i2c_bus_addr = 0xa0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x04 ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x05 ,
. type = SAA7164_UNIT_ANALOG_DEMODULATOR ,
. name = " TDA8290-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x84 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1b ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1c ,
. type = SAA7164_UNIT_ANALOG_DEMODULATOR ,
. name = " TDA8290-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x84 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1e ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " TDA10048-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x10 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1f ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " TDA10048-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x12 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} } ,
} ,
[ SAA7164_BOARD_HAUPPAUGE_HVR2250 ] = {
. name = " Hauppauge WinTV-HVR2250 " ,
. porta = SAA7164_MPEG_DVB ,
. portb = SAA7164_MPEG_DVB ,
. chiprev = SAA7164_CHIP_REV3 ,
. unit = { {
. id = 0x22 ,
. type = SAA7164_UNIT_EEPROM ,
. name = " 4K EEPROM " ,
. i2c_bus_nr = SAA7164_I2C_BUS_0 ,
. i2c_bus_addr = 0xa0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x04 ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x07 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-1 (TOP) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x32 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x08 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-1 (QAM) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x34 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x1e ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x20 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-2 (TOP) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x32 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x23 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-2 (QAM) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x34 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} } ,
} ,
[ SAA7164_BOARD_HAUPPAUGE_HVR2250_2 ] = {
. name = " Hauppauge WinTV-HVR2250 " ,
. porta = SAA7164_MPEG_DVB ,
. portb = SAA7164_MPEG_DVB ,
. chiprev = SAA7164_CHIP_REV3 ,
. unit = { {
2009-05-14 01:15:15 -03:00
. id = 0x28 ,
2009-05-09 21:17:28 -03:00
. type = SAA7164_UNIT_EEPROM ,
. name = " 4K EEPROM " ,
. i2c_bus_nr = SAA7164_I2C_BUS_0 ,
. i2c_bus_addr = 0xa0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x04 ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x07 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-1 (TOP) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x32 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x08 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-1 (QAM) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x34 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x24 ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x26 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-2 (TOP) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x32 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x29 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-2 (QAM) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x34 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} } ,
} ,
2009-05-11 22:03:07 -03:00
[ SAA7164_BOARD_HAUPPAUGE_HVR2250_3 ] = {
. name = " Hauppauge WinTV-HVR2250 " ,
. porta = SAA7164_MPEG_DVB ,
. portb = SAA7164_MPEG_DVB ,
. chiprev = SAA7164_CHIP_REV3 ,
. unit = { {
2009-05-14 01:15:15 -03:00
. id = 0x26 ,
2009-05-11 22:03:07 -03:00
. type = SAA7164_UNIT_EEPROM ,
. name = " 4K EEPROM " ,
. i2c_bus_nr = SAA7164_I2C_BUS_0 ,
. i2c_bus_addr = 0xa0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x04 ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-1 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x07 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-1 (TOP) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x32 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x08 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-1 (QAM) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_1 ,
. i2c_bus_addr = 0x34 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x22 ,
. type = SAA7164_UNIT_TUNER ,
. name = " TDA18271-2 " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0xc0 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x24 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-2 (TOP) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x32 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} , {
. id = 0x27 ,
. type = SAA7164_UNIT_DIGITAL_DEMODULATOR ,
. name = " CX24228/S5H1411-2 (QAM) " ,
. i2c_bus_nr = SAA7164_I2C_BUS_2 ,
. i2c_bus_addr = 0x34 > > 1 ,
. i2c_reg_len = REGLEN_8bit ,
} } ,
} ,
2009-05-09 21:17:28 -03:00
} ;
const unsigned int saa7164_bcount = ARRAY_SIZE ( saa7164_boards ) ;
/* ------------------------------------------------------------------ */
/* PCI subsystem IDs */
struct saa7164_subid saa7164_subids [ ] = {
{
. subvendor = 0x0070 ,
. subdevice = 0x8880 ,
. card = SAA7164_BOARD_HAUPPAUGE_HVR2250 ,
} , {
. subvendor = 0x0070 ,
. subdevice = 0x8810 ,
. card = SAA7164_BOARD_HAUPPAUGE_HVR2250 ,
} , {
. subvendor = 0x0070 ,
. subdevice = 0x8980 ,
. card = SAA7164_BOARD_HAUPPAUGE_HVR2200 ,
} , {
. subvendor = 0x0070 ,
. subdevice = 0x8900 ,
. card = SAA7164_BOARD_HAUPPAUGE_HVR2200_2 ,
} , {
. subvendor = 0x0070 ,
. subdevice = 0x8901 ,
. card = SAA7164_BOARD_HAUPPAUGE_HVR2200_3 ,
} , {
. subvendor = 0x0070 ,
. subdevice = 0x88A1 ,
2009-05-11 22:03:07 -03:00
. card = SAA7164_BOARD_HAUPPAUGE_HVR2250_3 ,
2009-05-09 21:17:28 -03:00
} , {
. subvendor = 0x0070 ,
. subdevice = 0x8891 ,
. card = SAA7164_BOARD_HAUPPAUGE_HVR2250_2 ,
2009-09-03 23:46:16 -03:00
} , {
. subvendor = 0x0070 ,
. subdevice = 0x8851 ,
. card = SAA7164_BOARD_HAUPPAUGE_HVR2250_2 ,
2009-05-09 21:17:28 -03:00
} ,
} ;
const unsigned int saa7164_idcount = ARRAY_SIZE ( saa7164_subids ) ;
void saa7164_card_list ( struct saa7164_dev * dev )
{
int i ;
if ( 0 = = dev - > pci - > subsystem_vendor & &
0 = = dev - > pci - > subsystem_device ) {
printk ( KERN_ERR
" %s: Board has no valid PCIe Subsystem ID and can't \n "
" %s: be autodetected. Pass card=<n> insmod option to \n "
" %s: workaround that. Send complaints to the vendor \n "
" %s: of the TV card. Best regards, \n "
" %s: -- tux \n " ,
dev - > name , dev - > name , dev - > name , dev - > name , dev - > name ) ;
} else {
printk ( KERN_ERR
" %s: Your board isn't known (yet) to the driver. \n "
" %s: Try to pick one of the existing card configs via \n "
" %s: card=<n> insmod option. Updating to the latest \n "
" %s: version might help as well. \n " ,
dev - > name , dev - > name , dev - > name , dev - > name ) ;
}
printk ( KERN_ERR " %s: Here are valid choices for the card=<n> insmod "
" option: \n " , dev - > name ) ;
for ( i = 0 ; i < saa7164_bcount ; i + + )
printk ( KERN_ERR " %s: card=%d -> %s \n " ,
dev - > name , i , saa7164_boards [ i ] . name ) ;
}
/* TODO: clean this define up into the -cards.c structs */
# define PCIEBRIDGE_UNITID 2
void saa7164_gpio_setup ( struct saa7164_dev * dev )
{
switch ( dev - > board ) {
case SAA7164_BOARD_HAUPPAUGE_HVR2200 :
case SAA7164_BOARD_HAUPPAUGE_HVR2200_2 :
case SAA7164_BOARD_HAUPPAUGE_HVR2200_3 :
case SAA7164_BOARD_HAUPPAUGE_HVR2250 :
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2 :
2009-05-11 22:03:07 -03:00
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3 :
2009-05-09 21:17:28 -03:00
/*
GPIO 2 : s5h1411 / tda10048 - 1 demod reset
GPIO 3 : s5h1411 / tda10048 - 2 demod reset
GPIO 7 : IRBlaster Zilog reset
*/
/* Reset parts by going in and out of reset */
saa7164_api_clear_gpiobit ( dev , PCIEBRIDGE_UNITID , 2 ) ;
saa7164_api_clear_gpiobit ( dev , PCIEBRIDGE_UNITID , 3 ) ;
msleep ( 10 ) ;
saa7164_api_set_gpiobit ( dev , PCIEBRIDGE_UNITID , 2 ) ;
saa7164_api_set_gpiobit ( dev , PCIEBRIDGE_UNITID , 3 ) ;
break ;
}
}
static void hauppauge_eeprom ( struct saa7164_dev * dev , u8 * eeprom_data )
{
struct tveeprom tv ;
/* TODO: Assumption: eeprom on bus 0 */
tveeprom_hauppauge_analog ( & dev - > i2c_bus [ 0 ] . i2c_client , & tv ,
eeprom_data ) ;
/* Make sure we support the board model */
switch ( tv . model ) {
case 88001 :
/* Development board - Limit circulation */
/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
* ATSC / QAM ( TDA18271 / S5H1411 ) and basic analog , no IR , FM */
case 88021 :
/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
* ATSC / QAM ( TDA18271 / S5H1411 ) and basic analog , MCE CIR , FM */
break ;
case 88041 :
/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
* ATSC / QAM ( TDA18271 / S5H1411 ) and basic analog , no IR , FM */
break ;
case 88061 :
/* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
* ATSC / QAM ( TDA18271 / S5H1411 ) and basic analog , FM */
break ;
case 89519 :
case 89609 :
/* WinTV-HVR2200 (PCIe, Retail, full-height)
* DVB - T ( TDA18271 / TDA10048 ) and basic analog , no IR */
break ;
case 89619 :
/* WinTV-HVR2200 (PCIe, Retail, half-height)
* DVB - T ( TDA18271 / TDA10048 ) and basic analog , no IR */
break ;
default :
printk ( KERN_ERR " %s: Warning: Unknown Hauppauge model #%d \n " ,
dev - > name , tv . model ) ;
break ;
}
printk ( KERN_INFO " %s: Hauppauge eeprom: model=%d \n " , dev - > name ,
tv . model ) ;
}
void saa7164_card_setup ( struct saa7164_dev * dev )
{
static u8 eeprom [ 256 ] ;
if ( dev - > i2c_bus [ 0 ] . i2c_rc = = 0 ) {
if ( saa7164_api_read_eeprom ( dev , & eeprom [ 0 ] ,
sizeof ( eeprom ) ) < 0 )
return ;
}
switch ( dev - > board ) {
case SAA7164_BOARD_HAUPPAUGE_HVR2200 :
case SAA7164_BOARD_HAUPPAUGE_HVR2200_2 :
case SAA7164_BOARD_HAUPPAUGE_HVR2200_3 :
case SAA7164_BOARD_HAUPPAUGE_HVR2250 :
2009-05-12 16:20:37 -03:00
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2 :
2009-05-11 22:03:07 -03:00
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3 :
2009-05-09 21:17:28 -03:00
hauppauge_eeprom ( dev , & eeprom [ 0 ] ) ;
break ;
}
}
/* With most other drivers, the kernel expects to communicate with subdrivers
* through i2c . This bridge does not allow that , it does not expose any direct
* access to I2C . Instead we have to communicate through the device f / w for
* register access to ' processing units ' . Each unit has a unique
* id , regardless of how the physical implementation occurs across
* the three physical i2c busses . The being said if we want leverge of
* the existing kernel drivers for tuners and demods we have to ' speak i2c ' ,
* to this bridge implements 3 virtual i2c buses . This is a helper function
* for those .
*
* Description : Translate the kernels notion of an i2c address and bus into
* the appropriate unitid .
*/
int saa7164_i2caddr_to_unitid ( struct saa7164_i2c * bus , int addr )
{
/* For a given bus and i2c device address, return the saa7164 unique
* unitid . < 0 on error */
struct saa7164_dev * dev = bus - > dev ;
struct saa7164_unit * unit ;
int i ;
for ( i = 0 ; i < SAA7164_MAX_UNITS ; i + + ) {
unit = & saa7164_boards [ dev - > board ] . unit [ i ] ;
if ( unit - > type = = SAA7164_UNIT_UNDEFINED )
continue ;
if ( ( bus - > nr = = unit - > i2c_bus_nr ) & &
( addr = = unit - > i2c_bus_addr ) )
return unit - > id ;
}
return - 1 ;
}
/* The 7164 API needs to know the i2c register length in advance.
* this is a helper function . Based on a specific chip addr and bus return the
* reg length .
*/
int saa7164_i2caddr_to_reglen ( struct saa7164_i2c * bus , int addr )
{
/* For a given bus and i2c device address, return the
* saa7164 registry address width . < 0 on error
*/
struct saa7164_dev * dev = bus - > dev ;
struct saa7164_unit * unit ;
int i ;
for ( i = 0 ; i < SAA7164_MAX_UNITS ; i + + ) {
unit = & saa7164_boards [ dev - > board ] . unit [ i ] ;
if ( unit - > type = = SAA7164_UNIT_UNDEFINED )
continue ;
if ( ( bus - > nr = = unit - > i2c_bus_nr ) & &
( addr = = unit - > i2c_bus_addr ) )
return unit - > i2c_reg_len ;
}
return - 1 ;
}
/* TODO: implement a 'findeeprom' functio like the above and fix any other
* eeprom related todo ' s in - api . c .
*/
/* Translate a unitid into a x readable device name, for display purposes. */
char * saa7164_unitid_name ( struct saa7164_dev * dev , u8 unitid )
{
char * undefed = " UNDEFINED " ;
char * bridge = " BRIDGE " ;
struct saa7164_unit * unit ;
int i ;
if ( unitid = = 0 )
return bridge ;
for ( i = 0 ; i < SAA7164_MAX_UNITS ; i + + ) {
unit = & saa7164_boards [ dev - > board ] . unit [ i ] ;
if ( unit - > type = = SAA7164_UNIT_UNDEFINED )
continue ;
if ( unitid = = unit - > id )
return unit - > name ;
}
return undefed ;
}