2019-05-20 09:19:02 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07: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-08 21:37:43 -08:00
& Marcus Metzler ( mocm @ thp . uni - koeln . de )
2005-04-16 15:20:36 -07:00
( c ) 1999 - 2003 Gerd Knorr < kraxel @ bytesex . org >
MAINTAINERS & files: Canonize the e-mails I use at files
From now on, I'll start using my @kernel.org as my development e-mail.
As such, let's remove the entries that point to the old
mchehab@s-opensource.com at MAINTAINERS file.
For the files written with a copyright with mchehab@s-opensource,
let's keep Samsung on their names, using mchehab+samsung@kernel.org,
in order to keep pointing to my employer, with sponsors the work.
For the files written before I join Samsung (on July, 4 2013),
let's just use mchehab@kernel.org.
For bug reports, we can simply point to just kernel.org, as
this will reach my mchehab+samsung inbox anyway.
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Brian Warner <brian.warner@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2018-04-25 05:34:48 -04:00
( c ) 2005 Mauro Carvalho Chehab < mchehab @ kernel . org >
2006-09-06 19:04:28 -03:00
- Multituner support and i2c address binding
2005-04-16 15:20:36 -07:00
*/
2011-08-21 19:56:48 -03:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2005-04-16 15:20:36 -07:00
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
# include "bttvp.h"
2006-01-09 15:32:31 -02:00
# include <media/v4l2-common.h>
2006-01-09 15:25:20 -02:00
# include <linux/jiffies.h>
# include <asm/io.h>
2005-04-16 15:20:36 -07:00
2006-01-13 14:10:19 -02:00
static int i2c_debug ;
static int i2c_hw ;
static int i2c_scan ;
2005-04-16 15:20:36 -07:00
module_param ( i2c_debug , int , 0644 ) ;
2009-12-10 16:54:48 -03:00
MODULE_PARM_DESC ( i2c_debug , " configure i2c debug level " ) ;
2005-04-16 15:20:36 -07:00
module_param ( i2c_hw , int , 0444 ) ;
[media] bt8xx: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:02 -02:00
MODULE_PARM_DESC ( i2c_hw , " force use of hardware i2c support, instead of software bitbang " ) ;
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 , 0444 ) ;
[media] bt8xx: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:02 -02:00
MODULE_PARM_DESC ( i2c_udelay , " soft i2c delay at insmod time, in usecs (should be 5 or higher). Lower value means higher bus speed. " ) ;
2006-09-06 19:04:28 -03:00
2005-04-16 15:20:36 -07: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 ;
}
2017-08-21 09:33:32 -04:00
static const struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
2005-04-16 15:20:36 -07: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-05 16:16:01 -07:00
/* timeout */
if ( wait_event_interruptible_timeout ( btv - > i2c_queue ,
2010-08-05 17:29:55 -03:00
btv - > i2c_done , msecs_to_jiffies ( 85 ) ) = = - ERESTARTSYS )
rc = - EIO ;
2005-04-16 15:20:36 -07: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-21 19:56:48 -03:00
pr_cont ( " <W %02x %02x " , msg - > addr < < 1 , msg - > buf [ 0 ] ) ;
2005-04-16 15:20:36 -07: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-21 19:56:48 -03:00
if ( i2c_debug )
pr_cont ( " %02x " , msg - > buf [ cnt ] ) ;
2005-04-16 15:20:36 -07:00
}
2012-12-17 08:53:54 -03:00
if ( i2c_debug & & ! ( xmit & BT878_I2C_NOSTOP ) )
2011-08-21 19:56:48 -03:00
pr_cont ( " > \n " ) ;
2005-04-16 15:20:36 -07:00
return msg - > len ;
eio :
retval = - EIO ;
err :
if ( i2c_debug )
2011-08-21 19:56:48 -03:00
pr_cont ( " ERR: %d \n " , retval ) ;
2005-04-16 15:20:36 -07: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-21 19:56:48 -03:00
for ( cnt = 0 ; cnt < msg - > len ; cnt + + ) {
2005-04-16 15:20:36 -07: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-21 19:56:48 -03:00
if ( i2c_debug ) {
if ( ! ( xmit & BT878_I2C_NOSTART ) )
pr_cont ( " <R %02x " , ( msg - > addr < < 1 ) + 1 ) ;
}
2005-04-16 15:20:36 -07: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-21 19:56:48 -03:00
pr_cont ( " =%02x " , msg - > buf [ cnt ] ) ;
2005-04-16 15:20:36 -07:00
}
2011-08-21 19:56:48 -03:00
if ( i2c_debug & & ! ( xmit & BT878_I2C_NOSTOP ) )
pr_cont ( " > \n " ) ;
2005-04-16 15:20:36 -07:00
}
2011-08-21 19:56:48 -03:00
2005-04-16 15:20:36 -07:00
return msg - > len ;
eio :
retval = - EIO ;
err :
if ( i2c_debug )
2011-08-21 19:56:48 -03:00
pr_cont ( " ERR: %d \n " , retval ) ;
2005-11-08 21:37:43 -08:00
return retval ;
2005-04-16 15:20:36 -07:00
}
static int bttv_i2c_xfer ( struct i2c_adapter * i2c_adap , struct i2c_msg * msgs , int num )
{
2009-03-14 12:36:54 -03:00
struct v4l2_device * v4l2_dev = i2c_get_adapdata ( i2c_adap ) ;
struct bttv * btv = to_bttv ( v4l2_dev ) ;
2005-04-16 15:20:36 -07:00
int retval = 0 ;
int i ;
if ( i2c_debug )
2011-08-21 19:56:48 -03:00
pr_debug ( " bt-i2c: " ) ;
2005-04-16 15:20:36 -07: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 12:20:18 -03:00
static const struct i2c_algorithm bttv_algo = {
2005-04-16 15:20:36 -07: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-08 21:37:43 -08:00
unsigned char buffer = 0 ;
2005-04-16 15:20:36 -07:00
if ( 0 ! = btv - > i2c_rc )
return - 1 ;
if ( bttv_verbose & & NULL ! = probe_for )
2011-08-21 19:56:48 -03:00
pr_info ( " %d: i2c: checking for %s @ 0x%02x... " ,
btv - > c . nr , probe_for , addr ) ;
2005-11-08 21:37:43 -08:00
btv - > i2c_client . addr = addr > > 1 ;
if ( 1 ! = i2c_master_recv ( & btv - > i2c_client , & buffer , 1 ) ) {
2005-04-16 15:20:36 -07:00
if ( NULL ! = probe_for ) {
if ( bttv_verbose )
2011-08-21 19:56:48 -03:00
pr_cont ( " not found \n " ) ;
2005-04-16 15:20:36 -07:00
} else
2011-08-21 19:56:48 -03:00
pr_warn ( " %d: i2c read 0x%x: error \n " ,
btv - > c . nr , addr ) ;
2005-11-08 21:37:43 -08:00
return - 1 ;
2005-04-16 15:20:36 -07:00
}
if ( bttv_verbose & & NULL ! = probe_for )
2011-08-21 19:56:48 -03:00
pr_cont ( " found \n " ) ;
2005-11-08 21:37:43 -08:00
return buffer ;
2005-04-16 15:20:36 -07:00
}
/* write I2C */
int bttv_I2CWrite ( struct bttv * btv , unsigned char addr , unsigned char b1 ,
2005-11-08 21:37:43 -08:00
unsigned char b2 , int both )
2005-04-16 15:20:36 -07:00
{
2005-11-08 21:37:43 -08:00
unsigned char buffer [ 2 ] ;
int bytes = both ? 2 : 1 ;
2005-04-16 15:20:36 -07:00
if ( 0 ! = btv - > i2c_rc )
return - 1 ;
2005-11-08 21:37:43 -08: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-16 15:20:36 -07:00
return - 1 ;
2005-11-08 21:37:43 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
/* read EEPROM content */
2012-12-21 13:17:53 -08:00
void bttv_readee ( struct bttv * btv , unsigned char * eedata , int addr )
2005-04-16 15:20:36 -07:00
{
2005-05-25 12:31:26 -07:00
memset ( eedata , 0 , 256 ) ;
if ( 0 ! = btv - > i2c_rc )
return ;
2005-04-16 15:20:36 -07:00
btv - > i2c_client . addr = addr > > 1 ;
tveeprom_read ( & btv - > i2c_client , eedata , 256 ) ;
}
static char * i2c_devs [ 128 ] = {
2005-09-09 13:03:39 -07:00
[ 0x1c > > 1 ] = " lgdt330x " ,
2005-04-16 15:20:36 -07: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 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 ;
2011-08-21 19:56:48 -03:00
pr_info ( " %s: i2c scan: found device @ 0x%x [%s] \n " ,
name , i < < 1 , i2c_devs [ i ] ? i2c_devs [ i ] : " ??? " ) ;
2005-04-16 15:20:36 -07:00
}
}
2011-11-09 13:27:53 -03:00
/* init + register i2c adapter */
2012-12-21 13:17:53 -08:00
int init_bttv_i2c ( struct bttv * btv )
2005-04-16 15:20:36 -07:00
{
2018-09-10 08:19:14 -04:00
strscpy ( btv - > i2c_client . name , " bttv internal " , I2C_NAME_SIZE ) ;
2005-04-16 15:20:36 -07:00
if ( i2c_hw )
btv - > use_i2c_hw = 1 ;
if ( btv - > use_i2c_hw ) {
/* bt878 */
2018-09-10 08:19:14 -04:00
strscpy ( btv - > c . i2c_adap . name , " bt878 " ,
2008-06-15 12:20:18 -03:00
sizeof ( btv - > c . i2c_adap . name ) ) ;
btv - > c . i2c_adap . algo = & bttv_algo ;
2005-04-16 15:20:36 -07:00
} else {
/* bt848 */
2006-09-06 19:04:28 -03:00
/* Prevents usage of invalid delay values */
if ( i2c_udelay < 5 )
i2c_udelay = 5 ;
2018-09-10 08:19:14 -04:00
strscpy ( btv - > c . i2c_adap . name , " bttv " ,
2008-06-15 12:20:18 -03:00
sizeof ( btv - > c . i2c_adap . name ) ) ;
2012-10-23 15:57:22 -03:00
btv - > i2c_algo = bttv_i2c_algo_bit_template ;
2008-06-15 12:20:18 -03:00
btv - > i2c_algo . udelay = i2c_udelay ;
2005-04-16 15:20:36 -07:00
btv - > i2c_algo . data = btv ;
btv - > c . i2c_adap . algo_data = & btv - > i2c_algo ;
}
2008-06-15 12:20:18 -03:00
btv - > c . i2c_adap . owner = THIS_MODULE ;
2005-04-16 15:20:36 -07: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 12:36:54 -03:00
i2c_set_adapdata ( & btv - > c . i2c_adap , & btv - > c . v4l2_dev ) ;
2005-11-08 21:37:43 -08:00
btv - > i2c_client . adapter = & btv - > c . i2c_adap ;
2005-04-16 15:20:36 -07: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 12:36:54 -03:00
do_i2c_scan ( btv - > c . v4l2_dev . name , & btv - > i2c_client ) ;
2009-05-13 16:48:50 -03:00
2010-02-19 00:18:41 -03:00
return btv - > i2c_rc ;
}
2013-02-17 09:41:29 -03:00
int fini_bttv_i2c ( struct bttv * btv )
{
2013-05-02 14:38:53 -07:00
if ( btv - > i2c_rc = = 0 )
i2c_del_adapter ( & btv - > c . i2c_adap ) ;
2013-02-17 09:41:29 -03:00
2013-05-02 14:38:53 -07:00
return 0 ;
2013-02-17 09:41:29 -03:00
}