2011-08-01 08:07:39 +04:00
/*
* NXP TDA10071 + Conexant CX24118A DVB - S / S2 demodulator + tuner driver
*
* Copyright ( C ) 2011 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 "tda10071_priv.h"
2016-08-10 00:32:21 +03:00
static const struct dvb_frontend_ops tda10071_ops ;
2011-08-01 08:07:39 +04:00
2015-04-21 04:21:44 +03:00
/*
* XXX : regmap_update_bits ( ) does not fit our needs as it does not support
* partially volatile registers . Also it performs register read even mask is as
* wide as register value .
*/
2011-08-01 08:07:39 +04:00
/* write single register with mask */
2015-04-21 02:04:00 +03:00
static int tda10071_wr_reg_mask ( struct tda10071_dev * dev ,
2012-10-27 18:27:24 +04:00
u8 reg , u8 val , u8 mask )
2011-08-01 08:07:39 +04:00
{
int ret ;
u8 tmp ;
/* no need for read if whole reg is written */
if ( mask ! = 0xff ) {
2015-04-21 04:21:44 +03:00
ret = regmap_bulk_read ( dev - > regmap , reg , & tmp , 1 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
return ret ;
val & = mask ;
tmp & = ~ mask ;
val | = tmp ;
}
2015-04-21 04:21:44 +03:00
return regmap_bulk_write ( dev - > regmap , reg , & val , 1 ) ;
2011-08-01 08:07:39 +04:00
}
/* execute firmware command */
2015-04-21 02:04:00 +03:00
static int tda10071_cmd_execute ( struct tda10071_dev * dev ,
2011-08-01 08:07:39 +04:00
struct tda10071_cmd * cmd )
{
2015-04-21 02:04:00 +03:00
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
int ret , i ;
2015-04-21 04:21:44 +03:00
unsigned int uitmp ;
2011-08-01 08:07:39 +04:00
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
}
2015-04-21 15:58:15 +03:00
mutex_lock ( & dev - > cmd_execute_mutex ) ;
2011-08-01 08:07:39 +04:00
/* write cmd and args for firmware */
2015-04-21 04:21:44 +03:00
ret = regmap_bulk_write ( dev - > regmap , 0x00 , cmd - > args , cmd - > len ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
2015-04-21 15:58:15 +03:00
goto error_mutex_unlock ;
2011-08-01 08:07:39 +04:00
/* start cmd execution */
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0x1f , 1 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
2015-04-21 15:58:15 +03:00
goto error_mutex_unlock ;
2011-08-01 08:07:39 +04:00
/* wait cmd execution terminate */
2015-04-21 04:21:44 +03:00
for ( i = 1000 , uitmp = 1 ; i & & uitmp ; i - - ) {
ret = regmap_read ( dev - > regmap , 0x1f , & uitmp ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
2015-04-21 15:58:15 +03:00
goto error_mutex_unlock ;
2011-08-01 08:07:39 +04:00
2011-09-13 18:51:23 +04:00
usleep_range ( 200 , 5000 ) ;
2011-08-01 08:07:39 +04:00
}
2015-04-21 15:58:15 +03:00
mutex_unlock ( & dev - > cmd_execute_mutex ) ;
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " loop=%d \n " , i ) ;
2011-08-01 08:07:39 +04:00
if ( i = = 0 ) {
ret = - ETIMEDOUT ;
goto error ;
}
return ret ;
2015-04-21 15:58:15 +03:00
error_mutex_unlock :
mutex_unlock ( & dev - > cmd_execute_mutex ) ;
2011-08-01 08:07:39 +04:00
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
static int tda10071_set_tone ( struct dvb_frontend * fe ,
2015-06-07 20:53:52 +03:00
enum fe_sec_tone_mode fe_sec_tone_mode )
2011-08-01 08:07:39 +04:00
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
struct tda10071_cmd cmd ;
int ret ;
u8 tone ;
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
}
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " tone_mode=%d \n " , fe_sec_tone_mode ) ;
2011-08-01 08:07:39 +04:00
switch ( fe_sec_tone_mode ) {
case SEC_TONE_ON :
tone = 1 ;
break ;
case SEC_TONE_OFF :
tone = 0 ;
break ;
default :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " invalid fe_sec_tone_mode \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
}
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_LNB_PCB_CONFIG ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = 0x00 ;
cmd . args [ 3 ] = 0x00 ;
cmd . args [ 4 ] = tone ;
cmd . len = 5 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
static int tda10071_set_voltage ( struct dvb_frontend * fe ,
2015-06-07 20:53:52 +03:00
enum fe_sec_voltage fe_sec_voltage )
2011-08-01 08:07:39 +04:00
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
struct tda10071_cmd cmd ;
int ret ;
u8 voltage ;
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
}
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " voltage=%d \n " , fe_sec_voltage ) ;
2011-08-01 08:07:39 +04:00
switch ( fe_sec_voltage ) {
case SEC_VOLTAGE_13 :
voltage = 0 ;
break ;
case SEC_VOLTAGE_18 :
voltage = 1 ;
break ;
case SEC_VOLTAGE_OFF :
voltage = 0 ;
break ;
default :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " invalid fe_sec_voltage \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
2012-09-07 18:24:43 +04:00
}
2011-08-01 08:07:39 +04:00
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_LNB_SET_DC_LEVEL ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = voltage ;
cmd . len = 3 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
static int tda10071_diseqc_send_master_cmd ( struct dvb_frontend * fe ,
struct dvb_diseqc_master_cmd * diseqc_cmd )
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
struct tda10071_cmd cmd ;
int ret , i ;
2015-04-21 04:21:44 +03:00
unsigned int uitmp ;
2011-08-01 08:07:39 +04:00
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
}
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " msg_len=%d \n " , diseqc_cmd - > msg_len ) ;
2011-08-01 08:07:39 +04:00
2012-07-01 22:29:15 +04:00
if ( diseqc_cmd - > msg_len < 3 | | diseqc_cmd - > msg_len > 6 ) {
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
}
/* wait LNB TX */
2015-04-21 04:21:44 +03:00
for ( i = 500 , uitmp = 0 ; i & & ! uitmp ; i - - ) {
ret = regmap_read ( dev - > regmap , 0x47 , & uitmp ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
uitmp = ( uitmp > > 0 ) & 1 ;
2011-09-13 18:51:23 +04:00
usleep_range ( 10000 , 20000 ) ;
2011-08-01 08:07:39 +04:00
}
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " loop=%d \n " , i ) ;
2011-08-01 08:07:39 +04:00
if ( i = = 0 ) {
ret = - ETIMEDOUT ;
goto error ;
}
2015-04-21 04:21:44 +03:00
ret = regmap_update_bits ( dev - > regmap , 0x47 , 0x01 , 0x00 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_LNB_SEND_DISEQC ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = 0 ;
cmd . args [ 3 ] = 0 ;
cmd . args [ 4 ] = 2 ;
cmd . args [ 5 ] = 0 ;
cmd . args [ 6 ] = diseqc_cmd - > msg_len ;
memcpy ( & cmd . args [ 7 ] , diseqc_cmd - > msg , diseqc_cmd - > msg_len ) ;
cmd . len = 7 + diseqc_cmd - > msg_len ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
static int tda10071_diseqc_recv_slave_reply ( struct dvb_frontend * fe ,
struct dvb_diseqc_slave_reply * reply )
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
struct tda10071_cmd cmd ;
int ret , i ;
2015-04-21 04:21:44 +03:00
unsigned int uitmp ;
2011-08-01 08:07:39 +04:00
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
}
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " \n " ) ;
2011-08-01 08:07:39 +04:00
/* wait LNB RX */
2015-04-21 04:21:44 +03:00
for ( i = 500 , uitmp = 0 ; i & & ! uitmp ; i - - ) {
ret = regmap_read ( dev - > regmap , 0x47 , & uitmp ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
uitmp = ( uitmp > > 1 ) & 1 ;
2011-09-13 18:51:23 +04:00
usleep_range ( 10000 , 20000 ) ;
2011-08-01 08:07:39 +04:00
}
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " loop=%d \n " , i ) ;
2011-08-01 08:07:39 +04:00
if ( i = = 0 ) {
ret = - ETIMEDOUT ;
goto error ;
}
/* reply len */
2015-04-21 04:21:44 +03:00
ret = regmap_read ( dev - > regmap , 0x46 , & uitmp ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
reply - > msg_len = uitmp & 0x1f ; /* [4:0] */
2011-08-01 08:07:39 +04:00
if ( reply - > msg_len > sizeof ( reply - > msg ) )
reply - > msg_len = sizeof ( reply - > msg ) ; /* truncate API max */
/* read reply */
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_LNB_UPDATE_REPLY ;
cmd . args [ 1 ] = 0 ;
cmd . len = 2 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
ret = regmap_bulk_read ( dev - > regmap , cmd . len , reply - > msg ,
reply - > msg_len ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
static int tda10071_diseqc_send_burst ( struct dvb_frontend * fe ,
2015-06-07 20:53:52 +03:00
enum fe_sec_mini_cmd fe_sec_mini_cmd )
2011-08-01 08:07:39 +04:00
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
struct tda10071_cmd cmd ;
int ret , i ;
2015-04-21 04:21:44 +03:00
unsigned int uitmp ;
u8 burst ;
2011-08-01 08:07:39 +04:00
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
}
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " fe_sec_mini_cmd=%d \n " , fe_sec_mini_cmd ) ;
2011-08-01 08:07:39 +04:00
switch ( fe_sec_mini_cmd ) {
case SEC_MINI_A :
burst = 0 ;
break ;
case SEC_MINI_B :
burst = 1 ;
break ;
default :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " invalid fe_sec_mini_cmd \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
}
/* wait LNB TX */
2015-04-21 04:21:44 +03:00
for ( i = 500 , uitmp = 0 ; i & & ! uitmp ; i - - ) {
ret = regmap_read ( dev - > regmap , 0x47 , & uitmp ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
uitmp = ( uitmp > > 0 ) & 1 ;
2011-09-13 18:51:23 +04:00
usleep_range ( 10000 , 20000 ) ;
2011-08-01 08:07:39 +04:00
}
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " loop=%d \n " , i ) ;
2011-08-01 08:07:39 +04:00
if ( i = = 0 ) {
ret = - ETIMEDOUT ;
goto error ;
}
2015-04-21 04:21:44 +03:00
ret = regmap_update_bits ( dev - > regmap , 0x47 , 0x01 , 0x00 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_LNB_SEND_TONEBURST ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = burst ;
cmd . len = 3 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
2015-06-07 20:53:52 +03:00
static int tda10071_read_status ( struct dvb_frontend * fe , enum fe_status * status )
2011-08-01 08:07:39 +04:00
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2015-04-21 17:14:44 +03:00
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
struct tda10071_cmd cmd ;
2011-08-01 08:07:39 +04:00
int ret ;
2015-04-21 04:21:44 +03:00
unsigned int uitmp ;
2015-04-21 17:14:44 +03:00
u8 buf [ 8 ] ;
2011-08-01 08:07:39 +04:00
* status = 0 ;
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = 0 ;
goto error ;
}
2015-04-21 04:21:44 +03:00
ret = regmap_read ( dev - > regmap , 0x39 , & uitmp ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2014-02-11 07:17:37 +04:00
/* 0x39[0] tuner PLL */
2015-04-21 04:21:44 +03:00
if ( uitmp & 0x02 ) /* demod PLL */
2014-02-11 07:17:37 +04:00
* status | = FE_HAS_SIGNAL | FE_HAS_CARRIER ;
2015-04-21 04:21:44 +03:00
if ( uitmp & 0x04 ) /* viterbi or LDPC*/
2011-08-01 08:07:39 +04:00
* status | = FE_HAS_VITERBI ;
2015-04-21 04:21:44 +03:00
if ( uitmp & 0x08 ) /* RS or BCH */
2011-08-01 08:07:39 +04:00
* status | = FE_HAS_SYNC | FE_HAS_LOCK ;
2015-04-21 02:04:00 +03:00
dev - > fe_status = * status ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
/* signal strength */
if ( dev - > fe_status & FE_HAS_SIGNAL ) {
cmd . args [ 0 ] = CMD_GET_AGCACC ;
cmd . args [ 1 ] = 0 ;
cmd . len = 2 ;
ret = tda10071_cmd_execute ( dev , & cmd ) ;
if ( ret )
goto error ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
/* input power estimate dBm */
ret = regmap_read ( dev - > regmap , 0x50 , & uitmp ) ;
if ( ret )
goto error ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
c - > strength . stat [ 0 ] . scale = FE_SCALE_DECIBEL ;
c - > strength . stat [ 0 ] . svalue = ( int ) ( uitmp - 256 ) * 1000 ;
} else {
c - > strength . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
2011-08-01 08:07:39 +04:00
}
2015-04-21 17:14:44 +03:00
/* CNR */
if ( dev - > fe_status & FE_HAS_VITERBI ) {
/* Es/No */
ret = regmap_bulk_read ( dev - > regmap , 0x3a , buf , 2 ) ;
if ( ret )
goto error ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
c - > cnr . stat [ 0 ] . scale = FE_SCALE_DECIBEL ;
c - > cnr . stat [ 0 ] . svalue = ( buf [ 0 ] < < 8 | buf [ 1 ] < < 0 ) * 100 ;
} else {
c - > cnr . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
}
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
/* UCB/PER/BER */
if ( dev - > fe_status & FE_HAS_LOCK ) {
/* TODO: report total bits/packets */
u8 delivery_system , reg , len ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
switch ( dev - > delivery_system ) {
case SYS_DVBS :
reg = 0x4c ;
len = 8 ;
delivery_system = 1 ;
break ;
case SYS_DVBS2 :
reg = 0x4d ;
len = 4 ;
delivery_system = 0 ;
break ;
default :
ret = - EINVAL ;
goto error ;
}
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
ret = regmap_read ( dev - > regmap , reg , & uitmp ) ;
if ( ret )
goto error ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
if ( dev - > meas_count = = uitmp ) {
dev_dbg ( & client - > dev , " meas not ready=%02x \n " , uitmp ) ;
ret = 0 ;
goto error ;
} else {
dev - > meas_count = uitmp ;
}
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
cmd . args [ 0 ] = CMD_BER_UPDATE_COUNTERS ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = delivery_system ;
cmd . len = 3 ;
ret = tda10071_cmd_execute ( dev , & cmd ) ;
if ( ret )
goto error ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
ret = regmap_bulk_read ( dev - > regmap , cmd . len , buf , len ) ;
if ( ret )
goto error ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
if ( dev - > delivery_system = = SYS_DVBS ) {
dev - > dvbv3_ber = buf [ 0 ] < < 24 | buf [ 1 ] < < 16 |
buf [ 2 ] < < 8 | buf [ 3 ] < < 0 ;
dev - > post_bit_error + = buf [ 0 ] < < 24 | buf [ 1 ] < < 16 |
buf [ 2 ] < < 8 | buf [ 3 ] < < 0 ;
c - > post_bit_error . stat [ 0 ] . scale = FE_SCALE_COUNTER ;
c - > post_bit_error . stat [ 0 ] . uvalue = dev - > post_bit_error ;
dev - > block_error + = buf [ 4 ] < < 8 | buf [ 5 ] < < 0 ;
c - > block_error . stat [ 0 ] . scale = FE_SCALE_COUNTER ;
c - > block_error . stat [ 0 ] . uvalue = dev - > block_error ;
} else {
dev - > dvbv3_ber = buf [ 0 ] < < 8 | buf [ 1 ] < < 0 ;
dev - > post_bit_error + = buf [ 0 ] < < 8 | buf [ 1 ] < < 0 ;
c - > post_bit_error . stat [ 0 ] . scale = FE_SCALE_COUNTER ;
c - > post_bit_error . stat [ 0 ] . uvalue = dev - > post_bit_error ;
c - > block_error . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
}
} else {
c - > post_bit_error . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
c - > block_error . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
}
2011-08-01 08:07:39 +04:00
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
2015-04-21 17:14:44 +03:00
static int tda10071_read_snr ( struct dvb_frontend * fe , u16 * snr )
2011-08-01 08:07:39 +04:00
{
2015-04-21 17:14:44 +03:00
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
if ( c - > cnr . stat [ 0 ] . scale = = FE_SCALE_DECIBEL )
* snr = div_s64 ( c - > cnr . stat [ 0 ] . svalue , 100 ) ;
else
* snr = 0 ;
return 0 ;
}
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
static int tda10071_read_signal_strength ( struct dvb_frontend * fe , u16 * strength )
{
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
unsigned int uitmp ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
if ( c - > strength . stat [ 0 ] . scale = = FE_SCALE_DECIBEL ) {
2015-08-12 01:08:59 +03:00
uitmp = div_s64 ( c - > strength . stat [ 0 ] . svalue , 1000 ) + 256 ;
2015-04-21 17:14:44 +03:00
uitmp = clamp ( uitmp , 181U , 236U ) ; /* -75dBm - -20dBm */
/* scale value to 0x0000-0xffff */
* strength = ( uitmp - 181 ) * 0xffff / ( 236 - 181 ) ;
2011-08-01 08:07:39 +04:00
} else {
2015-04-21 17:14:44 +03:00
* strength = 0 ;
2011-08-01 08:07:39 +04:00
}
2015-04-21 17:14:44 +03:00
return 0 ;
}
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
static int tda10071_read_ber ( struct dvb_frontend * fe , u32 * ber )
{
struct tda10071_dev * dev = fe - > demodulator_priv ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
* ber = dev - > dvbv3_ber ;
return 0 ;
2011-08-01 08:07:39 +04:00
}
static int tda10071_read_ucblocks ( struct dvb_frontend * fe , u32 * ucblocks )
{
2015-04-21 17:14:44 +03:00
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
2011-08-01 08:07:39 +04:00
2015-04-21 17:14:44 +03:00
if ( c - > block_error . stat [ 0 ] . scale = = FE_SCALE_COUNTER )
* ucblocks = c - > block_error . stat [ 0 ] . uvalue ;
else
2011-08-01 08:07:39 +04:00
* ucblocks = 0 ;
2015-04-21 17:14:44 +03:00
return 0 ;
2011-08-01 08:07:39 +04:00
}
2011-12-26 21:46:22 +04:00
static int tda10071_set_frontend ( struct dvb_frontend * fe )
2011-08-01 08:07:39 +04:00
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
struct tda10071_cmd cmd ;
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
int ret , i ;
u8 mode , rolloff , pilot , inversion , div ;
2015-06-07 20:53:52 +03:00
enum fe_modulation modulation ;
2011-08-01 08:07:39 +04:00
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev ,
" delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d \n " ,
c - > delivery_system , c - > modulation , c - > frequency , c - > symbol_rate ,
c - > inversion , c - > pilot , c - > rolloff ) ;
2011-08-01 08:07:39 +04:00
2015-04-21 02:04:00 +03:00
dev - > delivery_system = SYS_UNDEFINED ;
2011-08-01 08:07:39 +04:00
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
}
switch ( c - > inversion ) {
case INVERSION_OFF :
inversion = 1 ;
break ;
case INVERSION_ON :
inversion = 0 ;
break ;
case INVERSION_AUTO :
/* 2 = auto; try first on then off
* 3 = auto ; try first off then on */
inversion = 3 ;
break ;
default :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " invalid inversion \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
}
switch ( c - > delivery_system ) {
case SYS_DVBS :
2014-07-04 12:44:39 +04:00
modulation = QPSK ;
2011-08-01 08:07:39 +04:00
rolloff = 0 ;
pilot = 2 ;
break ;
case SYS_DVBS2 :
2014-07-04 12:44:39 +04:00
modulation = c - > modulation ;
2011-08-01 08:07:39 +04:00
switch ( c - > rolloff ) {
case ROLLOFF_20 :
rolloff = 2 ;
break ;
case ROLLOFF_25 :
rolloff = 1 ;
break ;
case ROLLOFF_35 :
rolloff = 0 ;
break ;
case ROLLOFF_AUTO :
default :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " invalid rolloff \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
}
switch ( c - > pilot ) {
case PILOT_OFF :
pilot = 0 ;
break ;
case PILOT_ON :
pilot = 1 ;
break ;
case PILOT_AUTO :
pilot = 2 ;
break ;
default :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " invalid pilot \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
}
break ;
default :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " invalid delivery_system \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
}
for ( i = 0 , mode = 0xff ; i < ARRAY_SIZE ( TDA10071_MODCOD ) ; i + + ) {
if ( c - > delivery_system = = TDA10071_MODCOD [ i ] . delivery_system & &
2014-07-04 12:44:39 +04:00
modulation = = TDA10071_MODCOD [ i ] . modulation & &
2011-08-01 08:07:39 +04:00
c - > fec_inner = = TDA10071_MODCOD [ i ] . fec ) {
mode = TDA10071_MODCOD [ i ] . val ;
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " mode found=%02x \n " , mode ) ;
2011-08-01 08:07:39 +04:00
break ;
}
}
if ( mode = = 0xff ) {
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " invalid parameter combination \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EINVAL ;
goto error ;
}
if ( c - > symbol_rate < = 5000000 )
div = 14 ;
else
div = 4 ;
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0x81 , div ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0xe3 , div ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_CHANGE_CHANNEL ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = mode ;
cmd . args [ 3 ] = ( c - > frequency > > 16 ) & 0xff ;
cmd . args [ 4 ] = ( c - > frequency > > 8 ) & 0xff ;
cmd . args [ 5 ] = ( c - > frequency > > 0 ) & 0xff ;
cmd . args [ 6 ] = ( ( c - > symbol_rate / 1000 ) > > 8 ) & 0xff ;
cmd . args [ 7 ] = ( ( c - > symbol_rate / 1000 ) > > 0 ) & 0xff ;
cmd . args [ 8 ] = ( tda10071_ops . info . frequency_tolerance > > 8 ) & 0xff ;
cmd . args [ 9 ] = ( tda10071_ops . info . frequency_tolerance > > 0 ) & 0xff ;
cmd . args [ 10 ] = rolloff ;
cmd . args [ 11 ] = inversion ;
cmd . args [ 12 ] = pilot ;
cmd . args [ 13 ] = 0x00 ;
cmd . args [ 14 ] = 0x00 ;
cmd . len = 15 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 02:04:00 +03:00
dev - > delivery_system = c - > delivery_system ;
2011-08-01 08:07:39 +04:00
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
2016-02-04 17:58:30 +03:00
static int tda10071_get_frontend ( struct dvb_frontend * fe ,
struct dtv_frontend_properties * c )
2011-08-01 08:07:39 +04:00
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
int ret , i ;
u8 buf [ 5 ] , tmp ;
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm | | ! ( dev - > fe_status & FE_HAS_LOCK ) ) {
2015-04-21 17:16:44 +03:00
ret = 0 ;
2011-08-01 08:07:39 +04:00
goto error ;
}
2015-04-21 04:21:44 +03:00
ret = regmap_bulk_read ( dev - > regmap , 0x30 , buf , 5 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
tmp = buf [ 0 ] & 0x3f ;
for ( i = 0 ; i < ARRAY_SIZE ( TDA10071_MODCOD ) ; i + + ) {
if ( tmp = = TDA10071_MODCOD [ i ] . val ) {
c - > modulation = TDA10071_MODCOD [ i ] . modulation ;
c - > fec_inner = TDA10071_MODCOD [ i ] . fec ;
c - > delivery_system = TDA10071_MODCOD [ i ] . delivery_system ;
}
}
switch ( ( buf [ 1 ] > > 0 ) & 0x01 ) {
case 0 :
2014-07-07 16:52:28 +04:00
c - > inversion = INVERSION_ON ;
2011-08-01 08:07:39 +04:00
break ;
case 1 :
2014-07-07 16:52:28 +04:00
c - > inversion = INVERSION_OFF ;
2011-08-01 08:07:39 +04:00
break ;
}
switch ( ( buf [ 1 ] > > 7 ) & 0x01 ) {
case 0 :
c - > pilot = PILOT_OFF ;
break ;
case 1 :
c - > pilot = PILOT_ON ;
break ;
}
c - > frequency = ( buf [ 2 ] < < 16 ) | ( buf [ 3 ] < < 8 ) | ( buf [ 4 ] < < 0 ) ;
2015-04-21 04:21:44 +03:00
ret = regmap_bulk_read ( dev - > regmap , 0x52 , buf , 3 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2014-07-08 09:48:28 +04:00
c - > symbol_rate = ( ( buf [ 0 ] < < 16 ) | ( buf [ 1 ] < < 8 ) | ( buf [ 2 ] < < 0 ) ) * 1000 ;
2011-08-01 08:07:39 +04:00
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
static int tda10071_init ( struct dvb_frontend * fe )
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2015-04-21 17:14:44 +03:00
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
2011-08-01 08:07:39 +04:00
struct tda10071_cmd cmd ;
2011-09-13 14:30:11 +04:00
int ret , i , len , remaining , fw_size ;
2015-04-21 04:21:44 +03:00
unsigned int uitmp ;
2011-08-01 08:07:39 +04:00
const struct firmware * fw ;
2012-09-12 18:37:29 +04:00
u8 * fw_file = TDA10071_FIRMWARE ;
2011-08-01 08:07:39 +04:00
u8 tmp , buf [ 4 ] ;
struct tda10071_reg_val_mask tab [ ] = {
{ 0xcd , 0x00 , 0x07 } ,
{ 0x80 , 0x00 , 0x02 } ,
{ 0xcd , 0x00 , 0xc0 } ,
{ 0xce , 0x00 , 0x1b } ,
{ 0x9d , 0x00 , 0x01 } ,
{ 0x9d , 0x00 , 0x02 } ,
{ 0x9e , 0x00 , 0x01 } ,
{ 0x87 , 0x00 , 0x80 } ,
{ 0xce , 0x00 , 0x08 } ,
{ 0xce , 0x00 , 0x10 } ,
} ;
struct tda10071_reg_val_mask tab2 [ ] = {
{ 0xf1 , 0x70 , 0xff } ,
2015-04-21 02:04:00 +03:00
{ 0x88 , dev - > pll_multiplier , 0x3f } ,
2011-08-01 08:07:39 +04:00
{ 0x89 , 0x00 , 0x10 } ,
{ 0x89 , 0x10 , 0x10 } ,
{ 0xc0 , 0x01 , 0x01 } ,
{ 0xc0 , 0x00 , 0x01 } ,
{ 0xe0 , 0xff , 0xff } ,
{ 0xe0 , 0x00 , 0xff } ,
{ 0x96 , 0x1e , 0x7e } ,
{ 0x8b , 0x08 , 0x08 } ,
{ 0x8b , 0x00 , 0x08 } ,
{ 0x8f , 0x1a , 0x7e } ,
{ 0x8c , 0x68 , 0xff } ,
{ 0x8d , 0x08 , 0xff } ,
{ 0x8e , 0x4c , 0xff } ,
{ 0x8f , 0x01 , 0x01 } ,
{ 0x8b , 0x04 , 0x04 } ,
{ 0x8b , 0x00 , 0x04 } ,
{ 0x87 , 0x05 , 0x07 } ,
{ 0x80 , 0x00 , 0x20 } ,
{ 0xc8 , 0x01 , 0xff } ,
{ 0xb4 , 0x47 , 0xff } ,
{ 0xb5 , 0x9c , 0xff } ,
{ 0xb6 , 0x7d , 0xff } ,
{ 0xba , 0x00 , 0x03 } ,
{ 0xb7 , 0x47 , 0xff } ,
{ 0xb8 , 0x9c , 0xff } ,
{ 0xb9 , 0x7d , 0xff } ,
{ 0xba , 0x00 , 0x0c } ,
{ 0xc8 , 0x00 , 0xff } ,
{ 0xcd , 0x00 , 0x04 } ,
{ 0xcd , 0x00 , 0x20 } ,
{ 0xe8 , 0x02 , 0xff } ,
{ 0xcf , 0x20 , 0xff } ,
{ 0x9b , 0xd7 , 0xff } ,
{ 0x9a , 0x01 , 0x03 } ,
{ 0xa8 , 0x05 , 0x0f } ,
{ 0xa8 , 0x65 , 0xf0 } ,
{ 0xa6 , 0xa0 , 0xf0 } ,
{ 0x9d , 0x50 , 0xfc } ,
{ 0x9e , 0x20 , 0xe0 } ,
{ 0xa3 , 0x1c , 0x7c } ,
{ 0xd5 , 0x03 , 0x03 } ,
} ;
2015-04-21 02:04:00 +03:00
if ( dev - > warm ) {
2011-08-01 08:07:39 +04:00
/* warm state - wake up device from sleep */
for ( i = 0 ; i < ARRAY_SIZE ( tab ) ; i + + ) {
2015-04-21 02:04:00 +03:00
ret = tda10071_wr_reg_mask ( dev , tab [ i ] . reg ,
2011-08-01 08:07:39 +04:00
tab [ i ] . val , tab [ i ] . mask ) ;
if ( ret )
goto error ;
}
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_SET_SLEEP_MODE ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = 0 ;
cmd . len = 3 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
} else {
/* cold state - try to download firmware */
/* request the firmware, this will block and timeout */
2015-04-21 01:54:56 +03:00
ret = request_firmware ( & fw , fw_file , & client - > dev ) ;
2011-08-01 08:07:39 +04:00
if ( ret ) {
2015-04-21 01:54:56 +03:00
dev_err ( & client - > dev ,
" did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d) \n " ,
fw_file , ret ) ;
2011-08-01 08:07:39 +04:00
goto error ;
}
/* init */
for ( i = 0 ; i < ARRAY_SIZE ( tab2 ) ; i + + ) {
2015-04-21 02:04:00 +03:00
ret = tda10071_wr_reg_mask ( dev , tab2 [ i ] . reg ,
2011-08-01 08:07:39 +04:00
tab2 [ i ] . val , tab2 [ i ] . mask ) ;
if ( ret )
goto error_release_firmware ;
}
/* download firmware */
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0xe0 , 0x7f ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error_release_firmware ;
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0xf7 , 0x81 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error_release_firmware ;
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0xf8 , 0x00 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error_release_firmware ;
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0xf9 , 0x00 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error_release_firmware ;
2015-04-21 01:54:56 +03:00
dev_info ( & client - > dev ,
" found a '%s' in cold state, will try to load a firmware \n " ,
tda10071_ops . info . name ) ;
dev_info ( & client - > dev , " downloading firmware from file '%s' \n " ,
fw_file ) ;
2011-08-01 08:07:39 +04:00
2011-09-13 14:30:11 +04:00
/* do not download last byte */
fw_size = fw - > size - 1 ;
for ( remaining = fw_size ; remaining > 0 ;
2015-04-21 02:04:00 +03:00
remaining - = ( dev - > i2c_wr_max - 1 ) ) {
2011-08-01 08:07:39 +04:00
len = remaining ;
2015-04-21 02:04:00 +03:00
if ( len > ( dev - > i2c_wr_max - 1 ) )
len = ( dev - > i2c_wr_max - 1 ) ;
2011-08-01 08:07:39 +04:00
2015-04-21 04:21:44 +03:00
ret = regmap_bulk_write ( dev - > regmap , 0xfa ,
2011-09-13 14:30:11 +04:00
( u8 * ) & fw - > data [ fw_size - remaining ] , len ) ;
2011-08-01 08:07:39 +04:00
if ( ret ) {
2015-04-21 01:54:56 +03:00
dev_err ( & client - > dev ,
" firmware download failed=%d \n " , ret ) ;
2014-01-30 16:00:34 +04:00
goto error_release_firmware ;
2011-08-01 08:07:39 +04:00
}
}
release_firmware ( fw ) ;
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0xf7 , 0x0c ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
ret = regmap_write ( dev - > regmap , 0xe0 , 0x00 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
/* wait firmware start */
msleep ( 250 ) ;
/* firmware status */
2015-04-21 04:21:44 +03:00
ret = regmap_read ( dev - > regmap , 0x51 , & uitmp ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
if ( uitmp ) {
2015-04-21 01:54:56 +03:00
dev_info ( & client - > dev , " firmware did not run \n " ) ;
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
} else {
2015-04-21 02:04:00 +03:00
dev - > warm = true ;
2011-08-01 08:07:39 +04:00
}
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_GET_FW_VERSION ;
cmd . len = 1 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
ret = regmap_bulk_read ( dev - > regmap , cmd . len , buf , 4 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 01:54:56 +03:00
dev_info ( & client - > dev , " firmware version %d.%d.%d.%d \n " ,
buf [ 0 ] , buf [ 1 ] , buf [ 2 ] , buf [ 3 ] ) ;
dev_info ( & client - > dev , " found a '%s' in warm state \n " ,
tda10071_ops . info . name ) ;
2011-08-01 08:07:39 +04:00
2015-04-21 04:21:44 +03:00
ret = regmap_bulk_read ( dev - > regmap , 0x81 , buf , 2 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_DEMOD_INIT ;
2015-04-21 02:04:00 +03:00
cmd . args [ 1 ] = ( ( dev - > clk / 1000 ) > > 8 ) & 0xff ;
cmd . args [ 2 ] = ( ( dev - > clk / 1000 ) > > 0 ) & 0xff ;
2012-07-01 22:59:13 +04:00
cmd . args [ 3 ] = buf [ 0 ] ;
cmd . args [ 4 ] = buf [ 1 ] ;
2015-04-21 02:04:00 +03:00
cmd . args [ 5 ] = dev - > pll_multiplier ;
cmd . args [ 6 ] = dev - > spec_inv ;
2012-07-01 22:59:13 +04:00
cmd . args [ 7 ] = 0x00 ;
cmd . len = 8 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 02:04:00 +03:00
if ( dev - > tuner_i2c_addr )
tmp = dev - > tuner_i2c_addr ;
2014-02-11 22:13:46 +04:00
else
tmp = 0x14 ;
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_TUNER_INIT ;
cmd . args [ 1 ] = 0x00 ;
cmd . args [ 2 ] = 0x00 ;
cmd . args [ 3 ] = 0x00 ;
cmd . args [ 4 ] = 0x00 ;
2014-02-11 22:13:46 +04:00
cmd . args [ 5 ] = tmp ;
2012-07-01 22:59:13 +04:00
cmd . args [ 6 ] = 0x00 ;
cmd . args [ 7 ] = 0x03 ;
cmd . args [ 8 ] = 0x02 ;
cmd . args [ 9 ] = 0x02 ;
cmd . args [ 10 ] = 0x00 ;
cmd . args [ 11 ] = 0x00 ;
cmd . args [ 12 ] = 0x00 ;
cmd . args [ 13 ] = 0x00 ;
cmd . args [ 14 ] = 0x00 ;
cmd . len = 15 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_MPEG_CONFIG ;
cmd . args [ 1 ] = 0 ;
2015-04-21 02:04:00 +03:00
cmd . args [ 2 ] = dev - > ts_mode ;
2012-07-01 22:59:13 +04:00
cmd . args [ 3 ] = 0x00 ;
cmd . args [ 4 ] = 0x04 ;
cmd . args [ 5 ] = 0x00 ;
cmd . len = 6 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2015-04-21 04:21:44 +03:00
ret = regmap_update_bits ( dev - > regmap , 0xf0 , 0x01 , 0x01 ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_LNB_CONFIG ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = 150 ;
cmd . args [ 3 ] = 3 ;
cmd . args [ 4 ] = 22 ;
cmd . args [ 5 ] = 1 ;
cmd . args [ 6 ] = 1 ;
cmd . args [ 7 ] = 30 ;
cmd . args [ 8 ] = 30 ;
cmd . args [ 9 ] = 30 ;
cmd . args [ 10 ] = 30 ;
cmd . len = 11 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_BER_CONTROL ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = 14 ;
cmd . args [ 3 ] = 14 ;
cmd . len = 4 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
}
2015-04-21 17:14:44 +03:00
/* init stats here in order signal app which stats are supported */
c - > strength . len = 1 ;
c - > strength . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
c - > cnr . len = 1 ;
c - > cnr . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
c - > post_bit_error . len = 1 ;
c - > post_bit_error . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
c - > block_error . len = 1 ;
c - > block_error . stat [ 0 ] . scale = FE_SCALE_NOT_AVAILABLE ;
2011-08-01 08:07:39 +04:00
return ret ;
error_release_firmware :
release_firmware ( fw ) ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
static int tda10071_sleep ( struct dvb_frontend * fe )
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = fe - > demodulator_priv ;
struct i2c_client * client = dev - > client ;
2011-08-01 08:07:39 +04:00
struct tda10071_cmd cmd ;
int ret , i ;
struct tda10071_reg_val_mask tab [ ] = {
{ 0xcd , 0x07 , 0x07 } ,
{ 0x80 , 0x02 , 0x02 } ,
{ 0xcd , 0xc0 , 0xc0 } ,
{ 0xce , 0x1b , 0x1b } ,
{ 0x9d , 0x01 , 0x01 } ,
{ 0x9d , 0x02 , 0x02 } ,
{ 0x9e , 0x01 , 0x01 } ,
{ 0x87 , 0x80 , 0x80 } ,
{ 0xce , 0x08 , 0x08 } ,
{ 0xce , 0x10 , 0x10 } ,
} ;
2015-04-21 02:04:00 +03:00
if ( ! dev - > warm ) {
2011-08-01 08:07:39 +04:00
ret = - EFAULT ;
goto error ;
}
2012-07-01 22:59:13 +04:00
cmd . args [ 0 ] = CMD_SET_SLEEP_MODE ;
cmd . args [ 1 ] = 0 ;
cmd . args [ 2 ] = 1 ;
cmd . len = 3 ;
2015-04-21 02:04:00 +03:00
ret = tda10071_cmd_execute ( dev , & cmd ) ;
2011-08-01 08:07:39 +04:00
if ( ret )
goto error ;
for ( i = 0 ; i < ARRAY_SIZE ( tab ) ; i + + ) {
2015-04-21 02:04:00 +03:00
ret = tda10071_wr_reg_mask ( dev , tab [ i ] . reg , tab [ i ] . val ,
2011-08-01 08:07:39 +04:00
tab [ i ] . mask ) ;
if ( ret )
goto error ;
}
return ret ;
error :
2015-04-21 01:54:56 +03:00
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
2011-08-01 08:07:39 +04:00
return ret ;
}
static int tda10071_get_tune_settings ( struct dvb_frontend * fe ,
struct dvb_frontend_tune_settings * s )
{
s - > min_delay_ms = 8000 ;
s - > step_size = 0 ;
s - > max_drift = 0 ;
return 0 ;
}
2016-08-10 00:32:21 +03:00
static const struct dvb_frontend_ops tda10071_ops = {
2012-03-13 01:21:20 +04:00
. delsys = { SYS_DVBS , SYS_DVBS2 } ,
2011-08-01 08:07:39 +04:00
. info = {
. name = " NXP TDA10071 " ,
. frequency_min = 950000 ,
. frequency_max = 2150000 ,
. frequency_tolerance = 5000 ,
. symbol_rate_min = 1000000 ,
. symbol_rate_max = 45000000 ,
. caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 |
FE_CAN_FEC_2_3 |
FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 |
FE_CAN_FEC_5_6 |
FE_CAN_FEC_6_7 |
FE_CAN_FEC_7_8 |
FE_CAN_FEC_8_9 |
FE_CAN_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_RECOVER |
FE_CAN_2G_MODULATION
} ,
. get_tune_settings = tda10071_get_tune_settings ,
. init = tda10071_init ,
. sleep = tda10071_sleep ,
2011-12-26 21:46:22 +04:00
. set_frontend = tda10071_set_frontend ,
. get_frontend = tda10071_get_frontend ,
2011-08-01 08:07:39 +04:00
. read_status = tda10071_read_status ,
. read_snr = tda10071_read_snr ,
. read_signal_strength = tda10071_read_signal_strength ,
. read_ber = tda10071_read_ber ,
. read_ucblocks = tda10071_read_ucblocks ,
. diseqc_send_master_cmd = tda10071_diseqc_send_master_cmd ,
. diseqc_recv_slave_reply = tda10071_diseqc_recv_slave_reply ,
. diseqc_send_burst = tda10071_diseqc_send_burst ,
. set_tone = tda10071_set_tone ,
. set_voltage = tda10071_set_voltage ,
} ;
2015-04-16 17:46:24 +03:00
static struct dvb_frontend * tda10071_get_dvb_frontend ( struct i2c_client * client )
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev = i2c_get_clientdata ( client ) ;
2015-04-16 17:46:24 +03:00
dev_dbg ( & client - > dev , " \n " ) ;
return & dev - > fe ;
}
static int tda10071_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
2015-04-21 02:04:00 +03:00
struct tda10071_dev * dev ;
2015-04-16 17:46:24 +03:00
struct tda10071_platform_data * pdata = client - > dev . platform_data ;
int ret ;
2015-04-21 04:21:44 +03:00
unsigned int uitmp ;
static const struct regmap_config regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
} ;
2015-04-16 17:46:24 +03:00
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
if ( ! dev ) {
ret = - ENOMEM ;
goto err ;
}
dev - > client = client ;
2015-04-21 15:58:15 +03:00
mutex_init ( & dev - > cmd_execute_mutex ) ;
2015-04-21 01:54:56 +03:00
dev - > clk = pdata - > clk ;
dev - > i2c_wr_max = pdata - > i2c_wr_max ;
dev - > ts_mode = pdata - > ts_mode ;
dev - > spec_inv = pdata - > spec_inv ;
dev - > pll_multiplier = pdata - > pll_multiplier ;
dev - > tuner_i2c_addr = pdata - > tuner_i2c_addr ;
2015-04-21 04:21:44 +03:00
dev - > regmap = devm_regmap_init_i2c ( client , & regmap_config ) ;
if ( IS_ERR ( dev - > regmap ) ) {
ret = PTR_ERR ( dev - > regmap ) ;
goto err_kfree ;
}
2015-04-16 17:46:24 +03:00
/* chip ID */
2015-04-21 04:21:44 +03:00
ret = regmap_read ( dev - > regmap , 0xff , & uitmp ) ;
2015-06-06 14:11:16 +03:00
if ( ret )
goto err_kfree ;
2015-04-21 04:21:44 +03:00
if ( uitmp ! = 0x0f ) {
2015-06-06 14:11:16 +03:00
ret = - ENODEV ;
2015-04-16 17:46:24 +03:00
goto err_kfree ;
2015-06-06 14:11:16 +03:00
}
2015-04-16 17:46:24 +03:00
/* chip type */
2015-04-21 04:21:44 +03:00
ret = regmap_read ( dev - > regmap , 0xdd , & uitmp ) ;
2015-06-06 14:11:16 +03:00
if ( ret )
goto err_kfree ;
2015-04-21 04:21:44 +03:00
if ( uitmp ! = 0x00 ) {
2015-06-06 14:11:16 +03:00
ret = - ENODEV ;
2015-04-16 17:46:24 +03:00
goto err_kfree ;
2015-06-06 14:11:16 +03:00
}
2015-04-16 17:46:24 +03:00
/* chip version */
2015-04-21 04:21:44 +03:00
ret = regmap_read ( dev - > regmap , 0xfe , & uitmp ) ;
2015-06-06 14:11:16 +03:00
if ( ret )
2015-04-16 17:46:24 +03:00
goto err_kfree ;
2015-04-21 04:21:44 +03:00
if ( uitmp ! = 0x01 ) {
2015-06-06 14:11:16 +03:00
ret = - ENODEV ;
goto err_kfree ;
}
2015-04-16 17:46:24 +03:00
/* create dvb_frontend */
memcpy ( & dev - > fe . ops , & tda10071_ops , sizeof ( struct dvb_frontend_ops ) ) ;
dev - > fe . demodulator_priv = dev ;
i2c_set_clientdata ( client , dev ) ;
/* setup callbacks */
pdata - > get_dvb_frontend = tda10071_get_dvb_frontend ;
dev_info ( & client - > dev , " NXP TDA10071 successfully identified \n " ) ;
return 0 ;
err_kfree :
kfree ( dev ) ;
err :
dev_dbg ( & client - > dev , " failed=%d \n " , ret ) ;
return ret ;
}
static int tda10071_remove ( struct i2c_client * client )
{
struct tda10071_dev * dev = i2c_get_clientdata ( client ) ;
dev_dbg ( & client - > dev , " \n " ) ;
kfree ( dev ) ;
return 0 ;
}
static const struct i2c_device_id tda10071_id_table [ ] = {
{ " tda10071_cx24118 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , tda10071_id_table ) ;
static struct i2c_driver tda10071_driver = {
. driver = {
. name = " tda10071 " ,
. suppress_bind_attrs = true ,
} ,
. probe = tda10071_probe ,
. remove = tda10071_remove ,
. id_table = tda10071_id_table ,
} ;
module_i2c_driver ( tda10071_driver ) ;
2011-08-01 08:07:39 +04:00
MODULE_AUTHOR ( " Antti Palosaari <crope@iki.fi> " ) ;
MODULE_DESCRIPTION ( " NXP TDA10071 DVB-S/S2 demodulator driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
2012-09-12 18:37:29 +04:00
MODULE_FIRMWARE ( TDA10071_FIRMWARE ) ;