2005-04-17 02:20:36 +04:00
/*
bttv - i2c . c - - all the i2c code is here
bttv - Bt848 frame grabber driver
Copyright ( C ) 1996 , 97 , 98 Ralph Metzler ( rjkm @ thp . uni - koeln . de )
2005-11-09 08:37:43 +03:00
& Marcus Metzler ( mocm @ thp . uni - koeln . de )
2005-04-17 02:20:36 +04:00
( c ) 1999 - 2003 Gerd Knorr < kraxel @ bytesex . org >
2006-09-07 02:04:28 +04:00
( c ) 2005 Mauro Carvalho Chehab < mchehab @ infradead . org >
- Multituner support and i2c address binding
2005-04-17 02:20:36 +04: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 .
*/
2011-08-22 02:56:48 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2005-04-17 02:20:36 +04:00
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
# include "bttvp.h"
2006-01-09 20:32:31 +03:00
# include <media/v4l2-common.h>
2006-01-09 20:25:20 +03:00
# include <linux/jiffies.h>
# include <asm/io.h>
2005-04-17 02:20:36 +04:00
2006-01-13 19:10:19 +03:00
static int i2c_debug ;
static int i2c_hw ;
static int i2c_scan ;
2005-04-17 02:20:36 +04:00
module_param ( i2c_debug , int , 0644 ) ;
2009-12-10 22:54:48 +03:00
MODULE_PARM_DESC ( i2c_debug , " configure i2c debug level " ) ;
2005-04-17 02:20:36 +04:00
module_param ( i2c_hw , int , 0444 ) ;
2006-09-07 02:04:28 +04:00
MODULE_PARM_DESC ( i2c_hw , " force use of hardware i2c support, "
" instead of software bitbang " ) ;
2005-04-17 02:20:36 +04:00
module_param ( i2c_scan , int , 0444 ) ;
MODULE_PARM_DESC ( i2c_scan , " scan i2c bus at insmod time " ) ;
2006-09-07 02:04:28 +04:00
static unsigned int i2c_udelay = 5 ;
module_param ( i2c_udelay , int , 0444 ) ;
MODULE_PARM_DESC ( i2c_udelay , " soft i2c delay at insmod time, in usecs "
" (should be 5 or higher). Lower value means higher bus speed. " ) ;
2005-04-17 02:20:36 +04:00
/* ----------------------------------------------------------------------- */
/* I2C functions - bitbanging adapter (software i2c) */
static void bttv_bit_setscl ( void * data , int state )
{
struct bttv * btv = ( struct bttv * ) data ;
if ( state )
btv - > i2c_state | = 0x02 ;
else
btv - > i2c_state & = ~ 0x02 ;
btwrite ( btv - > i2c_state , BT848_I2C ) ;
btread ( BT848_I2C ) ;
}
static void bttv_bit_setsda ( void * data , int state )
{
struct bttv * btv = ( struct bttv * ) data ;
if ( state )
btv - > i2c_state | = 0x01 ;
else
btv - > i2c_state & = ~ 0x01 ;
btwrite ( btv - > i2c_state , BT848_I2C ) ;
btread ( BT848_I2C ) ;
}
static int bttv_bit_getscl ( void * data )
{
struct bttv * btv = ( struct bttv * ) data ;
int state ;
state = btread ( BT848_I2C ) & 0x02 ? 1 : 0 ;
return state ;
}
static int bttv_bit_getsda ( void * data )
{
struct bttv * btv = ( struct bttv * ) data ;
int state ;
state = btread ( BT848_I2C ) & 0x01 ;
return state ;
}
2008-06-15 19:20:18 +04:00
static struct i2c_algo_bit_data __devinitdata bttv_i2c_algo_bit_template = {
2005-04-17 02:20:36 +04:00
. setsda = bttv_bit_setsda ,
. setscl = bttv_bit_setscl ,
. getsda = bttv_bit_getsda ,
. getscl = bttv_bit_getscl ,
. udelay = 16 ,
. timeout = 200 ,
} ;
/* ----------------------------------------------------------------------- */
/* I2C functions - hardware i2c */
static u32 functionality ( struct i2c_adapter * adap )
{
return I2C_FUNC_SMBUS_EMUL ;
}
static int
bttv_i2c_wait_done ( struct bttv * btv )
{
int rc = 0 ;
2005-05-06 03:16:01 +04:00
/* timeout */
if ( wait_event_interruptible_timeout ( btv - > i2c_queue ,
2010-08-06 00:29:55 +04:00
btv - > i2c_done , msecs_to_jiffies ( 85 ) ) = = - ERESTARTSYS )
rc = - EIO ;
2005-04-17 02:20:36 +04:00
if ( btv - > i2c_done & BT848_INT_RACK )
rc = 1 ;
btv - > i2c_done = 0 ;
return rc ;
}
# define I2C_HW (BT878_I2C_MODE | BT848_I2C_SYNC |\
BT848_I2C_SCL | BT848_I2C_SDA )
static int
bttv_i2c_sendbytes ( struct bttv * btv , const struct i2c_msg * msg , int last )
{
u32 xmit ;
int retval , cnt ;
/* sanity checks */
if ( 0 = = msg - > len )
return - EINVAL ;
/* start, address + first byte */
xmit = ( msg - > addr < < 25 ) | ( msg - > buf [ 0 ] < < 16 ) | I2C_HW ;
if ( msg - > len > 1 | | ! last )
xmit | = BT878_I2C_NOSTOP ;
btwrite ( xmit , BT848_I2C ) ;
retval = bttv_i2c_wait_done ( btv ) ;
if ( retval < 0 )
goto err ;
if ( retval = = 0 )
goto eio ;
if ( i2c_debug ) {
2011-08-22 02:56:48 +04:00
pr_cont ( " <W %02x %02x " , msg - > addr < < 1 , msg - > buf [ 0 ] ) ;
2005-04-17 02:20:36 +04:00
}
for ( cnt = 1 ; cnt < msg - > len ; cnt + + ) {
/* following bytes */
xmit = ( msg - > buf [ cnt ] < < 24 ) | I2C_HW | BT878_I2C_NOSTART ;
if ( cnt < msg - > len - 1 | | ! last )
xmit | = BT878_I2C_NOSTOP ;
btwrite ( xmit , BT848_I2C ) ;
retval = bttv_i2c_wait_done ( btv ) ;
if ( retval < 0 )
goto err ;
if ( retval = = 0 )
goto eio ;
2011-08-22 02:56:48 +04:00
if ( i2c_debug )
pr_cont ( " %02x " , msg - > buf [ cnt ] ) ;
2005-04-17 02:20:36 +04:00
}
2011-08-22 02:56:48 +04:00
if ( ! ( xmit & BT878_I2C_NOSTOP ) )
pr_cont ( " > \n " ) ;
2005-04-17 02:20:36 +04:00
return msg - > len ;
eio :
retval = - EIO ;
err :
if ( i2c_debug )
2011-08-22 02:56:48 +04:00
pr_cont ( " ERR: %d \n " , retval ) ;
2005-04-17 02:20:36 +04:00
return retval ;
}
static int
bttv_i2c_readbytes ( struct bttv * btv , const struct i2c_msg * msg , int last )
{
u32 xmit ;
u32 cnt ;
int retval ;
2011-08-22 02:56:48 +04:00
for ( cnt = 0 ; cnt < msg - > len ; cnt + + ) {
2005-04-17 02:20:36 +04:00
xmit = ( msg - > addr < < 25 ) | ( 1 < < 24 ) | I2C_HW ;
if ( cnt < msg - > len - 1 )
xmit | = BT848_I2C_W3B ;
if ( cnt < msg - > len - 1 | | ! last )
xmit | = BT878_I2C_NOSTOP ;
if ( cnt )
xmit | = BT878_I2C_NOSTART ;
2011-08-22 02:56:48 +04:00
if ( i2c_debug ) {
if ( ! ( xmit & BT878_I2C_NOSTART ) )
pr_cont ( " <R %02x " , ( msg - > addr < < 1 ) + 1 ) ;
}
2005-04-17 02:20:36 +04:00
btwrite ( xmit , BT848_I2C ) ;
retval = bttv_i2c_wait_done ( btv ) ;
if ( retval < 0 )
goto err ;
if ( retval = = 0 )
goto eio ;
msg - > buf [ cnt ] = ( ( u32 ) btread ( BT848_I2C ) > > 8 ) & 0xff ;
if ( i2c_debug ) {
2011-08-22 02:56:48 +04:00
pr_cont ( " =%02x " , msg - > buf [ cnt ] ) ;
2005-04-17 02:20:36 +04:00
}
2011-08-22 02:56:48 +04:00
if ( i2c_debug & & ! ( xmit & BT878_I2C_NOSTOP ) )
pr_cont ( " > \n " ) ;
2005-04-17 02:20:36 +04:00
}
2011-08-22 02:56:48 +04:00
2005-04-17 02:20:36 +04:00
return msg - > len ;
eio :
retval = - EIO ;
err :
if ( i2c_debug )
2011-08-22 02:56:48 +04:00
pr_cont ( " ERR: %d \n " , retval ) ;
2005-11-09 08:37:43 +03:00
return retval ;
2005-04-17 02:20:36 +04:00
}
static int bttv_i2c_xfer ( struct i2c_adapter * i2c_adap , struct i2c_msg * msgs , int num )
{
2009-03-14 18:36:54 +03:00
struct v4l2_device * v4l2_dev = i2c_get_adapdata ( i2c_adap ) ;
struct bttv * btv = to_bttv ( v4l2_dev ) ;
2005-04-17 02:20:36 +04:00
int retval = 0 ;
int i ;
if ( i2c_debug )
2011-08-22 02:56:48 +04:00
pr_debug ( " bt-i2c: " ) ;
2005-04-17 02:20:36 +04:00
btwrite ( BT848_INT_I2CDONE | BT848_INT_RACK , BT848_INT_STAT ) ;
for ( i = 0 ; i < num ; i + + ) {
if ( msgs [ i ] . flags & I2C_M_RD ) {
/* read */
retval = bttv_i2c_readbytes ( btv , & msgs [ i ] , i + 1 = = num ) ;
if ( retval < 0 )
goto err ;
} else {
/* write */
retval = bttv_i2c_sendbytes ( btv , & msgs [ i ] , i + 1 = = num ) ;
if ( retval < 0 )
goto err ;
}
}
return num ;
err :
return retval ;
}
2008-06-15 19:20:18 +04:00
static const struct i2c_algorithm bttv_algo = {
2005-04-17 02:20:36 +04:00
. master_xfer = bttv_i2c_xfer ,
. functionality = functionality ,
} ;
/* ----------------------------------------------------------------------- */
/* I2C functions - common stuff */
/* read I2C */
int bttv_I2CRead ( struct bttv * btv , unsigned char addr , char * probe_for )
{
2005-11-09 08:37:43 +03:00
unsigned char buffer = 0 ;
2005-04-17 02:20:36 +04:00
if ( 0 ! = btv - > i2c_rc )
return - 1 ;
if ( bttv_verbose & & NULL ! = probe_for )
2011-08-22 02:56:48 +04:00
pr_info ( " %d: i2c: checking for %s @ 0x%02x... " ,
btv - > c . nr , probe_for , addr ) ;
2005-11-09 08:37:43 +03:00
btv - > i2c_client . addr = addr > > 1 ;
if ( 1 ! = i2c_master_recv ( & btv - > i2c_client , & buffer , 1 ) ) {
2005-04-17 02:20:36 +04:00
if ( NULL ! = probe_for ) {
if ( bttv_verbose )
2011-08-22 02:56:48 +04:00
pr_cont ( " not found \n " ) ;
2005-04-17 02:20:36 +04:00
} else
2011-08-22 02:56:48 +04:00
pr_warn ( " %d: i2c read 0x%x: error \n " ,
btv - > c . nr , addr ) ;
2005-11-09 08:37:43 +03:00
return - 1 ;
2005-04-17 02:20:36 +04:00
}
if ( bttv_verbose & & NULL ! = probe_for )
2011-08-22 02:56:48 +04:00
pr_cont ( " found \n " ) ;
2005-11-09 08:37:43 +03:00
return buffer ;
2005-04-17 02:20:36 +04:00
}
/* write I2C */
int bttv_I2CWrite ( struct bttv * btv , unsigned char addr , unsigned char b1 ,
2005-11-09 08:37:43 +03:00
unsigned char b2 , int both )
2005-04-17 02:20:36 +04:00
{
2005-11-09 08:37:43 +03:00
unsigned char buffer [ 2 ] ;
int bytes = both ? 2 : 1 ;
2005-04-17 02:20:36 +04:00
if ( 0 ! = btv - > i2c_rc )
return - 1 ;
2005-11-09 08:37:43 +03:00
btv - > i2c_client . addr = addr > > 1 ;
buffer [ 0 ] = b1 ;
buffer [ 1 ] = b2 ;
if ( bytes ! = i2c_master_send ( & btv - > i2c_client , buffer , bytes ) )
2005-04-17 02:20:36 +04:00
return - 1 ;
2005-11-09 08:37:43 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/* read EEPROM content */
void __devinit bttv_readee ( struct bttv * btv , unsigned char * eedata , int addr )
{
2005-05-25 23:31:26 +04:00
memset ( eedata , 0 , 256 ) ;
if ( 0 ! = btv - > i2c_rc )
return ;
2005-04-17 02:20:36 +04:00
btv - > i2c_client . addr = addr > > 1 ;
tveeprom_read ( & btv - > i2c_client , eedata , 256 ) ;
}
static char * i2c_devs [ 128 ] = {
2005-09-10 00:03:39 +04:00
[ 0x1c > > 1 ] = " lgdt330x " ,
2005-04-17 02:20:36 +04:00
[ 0x30 > > 1 ] = " IR (hauppauge) " ,
[ 0x80 > > 1 ] = " msp34xx " ,
[ 0x86 > > 1 ] = " tda9887 " ,
[ 0xa0 > > 1 ] = " eeprom " ,
[ 0xc0 > > 1 ] = " tuner (analog) " ,
[ 0xc2 > > 1 ] = " tuner (analog) " ,
} ;
static void do_i2c_scan ( char * name , struct i2c_client * c )
{
unsigned char buf ;
int i , rc ;
2007-03-29 15:42:30 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( i2c_devs ) ; i + + ) {
2005-04-17 02:20:36 +04:00
c - > addr = i ;
rc = i2c_master_recv ( c , & buf , 0 ) ;
if ( rc < 0 )
continue ;
2011-08-22 02:56:48 +04:00
pr_info ( " %s: i2c scan: found device @ 0x%x [%s] \n " ,
name , i < < 1 , i2c_devs [ i ] ? i2c_devs [ i ] : " ??? " ) ;
2005-04-17 02:20:36 +04:00
}
}
2011-11-09 20:27:53 +04:00
/* init + register i2c adapter */
2005-04-17 02:20:36 +04:00
int __devinit init_bttv_i2c ( struct bttv * btv )
{
2008-06-15 19:20:18 +04:00
strlcpy ( btv - > i2c_client . name , " bttv internal " , I2C_NAME_SIZE ) ;
2005-04-17 02:20:36 +04:00
if ( i2c_hw )
btv - > use_i2c_hw = 1 ;
if ( btv - > use_i2c_hw ) {
/* bt878 */
2008-06-15 19:20:18 +04:00
strlcpy ( btv - > c . i2c_adap . name , " bt878 " ,
sizeof ( btv - > c . i2c_adap . name ) ) ;
btv - > c . i2c_adap . algo = & bttv_algo ;
2005-04-17 02:20:36 +04:00
} else {
/* bt848 */
2006-09-07 02:04:28 +04:00
/* Prevents usage of invalid delay values */
if ( i2c_udelay < 5 )
i2c_udelay = 5 ;
2008-06-15 19:20:18 +04:00
strlcpy ( btv - > c . i2c_adap . name , " bttv " ,
sizeof ( btv - > c . i2c_adap . name ) ) ;
2005-04-17 02:20:36 +04:00
memcpy ( & btv - > i2c_algo , & bttv_i2c_algo_bit_template ,
sizeof ( bttv_i2c_algo_bit_template ) ) ;
2008-06-15 19:20:18 +04:00
btv - > i2c_algo . udelay = i2c_udelay ;
2005-04-17 02:20:36 +04:00
btv - > i2c_algo . data = btv ;
btv - > c . i2c_adap . algo_data = & btv - > i2c_algo ;
}
2008-06-15 19:20:18 +04:00
btv - > c . i2c_adap . owner = THIS_MODULE ;
2005-04-17 02:20:36 +04:00
btv - > c . i2c_adap . dev . parent = & btv - > c . pci - > dev ;
snprintf ( btv - > c . i2c_adap . name , sizeof ( btv - > c . i2c_adap . name ) ,
" bt%d #%d [%s] " , btv - > id , btv - > c . nr ,
btv - > use_i2c_hw ? " hw " : " sw " ) ;
2009-03-14 18:36:54 +03:00
i2c_set_adapdata ( & btv - > c . i2c_adap , & btv - > c . v4l2_dev ) ;
2005-11-09 08:37:43 +03:00
btv - > i2c_client . adapter = & btv - > c . i2c_adap ;
2005-04-17 02:20:36 +04:00
if ( btv - > use_i2c_hw ) {
btv - > i2c_rc = i2c_add_adapter ( & btv - > c . i2c_adap ) ;
} else {
bttv_bit_setscl ( btv , 1 ) ;
bttv_bit_setsda ( btv , 1 ) ;
btv - > i2c_rc = i2c_bit_add_bus ( & btv - > c . i2c_adap ) ;
}
if ( 0 = = btv - > i2c_rc & & i2c_scan )
2009-03-14 18:36:54 +03:00
do_i2c_scan ( btv - > c . v4l2_dev . name , & btv - > i2c_client ) ;
2009-05-13 23:48:50 +04:00
2010-02-19 06:18:41 +03:00
return btv - > i2c_rc ;
}