2007-03-29 08:42:30 -03:00
2005-04-16 15:20:36 -07:00
/*
cx88 - i2c . c - - all the i2c code is here
Copyright ( C ) 1996 , 97 , 98 Ralph Metzler ( rjkm @ thp . uni - koeln . de )
2005-11-08 21:37:43 -08:00
& Marcus Metzler ( mocm @ thp . uni - koeln . de )
2005-04-16 15:20:36 -07:00
( c ) 2002 Yurij Sysoev < yurij @ naturesoft . net >
( c ) 1999 - 2003 Gerd Knorr < kraxel @ bytesex . org >
2006-08-21 09:04:14 -03:00
( c ) 2005 Mauro Carvalho Chehab < mchehab @ infradead . org >
- Multituner support and i2c address binding
2005-04-16 15:20:36 -07:00
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/module.h>
# include <linux/init.h>
# include <asm/io.h>
# include "cx88.h"
2006-01-09 15:32:31 -02:00
# include <media/v4l2-common.h>
2005-04-16 15:20:36 -07:00
2008-04-22 14:41:48 -03:00
static unsigned int i2c_debug ;
2005-04-16 15:20:36 -07:00
module_param ( i2c_debug , int , 0644 ) ;
MODULE_PARM_DESC ( i2c_debug , " enable debug messages [i2c] " ) ;
2008-04-22 14:41:48 -03:00
static unsigned int i2c_scan ;
2005-04-16 15:20:36 -07:00
module_param ( i2c_scan , int , 0444 ) ;
MODULE_PARM_DESC ( i2c_scan , " scan i2c bus at insmod time " ) ;
2006-09-06 19:04:28 -03:00
static unsigned int i2c_udelay = 5 ;
module_param ( i2c_udelay , int , 0644 ) ;
MODULE_PARM_DESC ( i2c_udelay , " i2c delay at insmod time, in usecs "
" (should be 5 or higher). Lower value means higher bus speed. " ) ;
2005-04-16 15:20:36 -07:00
# define dprintk(level,fmt, arg...) if (i2c_debug >= level) \
printk ( KERN_DEBUG " %s: " fmt , core - > name , # # arg )
/* ----------------------------------------------------------------------- */
2005-05-01 08:59:29 -07:00
static void cx8800_bit_setscl ( void * data , int state )
2005-04-16 15:20:36 -07:00
{
struct cx88_core * core = data ;
if ( state )
core - > i2c_state | = 0x02 ;
else
core - > i2c_state & = ~ 0x02 ;
cx_write ( MO_I2C , core - > i2c_state ) ;
cx_read ( MO_I2C ) ;
}
2005-05-01 08:59:29 -07:00
static void cx8800_bit_setsda ( void * data , int state )
2005-04-16 15:20:36 -07:00
{
struct cx88_core * core = data ;
if ( state )
core - > i2c_state | = 0x01 ;
else
core - > i2c_state & = ~ 0x01 ;
cx_write ( MO_I2C , core - > i2c_state ) ;
cx_read ( MO_I2C ) ;
}
static int cx8800_bit_getscl ( void * data )
{
struct cx88_core * core = data ;
u32 state ;
state = cx_read ( MO_I2C ) ;
return state & 0x02 ? 1 : 0 ;
}
static int cx8800_bit_getsda ( void * data )
{
struct cx88_core * core = data ;
u32 state ;
state = cx_read ( MO_I2C ) ;
return state & 0x01 ;
}
/* ----------------------------------------------------------------------- */
2007-07-01 18:37:51 -03:00
static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
2005-04-16 15:20:36 -07:00
. setsda = cx8800_bit_setsda ,
. setscl = cx8800_bit_setscl ,
. getsda = cx8800_bit_getsda ,
. getscl = cx8800_bit_getscl ,
. udelay = 16 ,
. timeout = 200 ,
} ;
/* ----------------------------------------------------------------------- */
2010-08-25 09:50:20 -03:00
static const char * const i2c_devs [ 128 ] = {
2005-07-27 11:46:00 -07:00
[ 0x1c > > 1 ] = " lgdt330x " ,
2005-04-16 15:20:36 -07:00
[ 0x86 > > 1 ] = " tda9887/cx22702 " ,
[ 0xa0 > > 1 ] = " eeprom " ,
[ 0xc0 > > 1 ] = " tuner (analog) " ,
[ 0xc2 > > 1 ] = " tuner (analog/dvb) " ,
2008-01-05 16:53:01 -03:00
[ 0xc8 > > 1 ] = " xc5000 " ,
2005-04-16 15:20:36 -07:00
} ;
2010-08-25 09:50:20 -03:00
static void do_i2c_scan ( const char * name , struct i2c_client * c )
2005-04-16 15:20:36 -07:00
{
unsigned char buf ;
int i , rc ;
2007-03-29 08:42:30 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( i2c_devs ) ; i + + ) {
2005-04-16 15:20:36 -07:00
c - > addr = i ;
rc = i2c_master_recv ( c , & buf , 0 ) ;
if ( rc < 0 )
continue ;
printk ( " %s: i2c scan: found device @ 0x%x [%s] \n " ,
name , i < < 1 , i2c_devs [ i ] ? i2c_devs [ i ] : " ??? " ) ;
}
}
/* init + register i2c algo-bit adapter */
int cx88_i2c_init ( struct cx88_core * core , struct pci_dev * pci )
{
2006-09-06 19:04:28 -03:00
/* Prevents usage of invalid delay values */
if ( i2c_udelay < 5 )
i2c_udelay = 5 ;
2005-04-16 15:20:36 -07:00
memcpy ( & core - > i2c_algo , & cx8800_i2c_algo_template ,
sizeof ( core - > i2c_algo ) ) ;
core - > i2c_adap . dev . parent = & pci - > dev ;
strlcpy ( core - > i2c_adap . name , core - > name , sizeof ( core - > i2c_adap . name ) ) ;
2007-07-01 18:37:51 -03:00
core - > i2c_adap . owner = THIS_MODULE ;
core - > i2c_algo . udelay = i2c_udelay ;
2005-11-08 21:37:43 -08:00
core - > i2c_algo . data = core ;
2009-03-14 12:40:51 -03:00
i2c_set_adapdata ( & core - > i2c_adap , & core - > v4l2_dev ) ;
2005-11-08 21:37:43 -08:00
core - > i2c_adap . algo_data = & core - > i2c_algo ;
core - > i2c_client . adapter = & core - > i2c_adap ;
2007-07-01 18:37:51 -03:00
strlcpy ( core - > i2c_client . name , " cx88xx internal " , I2C_NAME_SIZE ) ;
2005-04-16 15:20:36 -07:00
cx8800_bit_setscl ( core , 1 ) ;
cx8800_bit_setsda ( core , 1 ) ;
core - > i2c_rc = i2c_bit_add_bus ( & core - > i2c_adap ) ;
if ( 0 = = core - > i2c_rc ) {
2008-09-22 01:46:26 -03:00
static u8 tuner_data [ ] =
{ 0x0b , 0xdc , 0x86 , 0x52 } ;
static struct i2c_msg tuner_msg =
{ . flags = 0 , . addr = 0xc2 > > 1 , . buf = tuner_data , . len = 4 } ;
2005-04-16 15:20:36 -07:00
dprintk ( 1 , " i2c register ok \n " ) ;
2008-09-22 01:46:26 -03:00
switch ( core - > boardnr ) {
case CX88_BOARD_HAUPPAUGE_HVR1300 :
case CX88_BOARD_HAUPPAUGE_HVR3000 :
case CX88_BOARD_HAUPPAUGE_HVR4000 :
printk ( " %s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner \n " ,
core - > name ) ;
i2c_transfer ( core - > i2c_client . adapter , & tuner_msg , 1 ) ;
break ;
default :
break ;
}
2005-04-16 15:20:36 -07:00
if ( i2c_scan )
do_i2c_scan ( core - > name , & core - > i2c_client ) ;
} else
printk ( " %s: i2c register FAILED \n " , core - > name ) ;
2009-05-13 16:48:50 -03:00
2010-06-28 12:55:43 -03:00
return core - > i2c_rc ;
}