2006-01-09 20:25:35 +03:00
/*
cx88 - vp3054 - i2c . c - - support for the secondary I2C bus of the
DNTV Live ! DVB - T Pro ( VP - 3054 ) , wired as :
GPIO [ 0 ] - > SCL , GPIO [ 1 ] - > SDA
( c ) 2005 Chris Pascoe < c . pascoe @ itee . uq . edu . au >
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 .
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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/module.h>
# include <linux/init.h>
# include <asm/io.h>
# include "cx88.h"
# include "cx88-vp3054-i2c.h"
2006-01-13 19:10:24 +03:00
MODULE_DESCRIPTION ( " driver for cx2388x VP3054 design " ) ;
MODULE_AUTHOR ( " Chris Pascoe <c.pascoe@itee.uq.edu.au> " ) ;
MODULE_LICENSE ( " GPL " ) ;
2006-01-09 20:25:35 +03:00
/* ----------------------------------------------------------------------- */
static void vp3054_bit_setscl ( void * data , int state )
{
struct cx8802_dev * dev = data ;
struct cx88_core * core = dev - > core ;
2007-10-14 09:52:16 +04:00
struct vp3054_i2c_state * vp3054_i2c = dev - > vp3054 ;
2006-01-09 20:25:35 +03:00
if ( state ) {
vp3054_i2c - > state | = 0x0001 ; /* SCL high */
vp3054_i2c - > state & = ~ 0x0100 ; /* external pullup */
} else {
vp3054_i2c - > state & = ~ 0x0001 ; /* SCL low */
vp3054_i2c - > state | = 0x0100 ; /* drive pin */
}
cx_write ( MO_GP0_IO , 0x010000 | vp3054_i2c - > state ) ;
cx_read ( MO_GP0_IO ) ;
}
static void vp3054_bit_setsda ( void * data , int state )
{
struct cx8802_dev * dev = data ;
struct cx88_core * core = dev - > core ;
2007-10-14 09:52:16 +04:00
struct vp3054_i2c_state * vp3054_i2c = dev - > vp3054 ;
2006-01-09 20:25:35 +03:00
if ( state ) {
vp3054_i2c - > state | = 0x0002 ; /* SDA high */
vp3054_i2c - > state & = ~ 0x0200 ; /* tristate pin */
} else {
vp3054_i2c - > state & = ~ 0x0002 ; /* SDA low */
vp3054_i2c - > state | = 0x0200 ; /* drive pin */
}
cx_write ( MO_GP0_IO , 0x020000 | vp3054_i2c - > state ) ;
cx_read ( MO_GP0_IO ) ;
}
static int vp3054_bit_getscl ( void * data )
{
struct cx8802_dev * dev = data ;
struct cx88_core * core = dev - > core ;
u32 state ;
state = cx_read ( MO_GP0_IO ) ;
return ( state & 0x01 ) ? 1 : 0 ;
}
static int vp3054_bit_getsda ( void * data )
{
struct cx8802_dev * dev = data ;
struct cx88_core * core = dev - > core ;
u32 state ;
state = cx_read ( MO_GP0_IO ) ;
return ( state & 0x02 ) ? 1 : 0 ;
}
/* ----------------------------------------------------------------------- */
2007-07-02 01:37:51 +04:00
static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {
2006-01-09 20:25:35 +03:00
. setsda = vp3054_bit_setsda ,
. setscl = vp3054_bit_setscl ,
. getsda = vp3054_bit_getsda ,
. getscl = vp3054_bit_getscl ,
. udelay = 16 ,
. timeout = 200 ,
} ;
/* ----------------------------------------------------------------------- */
int vp3054_i2c_probe ( struct cx8802_dev * dev )
{
struct cx88_core * core = dev - > core ;
struct vp3054_i2c_state * vp3054_i2c ;
int rc ;
2007-08-15 21:41:57 +04:00
if ( core - > boardnr ! = CX88_BOARD_DNTV_LIVE_DVB_T_PRO )
2006-01-09 20:25:35 +03:00
return 0 ;
2007-10-14 09:52:16 +04:00
vp3054_i2c = kzalloc ( sizeof ( * vp3054_i2c ) , GFP_KERNEL ) ;
if ( vp3054_i2c = = NULL )
2006-01-09 20:25:35 +03:00
return - ENOMEM ;
2007-10-14 09:52:16 +04:00
dev - > vp3054 = vp3054_i2c ;
2006-01-09 20:25:35 +03:00
memcpy ( & vp3054_i2c - > algo , & vp3054_i2c_algo_template ,
sizeof ( vp3054_i2c - > algo ) ) ;
vp3054_i2c - > adap . class | = I2C_CLASS_TV_DIGITAL ;
vp3054_i2c - > adap . dev . parent = & dev - > pci - > dev ;
strlcpy ( vp3054_i2c - > adap . name , core - > name ,
sizeof ( vp3054_i2c - > adap . name ) ) ;
2007-07-02 01:37:51 +04:00
vp3054_i2c - > adap . owner = THIS_MODULE ;
vp3054_i2c - > adap . id = I2C_HW_B_CX2388x ;
2006-01-09 20:25:35 +03:00
vp3054_i2c - > algo . data = dev ;
i2c_set_adapdata ( & vp3054_i2c - > adap , dev ) ;
vp3054_i2c - > adap . algo_data = & vp3054_i2c - > algo ;
vp3054_bit_setscl ( dev , 1 ) ;
vp3054_bit_setsda ( dev , 1 ) ;
rc = i2c_bit_add_bus ( & vp3054_i2c - > adap ) ;
if ( 0 ! = rc ) {
printk ( " %s: vp3054_i2c register FAILED \n " , core - > name ) ;
2007-10-14 09:52:16 +04:00
kfree ( dev - > vp3054 ) ;
dev - > vp3054 = NULL ;
2006-01-09 20:25:35 +03:00
}
return rc ;
}
void vp3054_i2c_remove ( struct cx8802_dev * dev )
{
2007-10-14 09:52:16 +04:00
struct vp3054_i2c_state * vp3054_i2c = dev - > vp3054 ;
2006-01-09 20:25:35 +03:00
if ( vp3054_i2c = = NULL | |
2007-08-15 21:41:57 +04:00
dev - > core - > boardnr ! = CX88_BOARD_DNTV_LIVE_DVB_T_PRO )
2006-01-09 20:25:35 +03:00
return ;
2006-12-10 23:21:33 +03:00
i2c_del_adapter ( & vp3054_i2c - > adap ) ;
2006-01-09 20:25:35 +03:00
kfree ( vp3054_i2c ) ;
}
EXPORT_SYMBOL ( vp3054_i2c_probe ) ;
EXPORT_SYMBOL ( vp3054_i2c_remove ) ;