2011-08-22 02:56:44 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2005-04-17 02:20:36 +04:00
# include <media/saa7146_vv.h>
static u32 saa7146_i2c_func ( struct i2c_adapter * adapter )
{
2011-08-22 02:56:44 +04:00
/* DEB_I2C("'%s'\n", adapter->name); */
2005-04-17 02:20:36 +04:00
return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_QUICK
| I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE
| I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA ;
}
/* this function returns the status-register of our i2c-device */
static inline u32 saa7146_i2c_status ( struct saa7146_dev * dev )
{
u32 iicsta = saa7146_read ( dev , I2C_STATUS ) ;
2011-08-22 02:56:44 +04:00
/* DEB_I2C("status: 0x%08x\n", iicsta); */
2005-04-17 02:20:36 +04:00
return iicsta ;
}
/* this function runs through the i2c-messages and prepares the data to be
sent through the saa7146 . have a look at the specifications p . 122 ff
to understand this . it returns the number of u32s to send , or - 1
in case of an error . */
2008-06-22 21:19:19 +04:00
static int saa7146_i2c_msg_prepare ( const struct i2c_msg * m , int num , __le32 * op )
2005-04-17 02:20:36 +04:00
{
int h1 , h2 ;
int i , j , addr ;
int mem = 0 , op_count = 0 ;
/* first determine size of needed memory */
for ( i = 0 ; i < num ; i + + ) {
mem + = m [ i ] . len + 1 ;
}
/* worst case: we need one u32 for three bytes to be send
plus one extra byte to address the device */
mem = 1 + ( ( mem - 1 ) / 3 ) ;
2011-08-22 02:56:44 +04:00
/* we assume that op points to a memory of at least
* SAA7146_I2C_MEM bytes size . if we exceed this limit . . .
*/
if ( ( 4 * mem ) > SAA7146_I2C_MEM ) {
/* DEB_I2C("cannot prepare i2c-message\n"); */
2005-04-17 02:20:36 +04:00
return - ENOMEM ;
}
/* be careful: clear out the i2c-mem first */
2008-06-22 21:19:19 +04:00
memset ( op , 0 , sizeof ( __le32 ) * mem ) ;
2005-04-17 02:20:36 +04:00
/* loop through all messages */
for ( i = 0 ; i < num ; i + + ) {
/* insert the address of the i2c-slave.
note : we get 7 bit i2c - addresses ,
so we have to perform a translation */
addr = ( m [ i ] . addr * 2 ) + ( ( 0 ! = ( m [ i ] . flags & I2C_M_RD ) ) ? 1 : 0 ) ;
h1 = op_count / 3 ; h2 = op_count % 3 ;
2008-06-22 21:19:19 +04:00
op [ h1 ] | = cpu_to_le32 ( ( u8 ) addr < < ( ( 3 - h2 ) * 8 ) ) ;
op [ h1 ] | = cpu_to_le32 ( SAA7146_I2C_START < < ( ( 3 - h2 ) * 2 ) ) ;
2005-04-17 02:20:36 +04:00
op_count + + ;
/* loop through all bytes of message i */
for ( j = 0 ; j < m [ i ] . len ; j + + ) {
/* insert the data bytes */
h1 = op_count / 3 ; h2 = op_count % 3 ;
2008-06-22 21:19:19 +04:00
op [ h1 ] | = cpu_to_le32 ( ( u32 ) ( ( u8 ) m [ i ] . buf [ j ] ) < < ( ( 3 - h2 ) * 8 ) ) ;
op [ h1 ] | = cpu_to_le32 ( SAA7146_I2C_CONT < < ( ( 3 - h2 ) * 2 ) ) ;
2005-04-17 02:20:36 +04:00
op_count + + ;
}
}
/* have a look at the last byte inserted:
if it was : . . . CONT change it to . . . STOP */
h1 = ( op_count - 1 ) / 3 ; h2 = ( op_count - 1 ) % 3 ;
2008-06-22 21:19:19 +04:00
if ( SAA7146_I2C_CONT = = ( 0x3 & ( le32_to_cpu ( op [ h1 ] ) > > ( ( 3 - h2 ) * 2 ) ) ) ) {
op [ h1 ] & = ~ cpu_to_le32 ( 0x2 < < ( ( 3 - h2 ) * 2 ) ) ;
op [ h1 ] | = cpu_to_le32 ( SAA7146_I2C_STOP < < ( ( 3 - h2 ) * 2 ) ) ;
2005-04-17 02:20:36 +04:00
}
/* return the number of u32s to send */
return mem ;
}
/* this functions loops through all i2c-messages. normally, it should determine
which bytes were read through the adapter and write them back to the corresponding
i2c - message . but instead , we simply write back all bytes .
fixme : this could be improved . */
2008-06-22 21:19:19 +04:00
static int saa7146_i2c_msg_cleanup ( const struct i2c_msg * m , int num , __le32 * op )
2005-04-17 02:20:36 +04:00
{
int i , j ;
int op_count = 0 ;
/* loop through all messages */
for ( i = 0 ; i < num ; i + + ) {
op_count + + ;
tree-wide: fix assorted typos all over the place
That is "success", "unknown", "through", "performance", "[re|un]mapping"
, "access", "default", "reasonable", "[con]currently", "temperature"
, "channel", "[un]used", "application", "example","hierarchy", "therefore"
, "[over|under]flow", "contiguous", "threshold", "enough" and others.
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2009-11-14 18:09:05 +03:00
/* loop through all bytes of message i */
2005-04-17 02:20:36 +04:00
for ( j = 0 ; j < m [ i ] . len ; j + + ) {
/* write back all bytes that could have been read */
2008-06-22 21:19:19 +04:00
m [ i ] . buf [ j ] = ( le32_to_cpu ( op [ op_count / 3 ] ) > > ( ( 3 - ( op_count % 3 ) ) * 8 ) ) ;
2005-04-17 02:20:36 +04:00
op_count + + ;
}
}
return 0 ;
}
/* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */
static int saa7146_i2c_reset ( struct saa7146_dev * dev )
{
/* get current status */
u32 status = saa7146_i2c_status ( dev ) ;
/* clear registers for sure */
saa7146_write ( dev , I2C_STATUS , dev - > i2c_bitrate ) ;
saa7146_write ( dev , I2C_TRANSFER , 0 ) ;
/* check if any operation is still in progress */
if ( 0 ! = ( status & SAA7146_I2C_BUSY ) ) {
/* yes, kill ongoing operation */
2011-08-22 02:56:44 +04:00
DEB_I2C ( " busy_state detected \n " ) ;
2005-04-17 02:20:36 +04:00
/* set "ABORT-OPERATION"-bit (bit 7)*/
saa7146_write ( dev , I2C_STATUS , ( dev - > i2c_bitrate | MASK_07 ) ) ;
saa7146_write ( dev , MC2 , ( MASK_00 | MASK_16 ) ) ;
msleep ( SAA7146_I2C_DELAY ) ;
/* clear all error-bits pending; this is needed because p.123, note 1 */
saa7146_write ( dev , I2C_STATUS , dev - > i2c_bitrate ) ;
saa7146_write ( dev , MC2 , ( MASK_00 | MASK_16 ) ) ;
msleep ( SAA7146_I2C_DELAY ) ;
}
/* check if any error is (still) present. (this can be necessary because p.123, note 1) */
status = saa7146_i2c_status ( dev ) ;
if ( dev - > i2c_bitrate ! = status ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " error_state detected. status:0x%08x \n " , status ) ;
2005-04-17 02:20:36 +04:00
/* Repeat the abort operation. This seems to be necessary
after serious protocol errors caused by e . g . the SAA7740 */
saa7146_write ( dev , I2C_STATUS , ( dev - > i2c_bitrate | MASK_07 ) ) ;
saa7146_write ( dev , MC2 , ( MASK_00 | MASK_16 ) ) ;
msleep ( SAA7146_I2C_DELAY ) ;
/* clear all error-bits pending */
saa7146_write ( dev , I2C_STATUS , dev - > i2c_bitrate ) ;
saa7146_write ( dev , MC2 , ( MASK_00 | MASK_16 ) ) ;
msleep ( SAA7146_I2C_DELAY ) ;
/* the data sheet says it might be necessary to clear the status
twice after an abort */
saa7146_write ( dev , I2C_STATUS , dev - > i2c_bitrate ) ;
saa7146_write ( dev , MC2 , ( MASK_00 | MASK_16 ) ) ;
msleep ( SAA7146_I2C_DELAY ) ;
}
2011-03-31 05:57:33 +04:00
/* if any error is still present, a fatal error has occurred ... */
2005-04-17 02:20:36 +04:00
status = saa7146_i2c_status ( dev ) ;
if ( dev - > i2c_bitrate ! = status ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " fatal error. status:0x%08x \n " , status ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
return 0 ;
}
/* this functions writes out the data-byte 'dword' to the i2c-device.
it returns 0 if ok , - 1 if the transfer failed , - 2 if the transfer
failed badly ( e . g . address error ) */
2008-06-22 21:19:19 +04:00
static int saa7146_i2c_writeout ( struct saa7146_dev * dev , __le32 * dword , int short_delay )
2005-04-17 02:20:36 +04:00
{
u32 status = 0 , mc2 = 0 ;
int trial = 0 ;
unsigned long timeout ;
/* write out i2c-command */
2011-08-22 02:56:44 +04:00
DEB_I2C ( " before: 0x%08x (status: 0x%08x), %d \n " ,
* dword , saa7146_read ( dev , I2C_STATUS ) , dev - > i2c_op ) ;
2005-04-17 02:20:36 +04:00
if ( 0 ! = ( SAA7146_USE_I2C_IRQ & dev - > ext - > flags ) ) {
saa7146_write ( dev , I2C_STATUS , dev - > i2c_bitrate ) ;
2008-06-22 21:19:19 +04:00
saa7146_write ( dev , I2C_TRANSFER , le32_to_cpu ( * dword ) ) ;
2005-04-17 02:20:36 +04:00
dev - > i2c_op = 1 ;
2006-11-01 19:01:42 +03:00
SAA7146_ISR_CLEAR ( dev , MASK_16 | MASK_17 ) ;
2005-04-17 02:20:36 +04:00
SAA7146_IER_ENABLE ( dev , MASK_16 | MASK_17 ) ;
saa7146_write ( dev , MC2 , ( MASK_00 | MASK_16 ) ) ;
2006-11-01 19:01:42 +03:00
timeout = HZ / 100 + 1 ; /* 10ms */
timeout = wait_event_interruptible_timeout ( dev - > i2c_wq , dev - > i2c_op = = 0 , timeout ) ;
if ( timeout = = - ERESTARTSYS | | dev - > i2c_op ) {
SAA7146_IER_DISABLE ( dev , MASK_16 | MASK_17 ) ;
SAA7146_ISR_CLEAR ( dev , MASK_16 | MASK_17 ) ;
if ( timeout = = - ERESTARTSYS )
/* a signal arrived */
return - ERESTARTSYS ;
2011-08-22 02:56:44 +04:00
pr_warn ( " %s %s [irq]: timed out waiting for end of xfer \n " ,
2008-04-09 06:20:00 +04:00
dev - > name , __func__ ) ;
2006-11-01 19:01:42 +03:00
return - EIO ;
2005-04-17 02:20:36 +04:00
}
status = saa7146_read ( dev , I2C_STATUS ) ;
} else {
saa7146_write ( dev , I2C_STATUS , dev - > i2c_bitrate ) ;
2008-06-22 21:19:19 +04:00
saa7146_write ( dev , I2C_TRANSFER , le32_to_cpu ( * dword ) ) ;
2005-04-17 02:20:36 +04:00
saa7146_write ( dev , MC2 , ( MASK_00 | MASK_16 ) ) ;
/* do not poll for i2c-status before upload is complete */
timeout = jiffies + HZ / 100 + 1 ; /* 10ms */
while ( 1 ) {
mc2 = ( saa7146_read ( dev , MC2 ) & 0x1 ) ;
if ( 0 ! = mc2 ) {
break ;
}
if ( time_after ( jiffies , timeout ) ) {
2011-08-22 02:56:44 +04:00
pr_warn ( " %s %s: timed out waiting for MC2 \n " ,
2008-04-09 06:20:00 +04:00
dev - > name , __func__ ) ;
2005-04-17 02:20:36 +04:00
return - EIO ;
}
}
/* wait until we get a transfer done or error */
timeout = jiffies + HZ / 100 + 1 ; /* 10ms */
2006-10-28 01:02:01 +04:00
/* first read usually delivers bogus results... */
saa7146_i2c_status ( dev ) ;
2005-04-17 02:20:36 +04:00
while ( 1 ) {
status = saa7146_i2c_status ( dev ) ;
if ( ( status & 0x3 ) ! = 1 )
break ;
if ( time_after ( jiffies , timeout ) ) {
/* this is normal when probing the bus
* ( no answer from nonexisistant device . . . )
*/
2011-08-22 02:56:44 +04:00
pr_warn ( " %s %s [poll]: timed out waiting for end of xfer \n " ,
2008-04-09 06:20:00 +04:00
dev - > name , __func__ ) ;
2005-04-17 02:20:36 +04:00
return - EIO ;
}
2006-10-28 01:02:01 +04:00
if ( + + trial < 50 & & short_delay )
2005-04-17 02:20:36 +04:00
udelay ( 10 ) ;
else
2006-10-28 01:02:01 +04:00
msleep ( 1 ) ;
2005-04-17 02:20:36 +04:00
}
}
/* give a detailed status report */
2007-08-09 09:41:16 +04:00
if ( 0 ! = ( status & ( SAA7146_I2C_SPERR | SAA7146_I2C_APERR |
SAA7146_I2C_DTERR | SAA7146_I2C_DRERR |
SAA7146_I2C_AL | SAA7146_I2C_ERR |
SAA7146_I2C_BUSY ) ) ) {
if ( 0 = = ( status & SAA7146_I2C_ERR ) | |
0 = = ( status & SAA7146_I2C_BUSY ) ) {
/* it may take some time until ERR goes high - ignore */
2011-08-22 02:56:44 +04:00
DEB_I2C ( " unexpected i2c status %04x \n " , status ) ;
2007-08-09 09:41:16 +04:00
}
2005-04-17 02:20:36 +04:00
if ( 0 ! = ( status & SAA7146_I2C_SPERR ) ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " error due to invalid start/stop condition \n " ) ;
2005-04-17 02:20:36 +04:00
}
if ( 0 ! = ( status & SAA7146_I2C_DTERR ) ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " error in data transmission \n " ) ;
2005-04-17 02:20:36 +04:00
}
if ( 0 ! = ( status & SAA7146_I2C_DRERR ) ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " error when receiving data \n " ) ;
2005-04-17 02:20:36 +04:00
}
if ( 0 ! = ( status & SAA7146_I2C_AL ) ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " error because arbitration lost \n " ) ;
2005-04-17 02:20:36 +04:00
}
/* we handle address-errors here */
if ( 0 ! = ( status & SAA7146_I2C_APERR ) ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " error in address phase \n " ) ;
2005-04-17 02:20:36 +04:00
return - EREMOTEIO ;
}
return - EIO ;
}
/* read back data, just in case we were reading ... */
2008-06-22 21:19:19 +04:00
* dword = cpu_to_le32 ( saa7146_read ( dev , I2C_TRANSFER ) ) ;
2005-04-17 02:20:36 +04:00
2011-08-22 02:56:44 +04:00
DEB_I2C ( " after: 0x%08x \n " , * dword ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2007-07-23 20:59:55 +04:00
static int saa7146_i2c_transfer ( struct saa7146_dev * dev , const struct i2c_msg * msgs , int num , int retries )
2005-04-17 02:20:36 +04:00
{
int i = 0 , count = 0 ;
2008-06-22 21:19:19 +04:00
__le32 * buffer = dev - > d_i2c . cpu_addr ;
2005-04-17 02:20:36 +04:00
int err = 0 ;
2005-12-12 11:37:27 +03:00
int short_delay = 0 ;
2005-04-17 02:20:36 +04:00
2006-02-07 11:49:14 +03:00
if ( mutex_lock_interruptible ( & dev - > i2c_lock ) )
2005-04-17 02:20:36 +04:00
return - ERESTARTSYS ;
for ( i = 0 ; i < num ; i + + ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " msg:%d/%d \n " , i + 1 , num ) ;
2005-04-17 02:20:36 +04:00
}
/* prepare the message(s), get number of u32s to transfer */
count = saa7146_i2c_msg_prepare ( msgs , num , buffer ) ;
if ( 0 > count ) {
err = - 1 ;
goto out ;
}
if ( count > 3 | | 0 ! = ( SAA7146_I2C_SHORT_DELAY & dev - > ext - > flags ) )
short_delay = 1 ;
do {
/* reset the i2c-device if necessary */
err = saa7146_i2c_reset ( dev ) ;
if ( 0 > err ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " could not reset i2c-device \n " ) ;
2005-04-17 02:20:36 +04:00
goto out ;
}
/* write out the u32s one after another */
for ( i = 0 ; i < count ; i + + ) {
err = saa7146_i2c_writeout ( dev , & buffer [ i ] , short_delay ) ;
if ( 0 ! = err ) {
/* this one is unsatisfying: some i2c slaves on some
dvb cards don ' t acknowledge correctly , so the saa7146
2011-03-31 05:57:33 +04:00
thinks that an address error occurred . in that case , the
2005-04-17 02:20:36 +04:00
transaction should be retrying , even if an address error
2011-03-31 05:57:33 +04:00
occurred . analog saa7146 based cards extensively rely on
2005-04-17 02:20:36 +04:00
i2c address probing , however , and address errors indicate that a
device is really * not * there . retrying in that case
increases the time the device needs to probe greatly , so
2009-02-28 16:35:48 +03:00
it should be avoided . So we bail out in irq mode after an
address error and trust the saa7146 address error detection . */
if ( - EREMOTEIO = = err & & 0 ! = ( SAA7146_USE_I2C_IRQ & dev - > ext - > flags ) )
goto out ;
2011-08-22 02:56:44 +04:00
DEB_I2C ( " error while sending message(s). starting again \n " ) ;
2005-04-17 02:20:36 +04:00
break ;
}
}
if ( 0 = = err ) {
err = num ;
break ;
}
2005-12-12 11:37:27 +03:00
/* delay a bit before retrying */
msleep ( 10 ) ;
2005-04-17 02:20:36 +04:00
} while ( err ! = num & & retries - - ) ;
2009-02-28 16:35:48 +03:00
/* quit if any error occurred */
if ( err ! = num )
2005-12-12 11:37:27 +03:00
goto out ;
2005-04-17 02:20:36 +04:00
/* if any things had to be read, get the results */
if ( 0 ! = saa7146_i2c_msg_cleanup ( msgs , num , buffer ) ) {
2011-08-22 02:56:44 +04:00
DEB_I2C ( " could not cleanup i2c-message \n " ) ;
2005-04-17 02:20:36 +04:00
err = - 1 ;
goto out ;
}
/* return the number of delivered messages */
2011-08-22 02:56:44 +04:00
DEB_I2C ( " transmission successful. (msg:%d) \n " , err ) ;
2005-04-17 02:20:36 +04:00
out :
/* another bug in revision 0: the i2c-registers get uploaded randomly by other
2011-03-31 05:57:33 +04:00
uploads , so we better clear them out before continuing */
2005-04-17 02:20:36 +04:00
if ( 0 = = dev - > revision ) {
2008-06-22 21:19:19 +04:00
__le32 zero = 0 ;
2005-04-17 02:20:36 +04:00
saa7146_i2c_reset ( dev ) ;
if ( 0 ! = saa7146_i2c_writeout ( dev , & zero , short_delay ) ) {
2011-08-22 02:56:44 +04:00
pr_info ( " revision 0 error. this should never happen \n " ) ;
2005-04-17 02:20:36 +04:00
}
}
2006-02-07 11:49:14 +03:00
mutex_unlock ( & dev - > i2c_lock ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
/* utility functions */
static int saa7146_i2c_xfer ( struct i2c_adapter * adapter , struct i2c_msg * msg , int num )
{
2009-02-07 13:38:12 +03:00
struct v4l2_device * v4l2_dev = i2c_get_adapdata ( adapter ) ;
struct saa7146_dev * dev = to_saa7146_dev ( v4l2_dev ) ;
2005-04-17 02:20:36 +04:00
/* use helper function to transfer data */
return saa7146_i2c_transfer ( dev , msg , num , adapter - > retries ) ;
}
/*****************************************************************************/
/* i2c-adapter helper functions */
/* exported algorithm data */
static struct i2c_algorithm saa7146_algo = {
. master_xfer = saa7146_i2c_xfer ,
. functionality = saa7146_i2c_func ,
} ;
int saa7146_i2c_adapter_prepare ( struct saa7146_dev * dev , struct i2c_adapter * i2c_adapter , u32 bitrate )
{
2011-08-22 02:56:44 +04:00
DEB_EE ( " bitrate: 0x%08x \n " , bitrate ) ;
2005-04-17 02:20:36 +04:00
/* enable i2c-port pins */
saa7146_write ( dev , MC1 , ( MASK_08 | MASK_24 ) ) ;
dev - > i2c_bitrate = bitrate ;
saa7146_i2c_reset ( dev ) ;
2009-02-07 13:45:08 +03:00
if ( i2c_adapter ) {
2009-02-07 13:38:12 +03:00
i2c_set_adapdata ( i2c_adapter , & dev - > v4l2_dev ) ;
2005-09-10 00:03:13 +04:00
i2c_adapter - > dev . parent = & dev - > pci - > dev ;
2005-04-17 02:20:36 +04:00
i2c_adapter - > algo = & saa7146_algo ;
i2c_adapter - > algo_data = NULL ;
i2c_adapter - > timeout = SAA7146_I2C_TIMEOUT ;
i2c_adapter - > retries = SAA7146_I2C_RETRIES ;
}
return 0 ;
}