2006-06-26 20:58:46 -03:00
/*
*
*
* Copyright ( C ) 2005 Mike Isely < isely @ pobox . com >
*
* 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
*
* 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 . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
2009-03-07 03:06:09 -03:00
# include <linux/i2c.h>
2011-07-03 14:03:12 -04:00
# include <linux/module.h>
2015-11-10 12:01:44 -02:00
# include <media/i2c/ir-kbd-i2c.h>
2006-06-26 20:58:46 -03:00
# include "pvrusb2-i2c-core.h"
# include "pvrusb2-hdw-internal.h"
# include "pvrusb2-debug.h"
2007-01-22 02:17:55 -03:00
# include "pvrusb2-fx2-cmd.h"
2007-04-28 20:11:03 -03:00
# include "pvrusb2.h"
2006-06-26 20:58:46 -03:00
# define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
/*
This module attempts to implement a compliant I2C adapter for the pvrusb2
2009-03-07 03:06:09 -03:00
device .
2006-06-26 20:58:46 -03:00
*/
2008-04-22 14:41:48 -03:00
static unsigned int i2c_scan ;
2006-06-26 20:58:46 -03:00
module_param ( i2c_scan , int , S_IRUGO | S_IWUSR ) ;
MODULE_PARM_DESC ( i2c_scan , " scan i2c bus at insmod time " ) ;
2007-04-28 20:11:03 -03:00
static int ir_mode [ PVR_NUM ] = { [ 0 . . . PVR_NUM - 1 ] = 1 } ;
module_param_array ( ir_mode , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( ir_mode , " specify: 0=disable IR reception, 1=normal IR " ) ;
2009-05-13 16:56:20 -03:00
static int pvr2_disable_ir_video ;
2009-05-01 22:23:39 -03:00
module_param_named ( disable_autoload_ir_video , pvr2_disable_ir_video ,
int , S_IRUGO | S_IWUSR ) ;
MODULE_PARM_DESC ( disable_autoload_ir_video ,
" 1=do not try to autoload ir_video IR receiver " ) ;
2006-06-26 20:58:46 -03:00
static int pvr2_i2c_write ( struct pvr2_hdw * hdw , /* Context */
u8 i2c_addr , /* I2C address we're talking to */
u8 * data , /* Data to write */
u16 length ) /* Size of data to write */
{
/* Return value - default 0 means success */
int ret ;
if ( ! data ) length = 0 ;
if ( length > ( sizeof ( hdw - > cmd_buffer ) - 3 ) ) {
pvr2_trace ( PVR2_TRACE_ERROR_LEGS ,
" Killing an I2C write to %u that is too large "
" (desired=%u limit=%u) " ,
i2c_addr ,
length , ( unsigned int ) ( sizeof ( hdw - > cmd_buffer ) - 3 ) ) ;
return - ENOTSUPP ;
}
LOCK_TAKE ( hdw - > ctl_lock ) ;
/* Clear the command buffer (likely to be paranoia) */
memset ( hdw - > cmd_buffer , 0 , sizeof ( hdw - > cmd_buffer ) ) ;
/* Set up command buffer for an I2C write */
2007-01-22 02:17:55 -03:00
hdw - > cmd_buffer [ 0 ] = FX2CMD_I2C_WRITE ; /* write prefix */
2006-06-26 20:58:46 -03:00
hdw - > cmd_buffer [ 1 ] = i2c_addr ; /* i2c addr of chip */
hdw - > cmd_buffer [ 2 ] = length ; /* length of what follows */
if ( length ) memcpy ( hdw - > cmd_buffer + 3 , data , length ) ;
/* Do the operation */
ret = pvr2_send_request ( hdw ,
hdw - > cmd_buffer ,
length + 3 ,
hdw - > cmd_buffer ,
1 ) ;
if ( ! ret ) {
if ( hdw - > cmd_buffer [ 0 ] ! = 8 ) {
ret = - EIO ;
if ( hdw - > cmd_buffer [ 0 ] ! = 7 ) {
trace_i2c ( " unexpected status "
" from i2_write[%d]: %d " ,
i2c_addr , hdw - > cmd_buffer [ 0 ] ) ;
}
}
}
LOCK_GIVE ( hdw - > ctl_lock ) ;
return ret ;
}
static int pvr2_i2c_read ( struct pvr2_hdw * hdw , /* Context */
u8 i2c_addr , /* I2C address we're talking to */
u8 * data , /* Data to write */
u16 dlen , /* Size of data to write */
u8 * res , /* Where to put data we read */
u16 rlen ) /* Amount of data to read */
{
/* Return value - default 0 means success */
int ret ;
if ( ! data ) dlen = 0 ;
if ( dlen > ( sizeof ( hdw - > cmd_buffer ) - 4 ) ) {
pvr2_trace ( PVR2_TRACE_ERROR_LEGS ,
" Killing an I2C read to %u that has wlen too large "
" (desired=%u limit=%u) " ,
i2c_addr ,
dlen , ( unsigned int ) ( sizeof ( hdw - > cmd_buffer ) - 4 ) ) ;
return - ENOTSUPP ;
}
if ( res & & ( rlen > ( sizeof ( hdw - > cmd_buffer ) - 1 ) ) ) {
pvr2_trace ( PVR2_TRACE_ERROR_LEGS ,
" Killing an I2C read to %u that has rlen too large "
" (desired=%u limit=%u) " ,
i2c_addr ,
rlen , ( unsigned int ) ( sizeof ( hdw - > cmd_buffer ) - 1 ) ) ;
return - ENOTSUPP ;
}
LOCK_TAKE ( hdw - > ctl_lock ) ;
/* Clear the command buffer (likely to be paranoia) */
memset ( hdw - > cmd_buffer , 0 , sizeof ( hdw - > cmd_buffer ) ) ;
/* Set up command buffer for an I2C write followed by a read */
2007-01-22 02:17:55 -03:00
hdw - > cmd_buffer [ 0 ] = FX2CMD_I2C_READ ; /* read prefix */
2006-06-26 20:58:46 -03:00
hdw - > cmd_buffer [ 1 ] = dlen ; /* arg length */
hdw - > cmd_buffer [ 2 ] = rlen ; /* answer length. Device will send one
more byte ( status ) . */
hdw - > cmd_buffer [ 3 ] = i2c_addr ; /* i2c addr of chip */
if ( dlen ) memcpy ( hdw - > cmd_buffer + 4 , data , dlen ) ;
/* Do the operation */
ret = pvr2_send_request ( hdw ,
hdw - > cmd_buffer ,
4 + dlen ,
hdw - > cmd_buffer ,
rlen + 1 ) ;
if ( ! ret ) {
if ( hdw - > cmd_buffer [ 0 ] ! = 8 ) {
ret = - EIO ;
if ( hdw - > cmd_buffer [ 0 ] ! = 7 ) {
trace_i2c ( " unexpected status "
" from i2_read[%d]: %d " ,
i2c_addr , hdw - > cmd_buffer [ 0 ] ) ;
}
}
}
/* Copy back the result */
if ( res & & rlen ) {
if ( ret ) {
/* Error, just blank out the return buffer */
memset ( res , 0 , rlen ) ;
} else {
memcpy ( res , hdw - > cmd_buffer + 1 , rlen ) ;
}
}
LOCK_GIVE ( hdw - > ctl_lock ) ;
return ret ;
}
/* This is the common low level entry point for doing I2C operations to the
hardware . */
2006-06-30 11:30:20 -03:00
static int pvr2_i2c_basic_op ( struct pvr2_hdw * hdw ,
u8 i2c_addr ,
u8 * wdata ,
u16 wlen ,
u8 * rdata ,
u16 rlen )
2006-06-26 20:58:46 -03:00
{
if ( ! rdata ) rlen = 0 ;
if ( ! wdata ) wlen = 0 ;
if ( rlen | | ! wlen ) {
return pvr2_i2c_read ( hdw , i2c_addr , wdata , wlen , rdata , rlen ) ;
} else {
return pvr2_i2c_write ( hdw , i2c_addr , wdata , wlen ) ;
}
}
2006-10-15 21:35:14 -03:00
/* This is a special entry point for cases of I2C transaction attempts to
the IR receiver . The implementation here simulates the IR receiver by
issuing a command to the FX2 firmware and using that response to return
what the real I2C receiver would have returned . We use this for 24 xxx
devices , where the IR receiver chip has been removed and replaced with
FX2 related logic . */
static int i2c_24xxx_ir ( struct pvr2_hdw * hdw ,
u8 i2c_addr , u8 * wdata , u16 wlen , u8 * rdata , u16 rlen )
{
u8 dat [ 4 ] ;
unsigned int stat ;
if ( ! ( rlen | | wlen ) ) {
/* This is a probe attempt. Just let it succeed. */
return 0 ;
}
/* We don't understand this kind of transaction */
if ( ( wlen ! = 0 ) | | ( rlen = = 0 ) ) return - EIO ;
if ( rlen < 3 ) {
/* Mike Isely <isely@pobox.com> Appears to be a probe
attempt from lirc . Just fill in zeroes and return . If
we try instead to do the full transaction here , then bad
things seem to happen within the lirc driver module
( version 0.8 .0 - 7 sources from Debian , when run under
vanilla 2.6 .17 .6 kernel ) - and I don ' t have the patience
to chase it down . */
if ( rlen > 0 ) rdata [ 0 ] = 0 ;
if ( rlen > 1 ) rdata [ 1 ] = 0 ;
return 0 ;
}
/* Issue a command to the FX2 to read the IR receiver. */
LOCK_TAKE ( hdw - > ctl_lock ) ; do {
2007-01-22 02:17:55 -03:00
hdw - > cmd_buffer [ 0 ] = FX2CMD_GET_IR_CODE ;
2006-10-15 21:35:14 -03:00
stat = pvr2_send_request ( hdw ,
hdw - > cmd_buffer , 1 ,
hdw - > cmd_buffer , 4 ) ;
dat [ 0 ] = hdw - > cmd_buffer [ 0 ] ;
dat [ 1 ] = hdw - > cmd_buffer [ 1 ] ;
dat [ 2 ] = hdw - > cmd_buffer [ 2 ] ;
dat [ 3 ] = hdw - > cmd_buffer [ 3 ] ;
} while ( 0 ) ; LOCK_GIVE ( hdw - > ctl_lock ) ;
/* Give up if that operation failed. */
if ( stat ! = 0 ) return stat ;
/* Mangle the results into something that looks like the real IR
receiver . */
rdata [ 2 ] = 0xc1 ;
if ( dat [ 0 ] ! = 1 ) {
/* No code received. */
rdata [ 0 ] = 0 ;
rdata [ 1 ] = 0 ;
} else {
u16 val ;
/* Mash the FX2 firmware-provided IR code into something
that the normal i2c chip - level driver expects . */
val = dat [ 1 ] ;
val < < = 8 ;
val | = dat [ 2 ] ;
val > > = 1 ;
val & = ~ 0x0003 ;
val | = 0x8000 ;
rdata [ 0 ] = ( val > > 8 ) & 0xffu ;
rdata [ 1 ] = val & 0xffu ;
}
return 0 ;
}
2006-06-26 20:58:46 -03:00
/* This is a special entry point that is entered if an I2C operation is
attempted to a wm8775 chip on model 24 xxx hardware . Autodetect of this
part doesn ' t work , but we know it is really there . So let ' s look for
the autodetect attempt and just return success if we see that . */
static int i2c_hack_wm8775 ( struct pvr2_hdw * hdw ,
u8 i2c_addr , u8 * wdata , u16 wlen , u8 * rdata , u16 rlen )
{
if ( ! ( rlen | | wlen ) ) {
// This is a probe attempt. Just let it succeed.
return 0 ;
}
return pvr2_i2c_basic_op ( hdw , i2c_addr , wdata , wlen , rdata , rlen ) ;
}
2007-04-28 20:11:03 -03:00
/* This is an entry point designed to always fail any attempt to perform a
transfer . We use this to cause certain I2C addresses to not be
probed . */
static int i2c_black_hole ( struct pvr2_hdw * hdw ,
u8 i2c_addr , u8 * wdata , u16 wlen , u8 * rdata , u16 rlen )
{
return - EIO ;
}
2006-06-26 20:58:46 -03:00
/* This is a special entry point that is entered if an I2C operation is
attempted to a cx25840 chip on model 24 xxx hardware . This chip can
sometimes wedge itself . Worse still , when this happens msp3400 can
falsely detect this part and then the system gets hosed up after msp3400
gets confused and dies . What we want to do here is try to keep msp3400
away and also try to notice if the chip is wedged and send a warning to
the system log . */
static int i2c_hack_cx25840 ( struct pvr2_hdw * hdw ,
u8 i2c_addr , u8 * wdata , u16 wlen , u8 * rdata , u16 rlen )
{
int ret ;
unsigned int subaddr ;
u8 wbuf [ 2 ] ;
int state = hdw - > i2c_cx25840_hack_state ;
if ( ! ( rlen | | wlen ) ) {
// Probe attempt - always just succeed and don't bother the
// hardware (this helps to make the state machine further
// down somewhat easier).
return 0 ;
}
if ( state = = 3 ) {
return pvr2_i2c_basic_op ( hdw , i2c_addr , wdata , wlen , rdata , rlen ) ;
}
/* We're looking for the exact pattern where the revision register
is being read . The cx25840 module will always look at the
revision register first . Any other pattern of access therefore
has to be a probe attempt from somebody else so we ' ll reject it .
Normally we could just let each client just probe the part
anyway , but when the cx25840 is wedged , msp3400 will get a false
positive and that just screws things up . . . */
if ( wlen = = 0 ) {
switch ( state ) {
case 1 : subaddr = 0x0100 ; break ;
case 2 : subaddr = 0x0101 ; break ;
default : goto fail ;
}
} else if ( wlen = = 2 ) {
subaddr = ( wdata [ 0 ] < < 8 ) | wdata [ 1 ] ;
switch ( subaddr ) {
case 0x0100 : state = 1 ; break ;
case 0x0101 : state = 2 ; break ;
default : goto fail ;
}
} else {
goto fail ;
}
if ( ! rlen ) goto success ;
state = 0 ;
if ( rlen ! = 1 ) goto fail ;
/* If we get to here then we have a legitimate read for one of the
two revision bytes , so pass it through . */
wbuf [ 0 ] = subaddr > > 8 ;
wbuf [ 1 ] = subaddr ;
ret = pvr2_i2c_basic_op ( hdw , i2c_addr , wbuf , 2 , rdata , rlen ) ;
if ( ( ret ! = 0 ) | | ( * rdata = = 0x04 ) | | ( * rdata = = 0x0a ) ) {
pvr2_trace ( PVR2_TRACE_ERROR_LEGS ,
" WARNING: Detected a wedged cx25840 chip; "
" the device will not work. " ) ;
pvr2_trace ( PVR2_TRACE_ERROR_LEGS ,
" WARNING: Try power cycling the pvrusb2 device. " ) ;
pvr2_trace ( PVR2_TRACE_ERROR_LEGS ,
" WARNING: Disabling further access to the device "
" to prevent other foul-ups. " ) ;
// This blocks all further communication with the part.
2006-06-30 11:35:28 -03:00
hdw - > i2c_func [ 0x44 ] = NULL ;
2006-06-26 20:58:46 -03:00
pvr2_hdw_render_useless ( hdw ) ;
goto fail ;
}
/* Success! */
pvr2_trace ( PVR2_TRACE_CHIPS , " cx25840 appears to be OK. " ) ;
state = 3 ;
success :
hdw - > i2c_cx25840_hack_state = state ;
return 0 ;
fail :
hdw - > i2c_cx25840_hack_state = state ;
return - EIO ;
}
/* This is a very, very limited I2C adapter implementation. We can only
support what we actually know will work on the device . . . */
static int pvr2_i2c_xfer ( struct i2c_adapter * i2c_adap ,
struct i2c_msg msgs [ ] ,
int num )
{
int ret = - ENOTSUPP ;
2006-06-30 11:35:28 -03:00
pvr2_i2c_func funcp = NULL ;
2006-06-26 20:58:46 -03:00
struct pvr2_hdw * hdw = ( struct pvr2_hdw * ) ( i2c_adap - > algo_data ) ;
if ( ! num ) {
ret = - EINVAL ;
goto done ;
}
if ( msgs [ 0 ] . addr < PVR2_I2C_FUNC_CNT ) {
funcp = hdw - > i2c_func [ msgs [ 0 ] . addr ] ;
}
if ( ! funcp ) {
ret = - EIO ;
goto done ;
}
if ( num = = 1 ) {
if ( msgs [ 0 ] . flags & I2C_M_RD ) {
/* Simple read */
u16 tcnt , bcnt , offs ;
if ( ! msgs [ 0 ] . len ) {
/* Length == 0 read. This is a probe. */
2006-06-30 11:35:28 -03:00
if ( funcp ( hdw , msgs [ 0 ] . addr , NULL , 0 , NULL , 0 ) ) {
2006-06-26 20:58:46 -03:00
ret = - EIO ;
goto done ;
}
ret = 1 ;
goto done ;
}
/* If the read is short enough we'll do the whole
thing atomically . Otherwise we have no choice
but to break apart the reads . */
tcnt = msgs [ 0 ] . len ;
offs = 0 ;
while ( tcnt ) {
bcnt = tcnt ;
if ( bcnt > sizeof ( hdw - > cmd_buffer ) - 1 ) {
bcnt = sizeof ( hdw - > cmd_buffer ) - 1 ;
}
2006-06-30 11:35:28 -03:00
if ( funcp ( hdw , msgs [ 0 ] . addr , NULL , 0 ,
2006-06-26 20:58:46 -03:00
msgs [ 0 ] . buf + offs , bcnt ) ) {
ret = - EIO ;
goto done ;
}
offs + = bcnt ;
tcnt - = bcnt ;
}
ret = 1 ;
goto done ;
} else {
/* Simple write */
ret = 1 ;
if ( funcp ( hdw , msgs [ 0 ] . addr ,
2006-06-30 11:35:28 -03:00
msgs [ 0 ] . buf , msgs [ 0 ] . len , NULL , 0 ) ) {
2006-06-26 20:58:46 -03:00
ret = - EIO ;
}
goto done ;
}
} else if ( num = = 2 ) {
if ( msgs [ 0 ] . addr ! = msgs [ 1 ] . addr ) {
trace_i2c ( " i2c refusing 2 phase transfer with "
" conflicting target addresses " ) ;
ret = - ENOTSUPP ;
goto done ;
}
if ( ( ! ( ( msgs [ 0 ] . flags & I2C_M_RD ) ) ) & &
( msgs [ 1 ] . flags & I2C_M_RD ) ) {
u16 tcnt , bcnt , wcnt , offs ;
/* Write followed by atomic read. If the read
portion is short enough we ' ll do the whole thing
atomically . Otherwise we have no choice but to
break apart the reads . */
tcnt = msgs [ 1 ] . len ;
wcnt = msgs [ 0 ] . len ;
offs = 0 ;
while ( tcnt | | wcnt ) {
bcnt = tcnt ;
if ( bcnt > sizeof ( hdw - > cmd_buffer ) - 1 ) {
bcnt = sizeof ( hdw - > cmd_buffer ) - 1 ;
}
if ( funcp ( hdw , msgs [ 0 ] . addr ,
msgs [ 0 ] . buf , wcnt ,
msgs [ 1 ] . buf + offs , bcnt ) ) {
ret = - EIO ;
goto done ;
}
offs + = bcnt ;
tcnt - = bcnt ;
wcnt = 0 ;
}
ret = 2 ;
goto done ;
} else {
trace_i2c ( " i2c refusing complex transfer "
" read0=%d read1=%d " ,
( msgs [ 0 ] . flags & I2C_M_RD ) ,
( msgs [ 1 ] . flags & I2C_M_RD ) ) ;
}
} else {
trace_i2c ( " i2c refusing %d phase transfer " , num ) ;
}
done :
if ( pvrusb2_debug & PVR2_TRACE_I2C_TRAF ) {
unsigned int idx , offs , cnt ;
for ( idx = 0 ; idx < num ; idx + + ) {
cnt = msgs [ idx ] . len ;
printk ( KERN_INFO
" pvrusb2 i2c xfer %u/%u: "
2007-09-08 23:19:32 -03:00
" addr=0x%x len=%d %s " ,
2006-06-26 20:58:46 -03:00
idx + 1 , num ,
msgs [ idx ] . addr ,
cnt ,
( msgs [ idx ] . flags & I2C_M_RD ?
2007-09-08 23:19:32 -03:00
" read " : " write " ) ) ;
2006-06-26 20:58:46 -03:00
if ( ( ret > 0 ) | | ! ( msgs [ idx ] . flags & I2C_M_RD ) ) {
if ( cnt > 8 ) cnt = 8 ;
printk ( " [ " ) ;
for ( offs = 0 ; offs < ( cnt > 8 ? 8 : cnt ) ; offs + + ) {
if ( offs ) printk ( " " ) ;
printk ( " %02x " , msgs [ idx ] . buf [ offs ] ) ;
}
if ( offs < cnt ) printk ( " ... " ) ;
printk ( " ] " ) ;
}
if ( idx + 1 = = num ) {
printk ( " result=%d " , ret ) ;
}
printk ( " \n " ) ;
}
if ( ! num ) {
printk ( KERN_INFO
" pvrusb2 i2c xfer null transfer result=%d \n " ,
ret ) ;
}
}
return ret ;
}
static u32 pvr2_i2c_functionality ( struct i2c_adapter * adap )
{
2007-09-08 23:19:32 -03:00
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C ;
2006-06-26 20:58:46 -03:00
}
static struct i2c_algorithm pvr2_i2c_algo_template = {
. master_xfer = pvr2_i2c_xfer ,
. functionality = pvr2_i2c_functionality ,
} ;
static struct i2c_adapter pvr2_i2c_adap_template = {
. owner = THIS_MODULE ,
2009-03-06 23:51:35 -03:00
. class = 0 ,
2006-06-26 20:58:46 -03:00
} ;
2008-08-31 21:06:11 -03:00
/* Return true if device exists at given address */
static int do_i2c_probe ( struct pvr2_hdw * hdw , int addr )
2006-06-26 20:58:46 -03:00
{
struct i2c_msg msg [ 1 ] ;
2008-08-31 21:06:11 -03:00
int rc ;
2006-06-26 20:58:46 -03:00
msg [ 0 ] . addr = 0 ;
msg [ 0 ] . flags = I2C_M_RD ;
msg [ 0 ] . len = 0 ;
2006-06-30 11:35:28 -03:00
msg [ 0 ] . buf = NULL ;
2008-08-31 21:06:11 -03:00
msg [ 0 ] . addr = addr ;
rc = i2c_transfer ( & hdw - > i2c_adap , msg , ARRAY_SIZE ( msg ) ) ;
return rc = = 1 ;
}
static void do_i2c_scan ( struct pvr2_hdw * hdw )
{
int i ;
printk ( KERN_INFO " %s: i2c scan beginning \n " , hdw - > name ) ;
2006-06-26 20:58:46 -03:00
for ( i = 0 ; i < 128 ; i + + ) {
2008-08-31 21:06:11 -03:00
if ( do_i2c_probe ( hdw , i ) ) {
printk ( KERN_INFO " %s: i2c scan: found device @ 0x%x \n " ,
hdw - > name , i ) ;
}
2006-06-26 20:58:46 -03:00
}
2008-08-31 21:06:11 -03:00
printk ( KERN_INFO " %s: i2c scan done. \n " , hdw - > name ) ;
2006-06-26 20:58:46 -03:00
}
2009-05-01 22:23:39 -03:00
static void pvr2_i2c_register_ir ( struct pvr2_hdw * hdw )
{
struct i2c_board_info info ;
2011-01-16 21:21:03 -03:00
struct IR_i2c_init_data * init_data = & hdw - > ir_init_data ;
2009-05-01 22:23:39 -03:00
if ( pvr2_disable_ir_video ) {
pvr2_trace ( PVR2_TRACE_INFO ,
" Automatic binding of ir_video has been disabled. " ) ;
return ;
}
2011-01-16 21:21:03 -03:00
memset ( & info , 0 , sizeof ( struct i2c_board_info ) ) ;
switch ( hdw - > ir_scheme_active ) {
case PVR2_IR_SCHEME_24XXX : /* FX2-controlled IR */
case PVR2_IR_SCHEME_29XXX : /* Original 29xxx device */
2011-01-24 12:18:48 -03:00
init_data - > ir_codes = RC_MAP_HAUPPAUGE ;
2011-01-16 21:21:03 -03:00
init_data - > internal_get_key_func = IR_KBD_GET_KEY_HAUP ;
2012-10-11 19:11:54 -03:00
init_data - > type = RC_BIT_RC5 ;
2011-01-16 21:21:03 -03:00
init_data - > name = hdw - > hdw_desc - > description ;
init_data - > polling_interval = 100 ; /* ms From ir-kbd-i2c */
/* IR Receiver */
info . addr = 0x18 ;
info . platform_data = init_data ;
strlcpy ( info . type , " ir_video " , I2C_NAME_SIZE ) ;
pvr2_trace ( PVR2_TRACE_INFO , " Binding %s to i2c address 0x%02x. " ,
info . type , info . addr ) ;
i2c_new_device ( & hdw - > i2c_adap , & info ) ;
break ;
case PVR2_IR_SCHEME_ZILOG : /* HVR-1950 style */
case PVR2_IR_SCHEME_24XXX_MCE : /* 24xxx MCE device */
2011-01-24 12:18:48 -03:00
init_data - > ir_codes = RC_MAP_HAUPPAUGE ;
2011-01-16 21:21:03 -03:00
init_data - > internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR ;
2012-10-11 19:11:54 -03:00
init_data - > type = RC_BIT_RC5 ;
2011-01-16 21:21:03 -03:00
init_data - > name = hdw - > hdw_desc - > description ;
/* IR Receiver */
info . addr = 0x71 ;
info . platform_data = init_data ;
strlcpy ( info . type , " ir_rx_z8f0811_haup " , I2C_NAME_SIZE ) ;
pvr2_trace ( PVR2_TRACE_INFO , " Binding %s to i2c address 0x%02x. " ,
info . type , info . addr ) ;
i2c_new_device ( & hdw - > i2c_adap , & info ) ;
/* IR Trasmitter */
info . addr = 0x70 ;
info . platform_data = init_data ;
strlcpy ( info . type , " ir_tx_z8f0811_haup " , I2C_NAME_SIZE ) ;
pvr2_trace ( PVR2_TRACE_INFO , " Binding %s to i2c address 0x%02x. " ,
info . type , info . addr ) ;
i2c_new_device ( & hdw - > i2c_adap , & info ) ;
break ;
default :
2009-05-01 22:23:39 -03:00
/* The device either doesn't support I2C-based IR or we
don ' t know ( yet ) how to operate IR on the device . */
2011-01-16 21:21:03 -03:00
break ;
2009-05-01 22:23:39 -03:00
}
}
2006-06-26 20:58:46 -03:00
void pvr2_i2c_core_init ( struct pvr2_hdw * hdw )
{
unsigned int idx ;
2006-10-15 21:35:14 -03:00
/* The default action for all possible I2C addresses is just to do
the transfer normally . */
2006-06-26 20:58:46 -03:00
for ( idx = 0 ; idx < PVR2_I2C_FUNC_CNT ; idx + + ) {
hdw - > i2c_func [ idx ] = pvr2_i2c_basic_op ;
}
2006-10-15 21:35:14 -03:00
/* However, deal with various special cases for 24xxx hardware. */
2007-04-28 20:11:03 -03:00
if ( ir_mode [ hdw - > unit_number ] = = 0 ) {
printk ( KERN_INFO " %s: IR disabled \n " , hdw - > name ) ;
hdw - > i2c_func [ 0x18 ] = i2c_black_hole ;
} else if ( ir_mode [ hdw - > unit_number ] = = 1 ) {
2009-04-06 01:51:38 -03:00
if ( hdw - > ir_scheme_active = = PVR2_IR_SCHEME_24XXX ) {
/* Set up translation so that our IR looks like a
29 xxx device */
2007-04-28 20:11:03 -03:00
hdw - > i2c_func [ 0x18 ] = i2c_24xxx_ir ;
}
}
2007-11-26 01:53:12 -03:00
if ( hdw - > hdw_desc - > flag_has_cx25840 ) {
2006-06-26 20:58:46 -03:00
hdw - > i2c_func [ 0x44 ] = i2c_hack_cx25840 ;
}
2007-11-26 01:53:12 -03:00
if ( hdw - > hdw_desc - > flag_has_wm8775 ) {
hdw - > i2c_func [ 0x1b ] = i2c_hack_wm8775 ;
}
2006-06-26 20:58:46 -03:00
// Configure the adapter and set up everything else related to it.
2012-10-23 15:57:09 -03:00
hdw - > i2c_adap = pvr2_i2c_adap_template ;
hdw - > i2c_algo = pvr2_i2c_algo_template ;
2006-06-26 20:58:46 -03:00
strlcpy ( hdw - > i2c_adap . name , hdw - > name , sizeof ( hdw - > i2c_adap . name ) ) ;
2007-02-13 22:09:03 +01:00
hdw - > i2c_adap . dev . parent = & hdw - > usb_dev - > dev ;
2006-06-26 20:58:46 -03:00
hdw - > i2c_adap . algo = & hdw - > i2c_algo ;
hdw - > i2c_adap . algo_data = hdw ;
hdw - > i2c_linked = ! 0 ;
2009-03-06 23:42:20 -03:00
i2c_set_adapdata ( & hdw - > i2c_adap , & hdw - > v4l2_dev ) ;
2006-06-26 20:58:46 -03:00
i2c_add_adapter ( & hdw - > i2c_adap ) ;
2008-08-31 21:06:11 -03:00
if ( hdw - > i2c_func [ 0x18 ] = = i2c_24xxx_ir ) {
/* Probe for a different type of IR receiver on this
2009-04-06 01:51:38 -03:00
device . This is really the only way to differentiate
older 24 xxx devices from 24 xxx variants that include an
IR blaster . If the IR blaster is present , the IR
receiver is part of that chip and thus we must disable
the emulated IR receiver . */
2008-08-31 21:06:11 -03:00
if ( do_i2c_probe ( hdw , 0x71 ) ) {
pvr2_trace ( PVR2_TRACE_INFO ,
" Device has newer IR hardware; "
" disabling unneeded virtual IR device " ) ;
hdw - > i2c_func [ 0x18 ] = NULL ;
2009-04-06 01:51:38 -03:00
/* Remember that this is a different device... */
hdw - > ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE ;
2008-08-31 21:06:11 -03:00
}
}
2006-06-26 20:58:46 -03:00
if ( i2c_scan ) do_i2c_scan ( hdw ) ;
2009-05-01 22:23:39 -03:00
pvr2_i2c_register_ir ( hdw ) ;
2006-06-26 20:58:46 -03:00
}
void pvr2_i2c_core_done ( struct pvr2_hdw * hdw )
{
if ( hdw - > i2c_linked ) {
i2c_del_adapter ( & hdw - > i2c_adap ) ;
hdw - > i2c_linked = 0 ;
}
}