2012-03-03 17:19:52 -03:00
/*
2012-08-14 16:23:43 -03:00
* drivers / media / i2c / smiapp / smiapp - regs . c
2012-03-03 17:19:52 -03:00
*
* Generic driver for SMIA / SMIA + + compliant camera modules
*
* Copyright ( C ) 2011 - - 2012 Nokia Corporation
2012-10-28 06:44:17 -03:00
* Contact : Sakari Ailus < sakari . ailus @ iki . fi >
2012-03-03 17:19:52 -03:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation .
*
* 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/delay.h>
# include <linux/i2c.h>
2012-04-22 08:55:10 -03:00
# include "smiapp.h"
2012-03-03 17:19:52 -03:00
# include "smiapp-regs.h"
static uint32_t float_to_u32_mul_1000000 ( struct i2c_client * client ,
uint32_t phloat )
{
int32_t exp ;
uint64_t man ;
if ( phloat > = 0x80000000 ) {
dev_err ( & client - > dev , " this is a negative number \n " ) ;
return 0 ;
}
if ( phloat = = 0x7f800000 )
return ~ 0 ; /* Inf. */
if ( ( phloat & 0x7f800000 ) = = 0x7f800000 ) {
dev_err ( & client - > dev , " NaN or other special number \n " ) ;
return 0 ;
}
/* Valid cases begin here */
if ( phloat = = 0 )
return 0 ; /* Valid zero */
if ( phloat > 0x4f800000 )
return ~ 0 ; /* larger than 4294967295 */
/*
* Unbias exponent ( note how phloat is now guaranteed to
* have 0 in the high bit )
*/
exp = ( ( int32_t ) phloat > > 23 ) - 127 ;
/* Extract mantissa, add missing '1' bit and it's in MHz */
man = ( ( phloat & 0x7fffff ) | 0x800000 ) * 1000000ULL ;
if ( exp < 0 )
man > > = - exp ;
else
man < < = exp ;
man > > = 23 ; /* Remove mantissa bias */
return man & 0xffffffff ;
}
/*
* Read a 8 / 16 / 32 - bit i2c register . The value is returned in ' val ' .
* Returns zero if successful , or non - zero otherwise .
*/
2012-04-22 09:11:26 -03:00
static int ____smiapp_read ( struct smiapp_sensor * sensor , u16 reg ,
u16 len , u32 * val )
2012-03-03 17:19:52 -03:00
{
2012-04-22 08:55:10 -03:00
struct i2c_client * client = v4l2_get_subdevdata ( & sensor - > src - > sd ) ;
2012-03-03 17:19:52 -03:00
struct i2c_msg msg ;
unsigned char data [ 4 ] ;
u16 offset = reg ;
int r ;
msg . addr = client - > addr ;
msg . flags = 0 ;
msg . len = 2 ;
msg . buf = data ;
/* high byte goes out first */
data [ 0 ] = ( u8 ) ( offset > > 8 ) ;
data [ 1 ] = ( u8 ) offset ;
r = i2c_transfer ( client - > adapter , & msg , 1 ) ;
if ( r ! = 1 ) {
if ( r > = 0 )
r = - EBUSY ;
goto err ;
}
msg . len = len ;
msg . flags = I2C_M_RD ;
r = i2c_transfer ( client - > adapter , & msg , 1 ) ;
if ( r ! = 1 ) {
if ( r > = 0 )
r = - EBUSY ;
goto err ;
}
* val = 0 ;
/* high byte comes first */
switch ( len ) {
2014-04-11 05:47:21 -03:00
case SMIAPP_REG_32BIT :
2012-03-03 17:19:52 -03:00
* val = ( data [ 0 ] < < 24 ) + ( data [ 1 ] < < 16 ) + ( data [ 2 ] < < 8 ) +
data [ 3 ] ;
break ;
2014-04-11 05:47:21 -03:00
case SMIAPP_REG_16BIT :
2012-03-03 17:19:52 -03:00
* val = ( data [ 0 ] < < 8 ) + data [ 1 ] ;
break ;
2014-04-11 05:47:21 -03:00
case SMIAPP_REG_8BIT :
2012-03-03 17:19:52 -03:00
* val = data [ 0 ] ;
break ;
default :
BUG ( ) ;
}
return 0 ;
err :
dev_err ( & client - > dev , " read from offset 0x%x error %d \n " , offset , r ) ;
return r ;
}
2012-04-22 09:11:26 -03:00
/* Read a register using 8-bit access only. */
static int ____smiapp_read_8only ( struct smiapp_sensor * sensor , u16 reg ,
u16 len , u32 * val )
{
unsigned int i ;
int rval ;
* val = 0 ;
for ( i = 0 ; i < len ; i + + ) {
u32 val8 ;
rval = ____smiapp_read ( sensor , reg + i , 1 , & val8 ) ;
if ( rval < 0 )
return rval ;
* val | = val8 < < ( ( len - i - 1 ) < < 3 ) ;
}
return 0 ;
}
/*
* Read a 8 / 16 / 32 - bit i2c register . The value is returned in ' val ' .
* Returns zero if successful , or non - zero otherwise .
*/
static int __smiapp_read ( struct smiapp_sensor * sensor , u32 reg , u32 * val ,
bool only8 )
{
struct i2c_client * client = v4l2_get_subdevdata ( & sensor - > src - > sd ) ;
2014-04-10 10:08:59 -03:00
u8 len = SMIAPP_REG_WIDTH ( reg ) ;
2012-04-22 09:11:26 -03:00
int rval ;
2014-04-11 05:47:21 -03:00
if ( len ! = SMIAPP_REG_8BIT & & len ! = SMIAPP_REG_16BIT
& & len ! = SMIAPP_REG_32BIT )
2012-04-22 09:11:26 -03:00
return - EINVAL ;
2014-04-12 16:41:12 -03:00
if ( len = = SMIAPP_REG_8BIT | | ! only8 )
2014-04-10 10:08:59 -03:00
rval = ____smiapp_read ( sensor , SMIAPP_REG_ADDR ( reg ) , len , val ) ;
2012-04-22 09:11:26 -03:00
else
2014-04-10 10:08:59 -03:00
rval = ____smiapp_read_8only ( sensor , SMIAPP_REG_ADDR ( reg ) , len ,
val ) ;
2012-04-22 09:11:26 -03:00
if ( rval < 0 )
return rval ;
2014-04-11 05:47:21 -03:00
if ( reg & SMIAPP_REG_FLAG_FLOAT )
2012-04-22 09:11:26 -03:00
* val = float_to_u32_mul_1000000 ( client , * val ) ;
return 0 ;
}
2014-04-01 08:37:38 -03:00
int smiapp_read_no_quirk ( struct smiapp_sensor * sensor , u32 reg , u32 * val )
2012-04-22 09:11:26 -03:00
{
return __smiapp_read (
sensor , reg , val ,
smiapp_needs_quirk ( sensor ,
SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY ) ) ;
}
2014-12-13 18:53:37 -02:00
static int smiapp_read_quirk ( struct smiapp_sensor * sensor , u32 reg , u32 * val ,
bool force8 )
2014-04-01 08:37:38 -03:00
{
int rval ;
* val = 0 ;
rval = smiapp_call_quirk ( sensor , reg_access , false , & reg , val ) ;
if ( rval = = - ENOIOCTLCMD )
return 0 ;
if ( rval < 0 )
return rval ;
2014-12-13 18:53:37 -02:00
if ( force8 )
return __smiapp_read ( sensor , reg , val , true ) ;
2014-04-01 08:37:38 -03:00
return smiapp_read_no_quirk ( sensor , reg , val ) ;
}
2014-12-13 18:53:37 -02:00
int smiapp_read ( struct smiapp_sensor * sensor , u32 reg , u32 * val )
2012-04-22 09:11:26 -03:00
{
2014-12-13 18:53:37 -02:00
return smiapp_read_quirk ( sensor , reg , val , false ) ;
}
2014-04-01 08:37:38 -03:00
2014-12-13 18:53:37 -02:00
int smiapp_read_8only ( struct smiapp_sensor * sensor , u32 reg , u32 * val )
{
return smiapp_read_quirk ( sensor , reg , val , true ) ;
2012-04-22 09:11:26 -03:00
}
2014-04-01 08:37:38 -03:00
int smiapp_write_no_quirk ( struct smiapp_sensor * sensor , u32 reg , u32 val )
2012-03-03 17:19:52 -03:00
{
2012-04-22 08:55:10 -03:00
struct i2c_client * client = v4l2_get_subdevdata ( & sensor - > src - > sd ) ;
2012-03-03 17:19:52 -03:00
struct i2c_msg msg ;
unsigned char data [ 6 ] ;
unsigned int retries ;
2014-04-10 10:08:59 -03:00
u8 flags = SMIAPP_REG_FLAGS ( reg ) ;
u8 len = SMIAPP_REG_WIDTH ( reg ) ;
u16 offset = SMIAPP_REG_ADDR ( reg ) ;
2012-03-03 17:19:52 -03:00
int r ;
2014-04-11 05:47:21 -03:00
if ( ( len ! = SMIAPP_REG_8BIT & & len ! = SMIAPP_REG_16BIT & &
len ! = SMIAPP_REG_32BIT ) | | flags )
2012-03-03 17:19:52 -03:00
return - EINVAL ;
msg . addr = client - > addr ;
msg . flags = 0 ; /* Write */
msg . len = 2 + len ;
msg . buf = data ;
/* high byte goes out first */
data [ 0 ] = ( u8 ) ( reg > > 8 ) ;
data [ 1 ] = ( u8 ) ( reg & 0xff ) ;
switch ( len ) {
2014-04-11 05:47:21 -03:00
case SMIAPP_REG_8BIT :
2012-03-03 17:19:52 -03:00
data [ 2 ] = val ;
break ;
2014-04-11 05:47:21 -03:00
case SMIAPP_REG_16BIT :
2012-03-03 17:19:52 -03:00
data [ 2 ] = val > > 8 ;
data [ 3 ] = val ;
break ;
2014-04-11 05:47:21 -03:00
case SMIAPP_REG_32BIT :
2012-03-03 17:19:52 -03:00
data [ 2 ] = val > > 24 ;
data [ 3 ] = val > > 16 ;
data [ 4 ] = val > > 8 ;
data [ 5 ] = val ;
break ;
default :
BUG ( ) ;
}
for ( retries = 0 ; retries < 5 ; retries + + ) {
/*
* Due to unknown reason sensor stops responding . This
* loop is a temporaty solution until the root cause
* is found .
*/
r = i2c_transfer ( client - > adapter , & msg , 1 ) ;
if ( r = = 1 ) {
if ( retries )
dev_err ( & client - > dev ,
[media] smiapp: 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>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:01 -02:00
" sensor i2c stall encountered. retries: %d \n " ,
retries ) ;
2012-03-03 17:19:52 -03:00
return 0 ;
}
usleep_range ( 2000 , 2000 ) ;
}
dev_err ( & client - > dev ,
" wrote 0x%x to offset 0x%x error %d \n " , val , offset , r ) ;
return r ;
}
2014-04-01 08:37:38 -03:00
/*
* Write to a 8 / 16 - bit register .
* Returns zero if successful , or non - zero otherwise .
*/
int smiapp_write ( struct smiapp_sensor * sensor , u32 reg , u32 val )
{
int rval ;
rval = smiapp_call_quirk ( sensor , reg_access , true , & reg , & val ) ;
if ( rval = = - ENOIOCTLCMD )
return 0 ;
if ( rval < 0 )
return rval ;
return smiapp_write_no_quirk ( sensor , reg , val ) ;
}