2019-05-27 08:55:06 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2017-11-23 03:24:45 -05:00
/*
* NXP TDA18250 silicon tuner driver
*
* Copyright ( C ) 2017 Olli Salonen < olli . salonen @ iki . fi >
*/
# include "tda18250_priv.h"
# include <linux/regmap.h>
static const struct dvb_tuner_ops tda18250_ops ;
static int tda18250_power_control ( struct dvb_frontend * fe ,
unsigned int power_state )
{
struct i2c_client * client = fe - > tuner_priv ;
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
int ret ;
unsigned int utmp ;
dev_dbg ( & client - > dev , " power state: %d " , power_state ) ;
switch ( power_state ) {
case TDA18250_POWER_NORMAL :
ret = regmap_write_bits ( dev - > regmap , R06_POWER2 , 0x07 , 0x00 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R25_REF , 0xc0 , 0xc0 ) ;
if ( ret )
goto err ;
break ;
case TDA18250_POWER_STANDBY :
if ( dev - > loopthrough ) {
ret = regmap_write_bits ( dev - > regmap ,
R25_REF , 0xc0 , 0x80 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap ,
R06_POWER2 , 0x07 , 0x02 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap ,
R10_LT1 , 0x80 , 0x00 ) ;
if ( ret )
goto err ;
} else {
ret = regmap_write_bits ( dev - > regmap ,
R25_REF , 0xc0 , 0x80 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap ,
R06_POWER2 , 0x07 , 0x01 ) ;
if ( ret )
goto err ;
ret = regmap_read ( dev - > regmap ,
R0D_AGC12 , & utmp ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap ,
R0D_AGC12 , 0x03 , 0x03 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap ,
R10_LT1 , 0x80 , 0x80 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap ,
R0D_AGC12 , 0x03 , utmp & 0x03 ) ;
if ( ret )
goto err ;
}
break ;
default :
ret = - EINVAL ;
goto err ;
}
return 0 ;
err :
return ret ;
}
static int tda18250_wait_for_irq ( struct dvb_frontend * fe ,
int maxwait , int step , u8 irq )
{
struct i2c_client * client = fe - > tuner_priv ;
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
int ret ;
unsigned long timeout ;
bool triggered ;
unsigned int utmp ;
triggered = false ;
timeout = jiffies + msecs_to_jiffies ( maxwait ) ;
while ( ! time_after ( jiffies , timeout ) ) {
// check for the IRQ
ret = regmap_read ( dev - > regmap , R08_IRQ1 , & utmp ) ;
if ( ret )
goto err ;
if ( ( utmp & irq ) = = irq ) {
triggered = true ;
break ;
}
msleep ( step ) ;
}
dev_dbg ( & client - > dev , " waited IRQ (0x%02x) %d ms, triggered: %s " , irq ,
jiffies_to_msecs ( jiffies ) -
( jiffies_to_msecs ( timeout ) - maxwait ) ,
triggered ? " true " : " false " ) ;
if ( ! triggered )
return - ETIMEDOUT ;
return 0 ;
err :
return ret ;
}
static int tda18250_init ( struct dvb_frontend * fe )
{
struct i2c_client * client = fe - > tuner_priv ;
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
int ret , i ;
/* default values for various regs */
static const u8 init_regs [ ] [ 2 ] = {
{ R0C_AGC11 , 0xc7 } ,
{ R0D_AGC12 , 0x5d } ,
{ R0E_AGC13 , 0x40 } ,
{ R0F_AGC14 , 0x0e } ,
{ R10_LT1 , 0x47 } ,
{ R11_LT2 , 0x4e } ,
{ R12_AGC21 , 0x26 } ,
{ R13_AGC22 , 0x60 } ,
{ R18_AGC32 , 0x37 } ,
{ R19_AGC33 , 0x09 } ,
{ R1A_AGCK , 0x00 } ,
{ R1E_WI_FI , 0x29 } ,
{ R1F_RF_BPF , 0x06 } ,
{ R20_IR_MIX , 0xc6 } ,
{ R21_IF_AGC , 0x00 } ,
{ R2C_PS1 , 0x75 } ,
{ R2D_PS2 , 0x06 } ,
{ R2E_PS3 , 0x07 } ,
{ R30_RSSI2 , 0x0e } ,
{ R31_IRQ_CTRL , 0x00 } ,
{ R39_SD5 , 0x00 } ,
{ R3B_REGU , 0x55 } ,
{ R3C_RCCAL1 , 0xa7 } ,
{ R3F_IRCAL2 , 0x85 } ,
{ R40_IRCAL3 , 0x87 } ,
{ R41_IRCAL4 , 0xc0 } ,
{ R43_PD1 , 0x40 } ,
{ R44_PD2 , 0xc0 } ,
{ R46_CPUMP , 0x0c } ,
{ R47_LNAPOL , 0x64 } ,
{ R4B_XTALOSC1 , 0x30 } ,
{ R59_AGC2_UP2 , 0x05 } ,
{ R5B_AGC_AUTO , 0x07 } ,
{ R5C_AGC_DEBUG , 0x00 } ,
} ;
/* crystal related regs depend on frequency */
static const u8 xtal_regs [ ] [ 5 ] = {
/* reg: 4d 4e 4f 50 51 */
[ TDA18250_XTAL_FREQ_16MHZ ] = { 0x3e , 0x80 , 0x50 , 0x00 , 0x20 } ,
[ TDA18250_XTAL_FREQ_24MHZ ] = { 0x5d , 0xc0 , 0xec , 0x00 , 0x18 } ,
[ TDA18250_XTAL_FREQ_25MHZ ] = { 0x61 , 0xa8 , 0xec , 0x80 , 0x19 } ,
[ TDA18250_XTAL_FREQ_27MHZ ] = { 0x69 , 0x78 , 0x8d , 0x80 , 0x1b } ,
[ TDA18250_XTAL_FREQ_30MHZ ] = { 0x75 , 0x30 , 0x8f , 0x00 , 0x1e } ,
} ;
dev_dbg ( & client - > dev , " \n " ) ;
ret = tda18250_power_control ( fe , TDA18250_POWER_NORMAL ) ;
if ( ret )
goto err ;
msleep ( 20 ) ;
if ( dev - > warm )
goto warm ;
/* set initial register values */
for ( i = 0 ; i < ARRAY_SIZE ( init_regs ) ; i + + ) {
ret = regmap_write ( dev - > regmap , init_regs [ i ] [ 0 ] ,
init_regs [ i ] [ 1 ] ) ;
if ( ret )
goto err ;
}
/* set xtal related regs */
ret = regmap_bulk_write ( dev - > regmap , R4D_XTALFLX1 ,
xtal_regs [ dev - > xtal_freq ] , 5 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R10_LT1 , 0x80 ,
dev - > loopthrough ? 0x00 : 0x80 ) ;
if ( ret )
goto err ;
/* clear IRQ */
ret = regmap_write ( dev - > regmap , R0A_IRQ3 , TDA18250_IRQ_HW_INIT ) ;
if ( ret )
goto err ;
/* start HW init */
ret = regmap_write ( dev - > regmap , R2A_MSM1 , 0x70 ) ;
if ( ret )
goto err ;
ret = regmap_write ( dev - > regmap , R2B_MSM2 , 0x01 ) ;
if ( ret )
goto err ;
ret = tda18250_wait_for_irq ( fe , 500 , 10 , TDA18250_IRQ_HW_INIT ) ;
if ( ret )
goto err ;
/* tuner calibration */
ret = regmap_write ( dev - > regmap , R2A_MSM1 , 0x02 ) ;
if ( ret )
goto err ;
ret = regmap_write ( dev - > regmap , R2B_MSM2 , 0x01 ) ;
if ( ret )
goto err ;
ret = tda18250_wait_for_irq ( fe , 500 , 10 , TDA18250_IRQ_CAL ) ;
if ( ret )
goto err ;
dev - > warm = true ;
warm :
/* power up LNA */
ret = regmap_write_bits ( dev - > regmap , R0C_AGC11 , 0x80 , 0x00 ) ;
if ( ret )
goto err ;
return 0 ;
err :
dev_dbg ( & client - > dev , " failed=%d " , ret ) ;
return ret ;
}
static int tda18250_set_agc ( struct dvb_frontend * fe )
{
struct i2c_client * client = fe - > tuner_priv ;
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
int ret ;
u8 utmp , utmp2 ;
dev_dbg ( & client - > dev , " \n " ) ;
ret = regmap_write_bits ( dev - > regmap , R1F_RF_BPF , 0x87 , 0x06 ) ;
if ( ret )
goto err ;
utmp = ( ( c - > frequency < 100000000 ) & &
( ( c - > delivery_system = = SYS_DVBC_ANNEX_A ) | |
( c - > delivery_system = = SYS_DVBC_ANNEX_C ) ) & &
( c - > bandwidth_hz = = 6000000 ) ) ? 0x80 : 0x00 ;
ret = regmap_write ( dev - > regmap , R5A_H3H5 , utmp ) ;
if ( ret )
goto err ;
/* AGC1 */
switch ( c - > delivery_system ) {
case SYS_ATSC :
case SYS_DVBT :
case SYS_DVBT2 :
utmp = 4 ;
break ;
default : /* DVB-C/QAM */
switch ( c - > bandwidth_hz ) {
case 6000000 :
utmp = ( c - > frequency < 800000000 ) ? 6 : 4 ;
break ;
default : /* 7.935 and 8 MHz */
utmp = ( c - > frequency < 100000000 ) ? 2 : 3 ;
break ;
}
break ;
}
ret = regmap_write_bits ( dev - > regmap , R0C_AGC11 , 0x07 , utmp ) ;
if ( ret )
goto err ;
/* AGC2 */
switch ( c - > delivery_system ) {
case SYS_ATSC :
case SYS_DVBT :
case SYS_DVBT2 :
utmp = ( c - > frequency < 320000000 ) ? 20 : 16 ;
utmp2 = ( c - > frequency < 320000000 ) ? 22 : 18 ;
break ;
default : /* DVB-C/QAM */
switch ( c - > bandwidth_hz ) {
case 6000000 :
if ( c - > frequency < 600000000 ) {
utmp = 18 ;
utmp2 = 22 ;
} else if ( c - > frequency < 800000000 ) {
utmp = 16 ;
utmp2 = 20 ;
} else {
utmp = 14 ;
utmp2 = 16 ;
}
break ;
default : /* 7.935 and 8 MHz */
utmp = ( c - > frequency < 320000000 ) ? 16 : 18 ;
utmp2 = ( c - > frequency < 320000000 ) ? 18 : 20 ;
break ;
}
break ;
}
ret = regmap_write_bits ( dev - > regmap , R58_AGC2_UP1 , 0x1f , utmp2 + 8 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R13_AGC22 , 0x1f , utmp ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R14_AGC23 , 0x1f , utmp2 ) ;
if ( ret )
goto err ;
switch ( c - > delivery_system ) {
case SYS_ATSC :
case SYS_DVBT :
case SYS_DVBT2 :
utmp = 98 ;
break ;
default : /* DVB-C/QAM */
utmp = 90 ;
break ;
}
ret = regmap_write_bits ( dev - > regmap , R16_AGC25 , 0xf8 , utmp ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R12_AGC21 , 0x60 ,
( c - > frequency > 800000000 ) ? 0x40 : 0x20 ) ;
if ( ret )
goto err ;
/* AGC3 */
switch ( c - > delivery_system ) {
case SYS_ATSC :
case SYS_DVBT :
case SYS_DVBT2 :
utmp = ( c - > frequency < 320000000 ) ? 5 : 7 ;
utmp2 = ( c - > frequency < 320000000 ) ? 10 : 12 ;
break ;
default : /* DVB-C/QAM */
utmp = 7 ;
utmp2 = 12 ;
break ;
}
ret = regmap_write ( dev - > regmap , R17_AGC31 , ( utmp < < 4 ) | utmp2 ) ;
if ( ret )
goto err ;
/* S2D */
switch ( c - > delivery_system ) {
case SYS_ATSC :
case SYS_DVBT :
case SYS_DVBT2 :
if ( c - > bandwidth_hz = = 8000000 )
utmp = 0x04 ;
else
utmp = ( c - > frequency < 320000000 ) ? 0x04 : 0x02 ;
break ;
default : /* DVB-C/QAM */
if ( c - > bandwidth_hz = = 6000000 )
utmp = ( ( c - > frequency > 172544000 ) & &
( c - > frequency < 320000000 ) ) ? 0x04 : 0x02 ;
else /* 7.935 and 8 MHz */
utmp = ( ( c - > frequency > 320000000 ) & &
( c - > frequency < 600000000 ) ) ? 0x02 : 0x04 ;
break ;
}
ret = regmap_write_bits ( dev - > regmap , R20_IR_MIX , 0x06 , utmp ) ;
if ( ret )
goto err ;
switch ( c - > delivery_system ) {
case SYS_ATSC :
case SYS_DVBT :
case SYS_DVBT2 :
utmp = 0 ;
break ;
default : /* DVB-C/QAM */
utmp = ( c - > frequency < 600000000 ) ? 0 : 3 ;
break ;
}
ret = regmap_write_bits ( dev - > regmap , R16_AGC25 , 0x03 , utmp ) ;
if ( ret )
goto err ;
utmp = 0x09 ;
switch ( c - > delivery_system ) {
case SYS_ATSC :
case SYS_DVBT :
case SYS_DVBT2 :
if ( c - > bandwidth_hz = = 8000000 )
utmp = 0x0c ;
break ;
default : /* DVB-C/QAM */
utmp = 0x0c ;
break ;
}
ret = regmap_write_bits ( dev - > regmap , R0F_AGC14 , 0x3f , utmp ) ;
if ( ret )
goto err ;
return 0 ;
err :
dev_dbg ( & client - > dev , " failed=%d " , ret ) ;
return ret ;
}
static int tda18250_pll_calc ( struct dvb_frontend * fe , u8 * rdiv ,
u8 * ndiv , u8 * icp )
{
struct i2c_client * client = fe - > tuner_priv ;
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
int ret ;
unsigned int uval , exp , lopd , scale ;
unsigned long fvco ;
ret = regmap_read ( dev - > regmap , R34_MD1 , & uval ) ;
if ( ret )
goto err ;
exp = ( uval & 0x70 ) > > 4 ;
if ( exp > 5 )
exp = 0 ;
lopd = 1 < < ( exp - 1 ) ;
scale = uval & 0x0f ;
fvco = lopd * scale * ( ( c - > frequency / 1000 ) + dev - > if_frequency ) ;
switch ( dev - > xtal_freq ) {
case TDA18250_XTAL_FREQ_16MHZ :
* rdiv = 1 ;
* ndiv = 0 ;
* icp = ( fvco < 6622000 ) ? 0x05 : 0x02 ;
break ;
case TDA18250_XTAL_FREQ_24MHZ :
case TDA18250_XTAL_FREQ_25MHZ :
* rdiv = 3 ;
* ndiv = 1 ;
* icp = ( fvco < 6622000 ) ? 0x05 : 0x02 ;
break ;
case TDA18250_XTAL_FREQ_27MHZ :
if ( fvco < 6643000 ) {
* rdiv = 2 ;
* ndiv = 0 ;
* icp = 0x05 ;
} else if ( fvco < 6811000 ) {
* rdiv = 2 ;
* ndiv = 0 ;
* icp = 0x06 ;
} else {
* rdiv = 3 ;
* ndiv = 1 ;
* icp = 0x02 ;
}
break ;
case TDA18250_XTAL_FREQ_30MHZ :
* rdiv = 2 ;
* ndiv = 0 ;
* icp = ( fvco < 6811000 ) ? 0x05 : 0x02 ;
break ;
default :
return - EINVAL ;
}
dev_dbg ( & client - > dev ,
" lopd=%d scale=%u fvco=%lu, rdiv=%d ndiv=%d icp=%d " ,
lopd , scale , fvco , * rdiv , * ndiv , * icp ) ;
return 0 ;
err :
return ret ;
}
static int tda18250_set_params ( struct dvb_frontend * fe )
{
struct i2c_client * client = fe - > tuner_priv ;
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
u32 if_khz ;
int ret ;
unsigned int i , j ;
u8 utmp ;
u8 buf [ 3 ] ;
# define REG 0
# define MASK 1
# define DVBT_6 2
# define DVBT_7 3
# define DVBT_8 4
# define DVBC_6 5
# define DVBC_8 6
# define ATSC 7
static const u8 delsys_params [ ] [ 16 ] = {
[ REG ] = { 0x22 , 0x23 , 0x24 , 0x21 , 0x0d , 0x0c , 0x0f , 0x14 ,
0x0e , 0x12 , 0x58 , 0x59 , 0x1a , 0x19 , 0x1e , 0x30 } ,
[ MASK ] = { 0x77 , 0xff , 0xff , 0x87 , 0xf0 , 0x78 , 0x07 , 0xe0 ,
0x60 , 0x0f , 0x60 , 0x0f , 0x33 , 0x30 , 0x80 , 0x06 } ,
[ DVBT_6 ] = { 0x51 , 0x03 , 0x83 , 0x82 , 0x40 , 0x48 , 0x01 , 0xe0 ,
0x60 , 0x0f , 0x60 , 0x05 , 0x03 , 0x10 , 0x00 , 0x04 } ,
[ DVBT_7 ] = { 0x52 , 0x03 , 0x85 , 0x82 , 0x40 , 0x48 , 0x01 , 0xe0 ,
0x60 , 0x0f , 0x60 , 0x05 , 0x03 , 0x10 , 0x00 , 0x04 } ,
[ DVBT_8 ] = { 0x53 , 0x03 , 0x87 , 0x82 , 0x40 , 0x48 , 0x06 , 0xe0 ,
0x60 , 0x07 , 0x60 , 0x05 , 0x03 , 0x10 , 0x00 , 0x04 } ,
[ DVBC_6 ] = { 0x32 , 0x05 , 0x86 , 0x82 , 0x50 , 0x00 , 0x06 , 0x60 ,
0x40 , 0x0e , 0x60 , 0x05 , 0x33 , 0x10 , 0x00 , 0x04 } ,
[ DVBC_8 ] = { 0x53 , 0x03 , 0x88 , 0x82 , 0x50 , 0x00 , 0x06 , 0x60 ,
0x40 , 0x0e , 0x60 , 0x05 , 0x33 , 0x10 , 0x00 , 0x04 } ,
[ ATSC ] = { 0x51 , 0x03 , 0x83 , 0x82 , 0x40 , 0x48 , 0x01 , 0xe0 ,
0x40 , 0x0e , 0x60 , 0x05 , 0x03 , 0x00 , 0x80 , 0x04 } ,
} ;
dev_dbg ( & client - > dev ,
" delivery_system=%d frequency=%u bandwidth_hz=%u " ,
c - > delivery_system , c - > frequency , c - > bandwidth_hz ) ;
switch ( c - > delivery_system ) {
case SYS_ATSC :
j = ATSC ;
if_khz = dev - > if_atsc ;
break ;
case SYS_DVBT :
case SYS_DVBT2 :
if ( c - > bandwidth_hz = = 0 ) {
ret = - EINVAL ;
goto err ;
} else if ( c - > bandwidth_hz < = 6000000 ) {
j = DVBT_6 ;
if_khz = dev - > if_dvbt_6 ;
} else if ( c - > bandwidth_hz < = 7000000 ) {
j = DVBT_7 ;
if_khz = dev - > if_dvbt_7 ;
} else if ( c - > bandwidth_hz < = 8000000 ) {
j = DVBT_8 ;
if_khz = dev - > if_dvbt_8 ;
} else {
ret = - EINVAL ;
goto err ;
}
break ;
case SYS_DVBC_ANNEX_A :
case SYS_DVBC_ANNEX_C :
if ( c - > bandwidth_hz = = 0 ) {
ret = - EINVAL ;
goto err ;
} else if ( c - > bandwidth_hz < = 6000000 ) {
j = DVBC_6 ;
if_khz = dev - > if_dvbc_6 ;
} else if ( c - > bandwidth_hz < = 8000000 ) {
j = DVBC_8 ;
if_khz = dev - > if_dvbc_8 ;
} else {
ret = - EINVAL ;
goto err ;
}
break ;
default :
ret = - EINVAL ;
dev_err ( & client - > dev , " unsupported delivery system=%d " ,
c - > delivery_system ) ;
goto err ;
}
/* set delivery system dependent registers */
for ( i = 0 ; i < 16 ; i + + ) {
ret = regmap_write_bits ( dev - > regmap , delsys_params [ REG ] [ i ] ,
delsys_params [ MASK ] [ i ] , delsys_params [ j ] [ i ] ) ;
if ( ret )
goto err ;
}
/* set IF if needed */
if ( dev - > if_frequency ! = if_khz ) {
utmp = DIV_ROUND_CLOSEST ( if_khz , 50 ) ;
ret = regmap_write ( dev - > regmap , R26_IF , utmp ) ;
if ( ret )
goto err ;
dev - > if_frequency = if_khz ;
dev_dbg ( & client - > dev , " set IF=%u kHz " , if_khz ) ;
}
ret = tda18250_set_agc ( fe ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R1A_AGCK , 0x03 , 0x01 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R14_AGC23 , 0x40 , 0x00 ) ;
if ( ret )
goto err ;
/* set frequency */
buf [ 0 ] = ( ( c - > frequency / 1000 ) > > 16 ) & 0xff ;
buf [ 1 ] = ( ( c - > frequency / 1000 ) > > 8 ) & 0xff ;
buf [ 2 ] = ( ( c - > frequency / 1000 ) > > 0 ) & 0xff ;
ret = regmap_bulk_write ( dev - > regmap , R27_RF1 , buf , 3 ) ;
if ( ret )
goto err ;
ret = regmap_write ( dev - > regmap , R0A_IRQ3 , TDA18250_IRQ_TUNE ) ;
if ( ret )
goto err ;
/* initial tune */
ret = regmap_write ( dev - > regmap , R2A_MSM1 , 0x01 ) ;
if ( ret )
goto err ;
ret = regmap_write ( dev - > regmap , R2B_MSM2 , 0x01 ) ;
if ( ret )
goto err ;
ret = tda18250_wait_for_irq ( fe , 500 , 10 , TDA18250_IRQ_TUNE ) ;
if ( ret )
goto err ;
/* calc ndiv and rdiv */
ret = tda18250_pll_calc ( fe , & buf [ 0 ] , & buf [ 1 ] , & buf [ 2 ] ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R4F_XTALFLX3 , 0xe0 ,
( buf [ 0 ] < < 6 ) | ( buf [ 1 ] < < 5 ) ) ;
if ( ret )
goto err ;
/* clear IRQ */
ret = regmap_write ( dev - > regmap , R0A_IRQ3 , TDA18250_IRQ_TUNE ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R46_CPUMP , 0x07 , 0x00 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R39_SD5 , 0x03 , 0x00 ) ;
if ( ret )
goto err ;
/* tune again */
ret = regmap_write ( dev - > regmap , R2A_MSM1 , 0x01 ) ; /* tune */
if ( ret )
goto err ;
ret = regmap_write ( dev - > regmap , R2B_MSM2 , 0x01 ) ; /* go */
if ( ret )
goto err ;
ret = tda18250_wait_for_irq ( fe , 500 , 10 , TDA18250_IRQ_TUNE ) ;
if ( ret )
goto err ;
/* pll locking */
msleep ( 20 ) ;
ret = regmap_write_bits ( dev - > regmap , R2B_MSM2 , 0x04 , 0x04 ) ;
if ( ret )
goto err ;
msleep ( 20 ) ;
/* restore AGCK */
ret = regmap_write_bits ( dev - > regmap , R1A_AGCK , 0x03 , 0x03 ) ;
if ( ret )
goto err ;
ret = regmap_write_bits ( dev - > regmap , R14_AGC23 , 0x40 , 0x40 ) ;
if ( ret )
goto err ;
/* charge pump */
ret = regmap_write_bits ( dev - > regmap , R46_CPUMP , 0x07 , buf [ 2 ] ) ;
return 0 ;
err :
return ret ;
}
static int tda18250_get_if_frequency ( struct dvb_frontend * fe , u32 * frequency )
{
struct i2c_client * client = fe - > tuner_priv ;
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
* frequency = dev - > if_frequency * 1000 ;
return 0 ;
}
static int tda18250_sleep ( struct dvb_frontend * fe )
{
struct i2c_client * client = fe - > tuner_priv ;
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
int ret ;
dev_dbg ( & client - > dev , " \n " ) ;
/* power down LNA */
ret = regmap_write_bits ( dev - > regmap , R0C_AGC11 , 0x80 , 0x00 ) ;
if ( ret )
return ret ;
/* set if freq to 0 in order to make sure it's set after wake up */
dev - > if_frequency = 0 ;
ret = tda18250_power_control ( fe , TDA18250_POWER_STANDBY ) ;
return ret ;
}
static const struct dvb_tuner_ops tda18250_ops = {
. info = {
2018-07-05 18:59:35 -04:00
. name = " NXP TDA18250 " ,
. frequency_min_hz = 42 * MHz ,
. frequency_max_hz = 870 * MHz ,
2017-11-23 03:24:45 -05:00
} ,
. init = tda18250_init ,
. set_params = tda18250_set_params ,
. get_if_frequency = tda18250_get_if_frequency ,
. sleep = tda18250_sleep ,
} ;
static int tda18250_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
struct tda18250_config * cfg = client - > dev . platform_data ;
struct dvb_frontend * fe = cfg - > fe ;
struct tda18250_dev * dev ;
int ret ;
unsigned char chip_id [ 3 ] ;
/* some registers are always read from HW */
static const struct regmap_range tda18250_yes_ranges [ ] = {
regmap_reg_range ( R05_POWER1 , R0B_IRQ4 ) ,
regmap_reg_range ( R21_IF_AGC , R21_IF_AGC ) ,
regmap_reg_range ( R2A_MSM1 , R2B_MSM2 ) ,
regmap_reg_range ( R2F_RSSI1 , R31_IRQ_CTRL ) ,
} ;
static const struct regmap_access_table tda18250_volatile_table = {
. yes_ranges = tda18250_yes_ranges ,
. n_yes_ranges = ARRAY_SIZE ( tda18250_yes_ranges ) ,
} ;
static const struct regmap_config tda18250_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = TDA18250_NUM_REGS - 1 ,
. volatile_table = & tda18250_volatile_table ,
} ;
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
if ( ! dev ) {
ret = - ENOMEM ;
goto err ;
}
i2c_set_clientdata ( client , dev ) ;
dev - > fe = cfg - > fe ;
dev - > loopthrough = cfg - > loopthrough ;
if ( cfg - > xtal_freq < TDA18250_XTAL_FREQ_MAX ) {
dev - > xtal_freq = cfg - > xtal_freq ;
} else {
ret = - EINVAL ;
dev_err ( & client - > dev , " xtal_freq invalid=%d " , cfg - > xtal_freq ) ;
goto err_kfree ;
}
dev - > if_dvbt_6 = cfg - > if_dvbt_6 ;
dev - > if_dvbt_7 = cfg - > if_dvbt_7 ;
dev - > if_dvbt_8 = cfg - > if_dvbt_8 ;
dev - > if_dvbc_6 = cfg - > if_dvbc_6 ;
dev - > if_dvbc_8 = cfg - > if_dvbc_8 ;
dev - > if_atsc = cfg - > if_atsc ;
dev - > if_frequency = 0 ;
dev - > warm = false ;
dev - > regmap = devm_regmap_init_i2c ( client , & tda18250_regmap_config ) ;
if ( IS_ERR ( dev - > regmap ) ) {
ret = PTR_ERR ( dev - > regmap ) ;
goto err_kfree ;
}
/* read the three chip ID registers */
regmap_bulk_read ( dev - > regmap , R00_ID1 , & chip_id , 3 ) ;
dev_dbg ( & client - > dev , " chip_id=%02x:%02x:%02x " ,
chip_id [ 0 ] , chip_id [ 1 ] , chip_id [ 2 ] ) ;
switch ( chip_id [ 0 ] ) {
case 0xc7 :
dev - > slave = false ;
break ;
case 0x47 :
dev - > slave = true ;
break ;
default :
ret = - ENODEV ;
goto err_kfree ;
}
if ( chip_id [ 1 ] ! = 0x4a ) {
ret = - ENODEV ;
goto err_kfree ;
}
switch ( chip_id [ 2 ] ) {
case 0x20 :
dev_info ( & client - > dev ,
" NXP TDA18250AHN/%s successfully identified " ,
dev - > slave ? " S " : " M " ) ;
break ;
case 0x21 :
dev_info ( & client - > dev ,
" NXP TDA18250BHN/%s successfully identified " ,
dev - > slave ? " S " : " M " ) ;
break ;
default :
ret = - ENODEV ;
goto err_kfree ;
}
fe - > tuner_priv = client ;
memcpy ( & fe - > ops . tuner_ops , & tda18250_ops ,
sizeof ( struct dvb_tuner_ops ) ) ;
/* put the tuner in standby */
tda18250_power_control ( fe , TDA18250_POWER_STANDBY ) ;
return 0 ;
err_kfree :
kfree ( dev ) ;
err :
dev_dbg ( & client - > dev , " failed=%d " , ret ) ;
return ret ;
}
static int tda18250_remove ( struct i2c_client * client )
{
struct tda18250_dev * dev = i2c_get_clientdata ( client ) ;
struct dvb_frontend * fe = dev - > fe ;
dev_dbg ( & client - > dev , " \n " ) ;
memset ( & fe - > ops . tuner_ops , 0 , sizeof ( struct dvb_tuner_ops ) ) ;
fe - > tuner_priv = NULL ;
kfree ( dev ) ;
return 0 ;
}
static const struct i2c_device_id tda18250_id_table [ ] = {
{ " tda18250 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , tda18250_id_table ) ;
static struct i2c_driver tda18250_driver = {
. driver = {
. name = " tda18250 " ,
} ,
. probe = tda18250_probe ,
. remove = tda18250_remove ,
. id_table = tda18250_id_table ,
} ;
module_i2c_driver ( tda18250_driver ) ;
MODULE_DESCRIPTION ( " NXP TDA18250 silicon tuner driver " ) ;
MODULE_AUTHOR ( " Olli Salonen <olli.salonen@iki.fi> " ) ;
MODULE_LICENSE ( " GPL " ) ;