2012-03-30 06:37:26 -03:00
/*
* Infineon TUA 9001 silicon tuner driver
*
* Copyright ( C ) 2009 Antti Palosaari < crope @ iki . fi >
*
* 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 . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
# include "tua9001.h"
# include "tua9001_priv.h"
/* write register */
static int tua9001_wr_reg ( struct tua9001_priv * priv , u8 reg , u16 val )
{
int ret ;
u8 buf [ 3 ] = { reg , ( val > > 8 ) & 0xff , ( val > > 0 ) & 0xff } ;
struct i2c_msg msg [ 1 ] = {
{
2015-04-15 19:12:34 -03:00
. addr = priv - > i2c_addr ,
2012-03-30 06:37:26 -03:00
. flags = 0 ,
. len = sizeof ( buf ) ,
. buf = buf ,
}
} ;
ret = i2c_transfer ( priv - > i2c , msg , 1 ) ;
if ( ret = = 1 ) {
ret = 0 ;
} else {
2012-09-11 22:27:10 -03:00
dev_warn ( & priv - > i2c - > dev , " %s: i2c wr failed=%d reg=%02x \n " ,
KBUILD_MODNAME , ret , reg ) ;
2012-03-30 06:37:26 -03:00
ret = - EREMOTEIO ;
}
return ret ;
}
static int tua9001_init ( struct dvb_frontend * fe )
{
struct tua9001_priv * priv = fe - > tuner_priv ;
int ret = 0 ;
u8 i ;
struct reg_val data [ ] = {
{ 0x1e , 0x6512 } ,
{ 0x25 , 0xb888 } ,
{ 0x39 , 0x5460 } ,
{ 0x3b , 0x00c0 } ,
{ 0x3a , 0xf000 } ,
{ 0x08 , 0x0000 } ,
{ 0x32 , 0x0030 } ,
{ 0x41 , 0x703a } ,
{ 0x40 , 0x1c78 } ,
{ 0x2c , 0x1c00 } ,
{ 0x36 , 0xc013 } ,
{ 0x37 , 0x6f18 } ,
{ 0x27 , 0x0008 } ,
{ 0x2a , 0x0001 } ,
{ 0x34 , 0x0a40 } ,
} ;
2012-09-11 22:27:10 -03:00
dev_dbg ( & priv - > i2c - > dev , " %s: \n " , __func__ ) ;
2012-09-11 22:27:07 -03:00
if ( fe - > callback ) {
ret = fe - > callback ( priv - > i2c , DVB_FRONTEND_COMPONENT_TUNER ,
TUA9001_CMD_RESETN , 0 ) ;
if ( ret < 0 )
goto err ;
}
2012-03-30 06:37:26 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( data ) ; i + + ) {
ret = tua9001_wr_reg ( priv , data [ i ] . reg , data [ i ] . val ) ;
2012-09-11 22:27:07 -03:00
if ( ret < 0 )
2015-04-15 19:33:13 -03:00
goto err ;
2012-03-30 06:37:26 -03:00
}
2012-09-11 22:27:07 -03:00
err :
if ( ret < 0 )
2012-09-11 22:27:10 -03:00
dev_dbg ( & priv - > i2c - > dev , " %s: failed=%d \n " , __func__ , ret ) ;
2012-09-11 22:27:07 -03:00
return ret ;
}
static int tua9001_sleep ( struct dvb_frontend * fe )
{
struct tua9001_priv * priv = fe - > tuner_priv ;
int ret = 0 ;
2012-09-11 22:27:10 -03:00
dev_dbg ( & priv - > i2c - > dev , " %s: \n " , __func__ ) ;
2012-09-11 22:27:07 -03:00
if ( fe - > callback )
ret = fe - > callback ( priv - > i2c , DVB_FRONTEND_COMPONENT_TUNER ,
TUA9001_CMD_RESETN , 1 ) ;
2012-03-30 06:37:26 -03:00
if ( ret < 0 )
2012-09-11 22:27:10 -03:00
dev_dbg ( & priv - > i2c - > dev , " %s: failed=%d \n " , __func__ , ret ) ;
2012-03-30 06:37:26 -03:00
return ret ;
}
static int tua9001_set_params ( struct dvb_frontend * fe )
{
struct tua9001_priv * priv = fe - > tuner_priv ;
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
2012-10-27 16:26:56 -03:00
int ret = 0 , i ;
2012-03-30 06:37:26 -03:00
u16 val ;
u32 frequency ;
struct reg_val data [ 2 ] ;
2012-09-11 22:27:10 -03:00
dev_dbg ( & priv - > i2c - > dev , " %s: delivery_system=%d frequency=%d " \
" bandwidth_hz=%d \n " , __func__ ,
c - > delivery_system , c - > frequency , c - > bandwidth_hz ) ;
2012-03-30 06:37:26 -03:00
switch ( c - > delivery_system ) {
case SYS_DVBT :
switch ( c - > bandwidth_hz ) {
case 8000000 :
val = 0x0000 ;
break ;
case 7000000 :
val = 0x1000 ;
break ;
case 6000000 :
val = 0x2000 ;
break ;
case 5000000 :
val = 0x3000 ;
break ;
default :
ret = - EINVAL ;
goto err ;
}
break ;
default :
ret = - EINVAL ;
goto err ;
}
data [ 0 ] . reg = 0x04 ;
data [ 0 ] . val = val ;
frequency = ( c - > frequency - 150000000 ) ;
frequency / = 100 ;
frequency * = 48 ;
frequency / = 10000 ;
data [ 1 ] . reg = 0x1f ;
data [ 1 ] . val = frequency ;
2012-09-11 22:27:07 -03:00
if ( fe - > callback ) {
ret = fe - > callback ( priv - > i2c , DVB_FRONTEND_COMPONENT_TUNER ,
TUA9001_CMD_RXEN , 0 ) ;
if ( ret < 0 )
2015-04-15 19:33:13 -03:00
goto err ;
2012-09-11 22:27:07 -03:00
}
2012-03-30 06:37:26 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( data ) ; i + + ) {
ret = tua9001_wr_reg ( priv , data [ i ] . reg , data [ i ] . val ) ;
if ( ret < 0 )
2015-04-15 19:33:13 -03:00
goto err ;
2012-09-11 22:27:07 -03:00
}
if ( fe - > callback ) {
ret = fe - > callback ( priv - > i2c , DVB_FRONTEND_COMPONENT_TUNER ,
TUA9001_CMD_RXEN , 1 ) ;
if ( ret < 0 )
2015-04-15 19:33:13 -03:00
goto err ;
2012-03-30 06:37:26 -03:00
}
err :
if ( ret < 0 )
2012-09-11 22:27:10 -03:00
dev_dbg ( & priv - > i2c - > dev , " %s: failed=%d \n " , __func__ , ret ) ;
2012-03-30 06:37:26 -03:00
return ret ;
}
static int tua9001_get_if_frequency ( struct dvb_frontend * fe , u32 * frequency )
{
2012-09-11 22:27:10 -03:00
struct tua9001_priv * priv = fe - > tuner_priv ;
dev_dbg ( & priv - > i2c - > dev , " %s: \n " , __func__ ) ;
2012-03-30 06:37:26 -03:00
* frequency = 0 ; /* Zero-IF */
return 0 ;
}
static const struct dvb_tuner_ops tua9001_tuner_ops = {
. info = {
. name = " Infineon TUA 9001 " ,
. frequency_min = 170000000 ,
. frequency_max = 862000000 ,
. frequency_step = 0 ,
} ,
. init = tua9001_init ,
2012-09-11 22:27:07 -03:00
. sleep = tua9001_sleep ,
2012-03-30 06:37:26 -03:00
. set_params = tua9001_set_params ,
. get_if_frequency = tua9001_get_if_frequency ,
} ;
2015-04-15 19:12:34 -03:00
static int tua9001_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
struct tua9001_priv * dev ;
struct tua9001_platform_data * pdata = client - > dev . platform_data ;
struct dvb_frontend * fe = pdata - > dvb_frontend ;
int ret ;
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
if ( ! dev ) {
ret = - ENOMEM ;
goto err ;
}
dev - > client = client ;
dev - > i2c_addr = client - > addr ;
dev - > i2c = client - > adapter ;
dev - > fe = pdata - > dvb_frontend ;
if ( fe - > callback ) {
ret = fe - > callback ( client - > adapter ,
DVB_FRONTEND_COMPONENT_TUNER ,
TUA9001_CMD_CEN , 1 ) ;
if ( ret )
goto err_kfree ;
ret = fe - > callback ( client - > adapter ,
DVB_FRONTEND_COMPONENT_TUNER ,
TUA9001_CMD_RXEN , 0 ) ;
if ( ret )
goto err_kfree ;
ret = fe - > callback ( client - > adapter ,
DVB_FRONTEND_COMPONENT_TUNER ,
TUA9001_CMD_RESETN , 1 ) ;
if ( ret )
goto err_kfree ;
}
fe - > tuner_priv = dev ;
memcpy ( & fe - > ops . tuner_ops , & tua9001_tuner_ops ,
sizeof ( struct dvb_tuner_ops ) ) ;
i2c_set_clientdata ( client , dev ) ;
dev_info ( & client - > dev , " Infineon TUA 9001 successfully attached \n " ) ;
return 0 ;
err_kfree :
kfree ( dev ) ;
err :
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
return ret ;
}
static int tua9001_remove ( struct i2c_client * client )
{
struct tua9001_priv * dev = i2c_get_clientdata ( client ) ;
struct dvb_frontend * fe = dev - > fe ;
int ret ;
dev_dbg ( & client - > dev , " \n " ) ;
if ( fe - > callback ) {
ret = fe - > callback ( client - > adapter ,
DVB_FRONTEND_COMPONENT_TUNER ,
TUA9001_CMD_CEN , 0 ) ;
if ( ret )
goto err_kfree ;
}
kfree ( dev ) ;
return 0 ;
err_kfree :
kfree ( dev ) ;
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
return ret ;
}
static const struct i2c_device_id tua9001_id_table [ ] = {
{ " tua9001 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , tua9001_id_table ) ;
static struct i2c_driver tua9001_driver = {
. driver = {
. owner = THIS_MODULE ,
. name = " tua9001 " ,
. suppress_bind_attrs = true ,
} ,
. probe = tua9001_probe ,
. remove = tua9001_remove ,
. id_table = tua9001_id_table ,
} ;
module_i2c_driver ( tua9001_driver ) ;
2012-03-30 06:37:26 -03:00
MODULE_DESCRIPTION ( " Infineon TUA 9001 silicon tuner driver " ) ;
MODULE_AUTHOR ( " Antti Palosaari <crope@iki.fi> " ) ;
MODULE_LICENSE ( " GPL " ) ;