2006-12-04 08:31:14 -03:00
/*
2007-04-14 16:23:49 -03:00
* usbvision_i2c . c
2006-12-04 08:30:53 -03:00
* i2c algorithm for USB - I2C Bridges
*
2007-04-14 16:23:49 -03:00
* Copyright ( c ) 1999 - 2007 Joerg Heckenbach < joerg @ heckenbach - aw . de >
2006-12-04 08:30:53 -03:00
* Dwaine Garden < dwainegarden @ rogers . com >
*
* This module is part of usbvision driver project .
* Updates to driver completed by Dwaine P . Garden
*
* 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 .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/init.h>
2010-12-29 13:53:21 -03:00
# include <linux/uaccess.h>
2006-12-04 08:30:53 -03:00
# include <linux/ioport.h>
# include <linux/errno.h>
# include <linux/usb.h>
# include <linux/i2c.h>
2006-12-04 08:31:45 -03:00
# include "usbvision.h"
2006-12-04 08:30:53 -03:00
2010-12-29 13:53:21 -03:00
# define DBG_I2C (1 << 0)
2006-12-04 08:30:53 -03:00
2008-04-22 14:41:48 -03:00
static int i2c_debug ;
2006-12-04 08:31:45 -03:00
2010-12-29 13:53:21 -03:00
module_param ( i2c_debug , int , 0644 ) ; /* debug_i2c_usb mode of the device driver */
2006-12-04 08:31:45 -03:00
MODULE_PARM_DESC ( i2c_debug , " enable debug messages [i2c] " ) ;
2006-12-04 08:30:53 -03:00
2008-04-04 21:00:57 -03:00
# define PDEBUG(level, fmt, args...) { \
if ( i2c_debug & ( level ) ) \
2008-10-10 05:08:23 -03:00
printk ( KERN_INFO KBUILD_MODNAME " :[%s:%d] " fmt , \
__func__ , __LINE__ , # # args ) ; \
2008-04-04 21:00:57 -03:00
}
2006-12-04 08:30:53 -03:00
2007-04-14 16:23:49 -03:00
static int usbvision_i2c_write ( struct usb_usbvision * usbvision , unsigned char addr , char * buf ,
2006-12-11 05:37:14 -03:00
short len ) ;
2007-04-14 16:23:49 -03:00
static int usbvision_i2c_read ( struct usb_usbvision * usbvision , unsigned char addr , char * buf ,
2006-12-11 05:37:14 -03:00
short len ) ;
2006-12-04 08:30:53 -03:00
static inline int try_write_address ( struct i2c_adapter * i2c_adap ,
unsigned char addr , int retries )
{
2007-04-14 16:23:49 -03:00
struct usb_usbvision * usbvision ;
2006-12-04 08:30:53 -03:00
int i , ret = - 1 ;
char buf [ 4 ] ;
2007-04-16 18:00:49 -03:00
usbvision = ( struct usb_usbvision * ) i2c_get_adapdata ( i2c_adap ) ;
2006-12-04 08:30:53 -03:00
buf [ 0 ] = 0x00 ;
for ( i = 0 ; i < = retries ; i + + ) {
2007-04-14 16:23:49 -03:00
ret = ( usbvision_i2c_write ( usbvision , addr , buf , 1 ) ) ;
2006-12-04 08:30:53 -03:00
if ( ret = = 1 )
break ; /* success! */
2006-12-11 17:18:15 -03:00
udelay ( 5 ) ;
2006-12-04 08:30:53 -03:00
if ( i = = retries ) /* no success */
break ;
2006-12-11 17:18:15 -03:00
udelay ( 10 ) ;
2006-12-04 08:30:53 -03:00
}
2006-12-04 08:31:45 -03:00
if ( i ) {
2010-12-29 13:53:21 -03:00
PDEBUG ( DBG_I2C , " Needed %d retries for address %#2x " , i , addr ) ;
PDEBUG ( DBG_I2C , " Maybe there's no device at this address " ) ;
2006-12-04 08:30:53 -03:00
}
return ret ;
}
static inline int try_read_address ( struct i2c_adapter * i2c_adap ,
unsigned char addr , int retries )
{
2007-04-14 16:23:49 -03:00
struct usb_usbvision * usbvision ;
2006-12-04 08:30:53 -03:00
int i , ret = - 1 ;
char buf [ 4 ] ;
2007-04-16 18:00:49 -03:00
usbvision = ( struct usb_usbvision * ) i2c_get_adapdata ( i2c_adap ) ;
2006-12-04 08:30:53 -03:00
for ( i = 0 ; i < = retries ; i + + ) {
2007-04-14 16:23:49 -03:00
ret = ( usbvision_i2c_read ( usbvision , addr , buf , 1 ) ) ;
2006-12-04 08:30:53 -03:00
if ( ret = = 1 )
break ; /* success! */
2006-12-11 17:18:15 -03:00
udelay ( 5 ) ;
2006-12-04 08:30:53 -03:00
if ( i = = retries ) /* no success */
break ;
2006-12-11 17:18:15 -03:00
udelay ( 10 ) ;
2006-12-04 08:30:53 -03:00
}
2006-12-04 08:31:45 -03:00
if ( i ) {
2010-12-29 13:53:21 -03:00
PDEBUG ( DBG_I2C , " Needed %d retries for address %#2x " , i , addr ) ;
PDEBUG ( DBG_I2C , " Maybe there's no device at this address " ) ;
2006-12-04 08:30:53 -03:00
}
return ret ;
}
static inline int usb_find_address ( struct i2c_adapter * i2c_adap ,
struct i2c_msg * msg , int retries ,
unsigned char * add )
{
unsigned short flags = msg - > flags ;
2006-12-04 08:31:14 -03:00
2006-12-04 08:30:53 -03:00
unsigned char addr ;
int ret ;
2011-11-07 05:24:49 -03:00
addr = ( msg - > addr < < 1 ) ;
if ( flags & I2C_M_RD )
addr | = 1 ;
2006-12-04 08:30:53 -03:00
2011-11-07 05:24:49 -03:00
add [ 0 ] = addr ;
if ( flags & I2C_M_RD )
ret = try_read_address ( i2c_adap , addr , retries ) ;
else
ret = try_write_address ( i2c_adap , addr , retries ) ;
if ( ret ! = 1 )
return - EREMOTEIO ;
2006-12-04 08:30:53 -03:00
return 0 ;
}
static int
2007-04-14 16:23:49 -03:00
usbvision_i2c_xfer ( struct i2c_adapter * i2c_adap , struct i2c_msg msgs [ ] , int num )
2006-12-04 08:30:53 -03:00
{
struct i2c_msg * pmsg ;
2007-04-14 16:23:49 -03:00
struct usb_usbvision * usbvision ;
2006-12-04 08:30:53 -03:00
int i , ret ;
2009-01-17 13:09:11 -03:00
unsigned char addr = 0 ;
2006-12-04 08:30:53 -03:00
2007-04-16 18:00:49 -03:00
usbvision = ( struct usb_usbvision * ) i2c_get_adapdata ( i2c_adap ) ;
2006-12-04 08:30:53 -03:00
for ( i = 0 ; i < num ; i + + ) {
pmsg = & msgs [ i ] ;
ret = usb_find_address ( i2c_adap , pmsg , i2c_adap - > retries , & addr ) ;
if ( ret ! = 0 ) {
2010-12-29 13:53:21 -03:00
PDEBUG ( DBG_I2C , " got NAK from device, message #%d " , i ) ;
2006-12-04 08:30:53 -03:00
return ( ret < 0 ) ? ret : - EREMOTEIO ;
}
if ( pmsg - > flags & I2C_M_RD ) {
/* read bytes into buffer */
2007-04-14 16:23:49 -03:00
ret = ( usbvision_i2c_read ( usbvision , addr , pmsg - > buf , pmsg - > len ) ) ;
2010-12-29 13:53:21 -03:00
if ( ret < pmsg - > len )
2006-12-04 08:30:53 -03:00
return ( ret < 0 ) ? ret : - EREMOTEIO ;
} else {
/* write bytes from buffer */
2007-04-14 16:23:49 -03:00
ret = ( usbvision_i2c_write ( usbvision , addr , pmsg - > buf , pmsg - > len ) ) ;
2010-12-29 13:53:21 -03:00
if ( ret < pmsg - > len )
2006-12-04 08:30:53 -03:00
return ( ret < 0 ) ? ret : - EREMOTEIO ;
}
}
return num ;
}
2007-04-14 16:23:49 -03:00
static u32 functionality ( struct i2c_adapter * adap )
2006-12-04 08:30:53 -03:00
{
2011-11-07 05:24:49 -03:00
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL ;
2006-12-04 08:30:53 -03:00
}
/* -----exported algorithm data: ------------------------------------- */
2017-07-09 18:04:24 -04:00
static const struct i2c_algorithm usbvision_algo = {
2007-04-14 16:23:49 -03:00
. master_xfer = usbvision_i2c_xfer ,
2006-12-04 08:30:53 -03:00
. smbus_xfer = NULL ,
2007-04-14 16:23:49 -03:00
. functionality = functionality ,
2006-12-04 08:30:53 -03:00
} ;
2006-12-04 08:31:45 -03:00
/* ----------------------------------------------------------------------- */
/* usbvision specific I2C functions */
/* ----------------------------------------------------------------------- */
2017-08-19 06:34:15 -04:00
static const struct i2c_adapter i2c_adap_template ;
2006-12-04 08:31:45 -03:00
2007-04-14 16:23:49 -03:00
int usbvision_i2c_register ( struct usb_usbvision * usbvision )
2006-12-04 08:31:45 -03:00
{
2009-02-21 18:11:31 -03:00
static unsigned short saa711x_addrs [ ] = {
0x4a > > 1 , 0x48 > > 1 , /* SAA7111, SAA7111A and SAA7113 */
0x42 > > 1 , 0x40 > > 1 , /* SAA7114, SAA7115 and SAA7118 */
I2C_CLIENT_END } ;
2010-09-17 15:07:28 -03:00
if ( usbvision - > registered_i2c )
return 0 ;
2012-10-23 15:57:06 -03:00
usbvision - > i2c_adap = i2c_adap_template ;
2006-12-04 08:31:45 -03:00
2017-07-17 10:29:58 -04:00
snprintf ( usbvision - > i2c_adap . name , sizeof ( usbvision - > i2c_adap . name ) ,
" usbvision-%d-%s " ,
usbvision - > dev - > bus - > busnum , usbvision - > dev - > devpath ) ;
2010-12-29 13:53:21 -03:00
PDEBUG ( DBG_I2C , " Adaptername: %s " , usbvision - > i2c_adap . name ) ;
2007-04-16 18:00:49 -03:00
usbvision - > i2c_adap . dev . parent = & usbvision - > dev - > dev ;
2009-02-21 18:11:31 -03:00
i2c_set_adapdata ( & usbvision - > i2c_adap , & usbvision - > v4l2_dev ) ;
2006-12-04 08:31:45 -03:00
if ( usbvision_write_reg ( usbvision , USBVISION_SER_MODE , USBVISION_IIC_LRNACK ) < 0 ) {
2011-04-27 17:36:05 -03:00
printk ( KERN_ERR " usbvision_i2c_register: can't write reg \n " ) ;
2006-12-04 08:31:45 -03:00
return - EBUSY ;
}
2009-02-21 18:11:31 -03:00
PDEBUG ( DBG_I2C , " I2C debugging is enabled [i2c] " ) ;
PDEBUG ( DBG_I2C , " ALGO debugging is enabled [i2c] " ) ;
/* register new adapter to i2c module... */
usbvision - > i2c_adap . algo = & usbvision_algo ;
usbvision - > i2c_adap . timeout = 100 ; /* default values, should */
usbvision - > i2c_adap . retries = 3 ; /* be replaced by defines */
i2c_add_adapter ( & usbvision - > i2c_adap ) ;
PDEBUG ( DBG_I2C , " i2c bus for %s registered " , usbvision - > i2c_adap . name ) ;
2006-12-04 08:31:45 -03:00
/* Request the load of the i2c modules we need */
2010-12-19 20:21:36 -03:00
switch ( usbvision_device_data [ usbvision - > dev_model ] . codec ) {
2006-12-04 08:31:45 -03:00
case CODEC_SAA7113 :
case CODEC_SAA7111 :
2010-05-02 09:29:27 -03:00
/* Without this delay the detection of the saa711x is
hit - and - miss . */
mdelay ( 10 ) ;
2009-08-10 02:49:08 -03:00
v4l2_i2c_new_subdev ( & usbvision - > v4l2_dev ,
2010-09-24 10:16:44 -03:00
& usbvision - > i2c_adap ,
2009-08-10 02:49:08 -03:00
" saa7115_auto " , 0 , saa711x_addrs ) ;
2006-12-04 08:31:45 -03:00
break ;
}
2010-12-19 20:21:36 -03:00
if ( usbvision_device_data [ usbvision - > dev_model ] . tuner = = 1 ) {
2009-02-21 18:11:31 -03:00
struct v4l2_subdev * sd ;
enum v4l2_i2c_tuner_type type ;
struct tuner_setup tun_setup ;
2009-08-10 02:49:08 -03:00
sd = v4l2_i2c_new_subdev ( & usbvision - > v4l2_dev ,
2010-09-24 10:16:44 -03:00
& usbvision - > i2c_adap ,
2009-08-10 02:49:08 -03:00
" tuner " , 0 , v4l2_i2c_tuner_addrs ( ADDRS_DEMOD ) ) ;
2009-02-21 18:11:31 -03:00
/* depending on whether we found a demod or not, select
the tuner type . */
type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV ;
2009-08-10 02:49:08 -03:00
sd = v4l2_i2c_new_subdev ( & usbvision - > v4l2_dev ,
2010-09-24 10:16:44 -03:00
& usbvision - > i2c_adap ,
2009-08-10 02:49:08 -03:00
" tuner " , 0 , v4l2_i2c_tuner_addrs ( type ) ) ;
2009-02-21 18:11:31 -03:00
2010-09-17 15:07:28 -03:00
if ( sd = = NULL )
return - ENODEV ;
2009-02-21 18:11:31 -03:00
if ( usbvision - > tuner_type ! = - 1 ) {
tun_setup . mode_mask = T_ANALOG_TV | T_RADIO ;
tun_setup . type = usbvision - > tuner_type ;
tun_setup . addr = v4l2_i2c_subdev_addr ( sd ) ;
call_all ( usbvision , tuner , s_type_addr , & tun_setup ) ;
}
2006-12-04 08:30:53 -03:00
}
2010-09-17 15:07:28 -03:00
usbvision - > registered_i2c = 1 ;
2006-12-04 08:30:53 -03:00
2009-02-21 18:11:31 -03:00
return 0 ;
2007-04-14 16:23:49 -03:00
}
int usbvision_i2c_unregister ( struct usb_usbvision * usbvision )
{
2010-09-17 15:07:28 -03:00
if ( ! usbvision - > registered_i2c )
return 0 ;
2007-04-14 16:23:49 -03:00
i2c_del_adapter ( & ( usbvision - > i2c_adap ) ) ;
2010-09-17 15:07:28 -03:00
usbvision - > registered_i2c = 0 ;
2007-04-14 16:23:49 -03:00
2010-12-29 13:53:21 -03:00
PDEBUG ( DBG_I2C , " i2c bus for %s unregistered " , usbvision - > i2c_adap . name ) ;
2007-04-14 16:23:49 -03:00
return 0 ;
2006-12-04 08:31:45 -03:00
}
static int
usbvision_i2c_read_max4 ( struct usb_usbvision * usbvision , unsigned char addr ,
char * buf , short len )
{
int rc , retries ;
for ( retries = 5 ; ; ) {
rc = usbvision_write_reg ( usbvision , USBVISION_SER_ADRS , addr ) ;
if ( rc < 0 )
return rc ;
/* Initiate byte read cycle */
/* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */
/* d3 0=Wr 1=Rd */
rc = usbvision_write_reg ( usbvision , USBVISION_SER_CONT ,
( len & 0x07 ) | 0x18 ) ;
if ( rc < 0 )
return rc ;
/* Test for Busy and ACK */
do {
/* USBVISION_SER_CONT -> d4 == 0 busy */
rc = usbvision_read_reg ( usbvision , USBVISION_SER_CONT ) ;
} while ( rc > 0 & & ( ( rc & 0x10 ) ! = 0 ) ) ; /* Retry while busy */
if ( rc < 0 )
return rc ;
/* USBVISION_SER_CONT -> d5 == 1 Not ack */
if ( ( rc & 0x20 ) = = 0 ) /* Ack? */
break ;
/* I2C abort */
rc = usbvision_write_reg ( usbvision , USBVISION_SER_CONT , 0x00 ) ;
if ( rc < 0 )
return rc ;
if ( - - retries < 0 )
return - 1 ;
}
switch ( len ) {
case 4 :
buf [ 3 ] = usbvision_read_reg ( usbvision , USBVISION_SER_DAT4 ) ;
2017-05-18 08:13:28 -03:00
/* fall through */
2006-12-04 08:31:45 -03:00
case 3 :
buf [ 2 ] = usbvision_read_reg ( usbvision , USBVISION_SER_DAT3 ) ;
2017-05-18 08:13:28 -03:00
/* fall through */
2006-12-04 08:31:45 -03:00
case 2 :
buf [ 1 ] = usbvision_read_reg ( usbvision , USBVISION_SER_DAT2 ) ;
2017-05-18 08:13:28 -03:00
/* fall through */
2006-12-04 08:31:45 -03:00
case 1 :
buf [ 0 ] = usbvision_read_reg ( usbvision , USBVISION_SER_DAT1 ) ;
break ;
default :
printk ( KERN_ERR
" usbvision_i2c_read_max4: buffer length > 4 \n " ) ;
}
if ( i2c_debug & DBG_I2C ) {
int idx ;
2010-12-29 13:53:21 -03:00
for ( idx = 0 ; idx < len ; idx + + )
PDEBUG ( DBG_I2C , " read %x from address %x " , ( unsigned char ) buf [ idx ] , addr ) ;
2006-12-04 08:31:45 -03:00
}
return len ;
}
static int usbvision_i2c_write_max4 ( struct usb_usbvision * usbvision ,
unsigned char addr , const char * buf ,
short len )
{
int rc , retries ;
int i ;
2015-07-20 09:59:36 -03:00
unsigned char * value = usbvision - > ctrl_urb_buffer ;
2006-12-04 08:31:45 -03:00
unsigned char ser_cont ;
ser_cont = ( len & 0x07 ) | 0x10 ;
value [ 0 ] = addr ;
value [ 1 ] = ser_cont ;
for ( i = 0 ; i < len ; i + + )
value [ i + 2 ] = buf [ i ] ;
for ( retries = 5 ; ; ) {
rc = usb_control_msg ( usbvision - > dev ,
usb_sndctrlpipe ( usbvision - > dev , 1 ) ,
USBVISION_OP_CODE ,
USB_DIR_OUT | USB_TYPE_VENDOR |
USB_RECIP_ENDPOINT , 0 ,
( __u16 ) USBVISION_SER_ADRS , value ,
len + 2 , HZ ) ;
if ( rc < 0 )
return rc ;
rc = usbvision_write_reg ( usbvision , USBVISION_SER_CONT ,
( len & 0x07 ) | 0x10 ) ;
if ( rc < 0 )
return rc ;
/* Test for Busy and ACK */
do {
rc = usbvision_read_reg ( usbvision , USBVISION_SER_CONT ) ;
} while ( rc > 0 & & ( ( rc & 0x10 ) ! = 0 ) ) ; /* Retry while busy */
if ( rc < 0 )
return rc ;
if ( ( rc & 0x20 ) = = 0 ) /* Ack? */
break ;
/* I2C abort */
usbvision_write_reg ( usbvision , USBVISION_SER_CONT , 0x00 ) ;
if ( - - retries < 0 )
return - 1 ;
}
if ( i2c_debug & DBG_I2C ) {
int idx ;
2010-12-29 13:53:21 -03:00
for ( idx = 0 ; idx < len ; idx + + )
PDEBUG ( DBG_I2C , " wrote %x at address %x " , ( unsigned char ) buf [ idx ] , addr ) ;
2006-12-04 08:31:45 -03:00
}
return len ;
}
2007-04-14 16:23:49 -03:00
static int usbvision_i2c_write ( struct usb_usbvision * usbvision , unsigned char addr , char * buf ,
2006-12-04 08:31:45 -03:00
short len )
{
2010-12-19 20:21:36 -03:00
char * buf_ptr = buf ;
2006-12-04 08:31:45 -03:00
int retval ;
int wrcount = 0 ;
int count ;
2010-12-19 20:21:36 -03:00
int max_len = 4 ;
2006-12-04 08:31:45 -03:00
while ( len > 0 ) {
2010-12-19 20:21:36 -03:00
count = ( len > max_len ) ? max_len : len ;
retval = usbvision_i2c_write_max4 ( usbvision , addr , buf_ptr , count ) ;
2006-12-04 08:31:45 -03:00
if ( retval > 0 ) {
len - = count ;
2010-12-19 20:21:36 -03:00
buf_ptr + = count ;
2006-12-04 08:31:45 -03:00
wrcount + = count ;
} else
return ( retval < 0 ) ? retval : - EFAULT ;
}
return wrcount ;
}
2007-04-14 16:23:49 -03:00
static int usbvision_i2c_read ( struct usb_usbvision * usbvision , unsigned char addr , char * buf ,
2006-12-04 08:31:45 -03:00
short len )
{
char temp [ 4 ] ;
int retval , i ;
int rdcount = 0 ;
int count ;
while ( len > 0 ) {
count = ( len > 3 ) ? 4 : len ;
retval = usbvision_i2c_read_max4 ( usbvision , addr , temp , count ) ;
if ( retval > 0 ) {
for ( i = 0 ; i < len ; i + + )
buf [ rdcount + i ] = temp [ i ] ;
len - = count ;
rdcount + = count ;
} else
return ( retval < 0 ) ? retval : - EFAULT ;
}
return rdcount ;
}
2017-08-19 06:34:15 -04:00
static const struct i2c_adapter i2c_adap_template = {
2006-12-04 08:31:45 -03:00
. owner = THIS_MODULE ,
. name = " usbvision " ,
} ;