2008-09-15 22:01:52 +04:00
/*
2010-06-18 04:19:13 +04:00
* Afatech AF9013 demodulator driver
2008-09-15 22:01:52 +04:00
*
* Copyright ( C ) 2007 Antti Palosaari < crope @ iki . fi >
2011-11-29 03:58:11 +04:00
* Copyright ( C ) 2011 Antti Palosaari < crope @ iki . fi >
2008-09-15 22:01:52 +04:00
*
* Thanks to Afatech who kindly provided information .
*
* 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 "af9013_priv.h"
int af9013_debug ;
2011-11-29 03:58:11 +04:00
module_param_named ( debug , af9013_debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " Turn on/off frontend debugging (default:off). " ) ;
2008-09-15 22:01:52 +04:00
struct af9013_state {
struct i2c_adapter * i2c ;
2011-11-29 03:58:11 +04:00
struct dvb_frontend fe ;
2008-09-15 22:01:52 +04:00
struct af9013_config config ;
2010-10-07 23:34:55 +04:00
/* tuner/demod RF and IF AGC limits used for signal strength calc */
u8 signal_strength_en , rf_50 , rf_80 , if_50 , if_80 ;
2008-09-15 22:01:52 +04:00
u16 signal_strength ;
u32 ber ;
u32 ucblocks ;
u16 snr ;
2011-11-29 03:58:11 +04:00
u32 bandwidth_hz ;
fe_status_t fe_status ;
unsigned long set_frontend_jiffies ;
unsigned long read_status_jiffies ;
bool first_tune ;
bool i2c_gate_state ;
unsigned int statistics_step : 3 ;
struct delayed_work statistics_work ;
2008-09-15 22:01:52 +04:00
} ;
2011-11-29 03:58:11 +04:00
/* write multiple registers */
static int af9013_wr_regs_i2c ( struct af9013_state * priv , u8 mbox , u16 reg ,
const u8 * val , int len )
2008-09-15 22:01:52 +04:00
{
2011-11-29 03:58:11 +04:00
int ret ;
2008-09-15 22:01:52 +04:00
u8 buf [ 3 + len ] ;
2011-11-29 03:58:11 +04:00
struct i2c_msg msg [ 1 ] = {
{
. addr = priv - > config . i2c_addr ,
. flags = 0 ,
. len = sizeof ( buf ) ,
. buf = buf ,
}
} ;
buf [ 0 ] = ( reg > > 8 ) & 0xff ;
buf [ 1 ] = ( reg > > 0 ) & 0xff ;
2008-09-15 22:01:52 +04:00
buf [ 2 ] = mbox ;
memcpy ( & buf [ 3 ] , val , len ) ;
2011-11-29 03:58:11 +04:00
ret = i2c_transfer ( priv - > i2c , msg , 1 ) ;
if ( ret = = 1 ) {
ret = 0 ;
} else {
warn ( " i2c wr failed=%d reg=%04x len=%d " , ret , reg , len ) ;
ret = - EREMOTEIO ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
return ret ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
/* read multiple registers */
static int af9013_rd_regs_i2c ( struct af9013_state * priv , u8 mbox , u16 reg ,
u8 * val , int len )
2008-09-15 22:01:52 +04:00
{
2011-11-29 03:58:11 +04:00
int ret ;
u8 buf [ 3 ] ;
struct i2c_msg msg [ 2 ] = {
{
. addr = priv - > config . i2c_addr ,
. flags = 0 ,
. len = 3 ,
. buf = buf ,
} , {
. addr = priv - > config . i2c_addr ,
. flags = I2C_M_RD ,
. len = len ,
. buf = val ,
}
} ;
buf [ 0 ] = ( reg > > 8 ) & 0xff ;
buf [ 1 ] = ( reg > > 0 ) & 0xff ;
buf [ 2 ] = mbox ;
ret = i2c_transfer ( priv - > i2c , msg , 2 ) ;
if ( ret = = 2 ) {
ret = 0 ;
} else {
warn ( " i2c rd failed=%d reg=%04x len=%d " , ret , reg , len ) ;
ret = - EREMOTEIO ;
}
return ret ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
/* write multiple registers */
static int af9013_wr_regs ( struct af9013_state * priv , u16 reg , const u8 * val ,
int len )
2008-09-15 22:01:52 +04:00
{
2011-11-29 03:58:11 +04:00
int ret , i ;
u8 mbox = ( 0 < < 7 ) | ( 0 < < 6 ) | ( 1 < < 1 ) | ( 1 < < 0 ) ;
2012-01-05 09:23:28 +04:00
if ( ( priv - > config . ts_mode = = AF9013_TS_USB ) & &
( ( reg & 0xff00 ) ! = 0xff00 ) & & ( ( reg & 0xff00 ) ! = 0xae00 ) ) {
2011-11-29 03:58:11 +04:00
mbox | = ( ( len - 1 ) < < 2 ) ;
ret = af9013_wr_regs_i2c ( priv , mbox , reg , val , len ) ;
} else {
for ( i = 0 ; i < len ; i + + ) {
ret = af9013_wr_regs_i2c ( priv , mbox , reg + i , val + i , 1 ) ;
if ( ret )
goto err ;
}
}
err :
return 0 ;
}
/* read multiple registers */
static int af9013_rd_regs ( struct af9013_state * priv , u16 reg , u8 * val , int len )
{
int ret , i ;
u8 mbox = ( 0 < < 7 ) | ( 0 < < 6 ) | ( 1 < < 1 ) | ( 0 < < 0 ) ;
2012-01-05 09:23:28 +04:00
if ( ( priv - > config . ts_mode = = AF9013_TS_USB ) & &
( ( reg & 0xff00 ) ! = 0xff00 ) & & ( ( reg & 0xff00 ) ! = 0xae00 ) ) {
2011-11-29 03:58:11 +04:00
mbox | = ( ( len - 1 ) < < 2 ) ;
ret = af9013_rd_regs_i2c ( priv , mbox , reg , val , len ) ;
} else {
for ( i = 0 ; i < len ; i + + ) {
ret = af9013_rd_regs_i2c ( priv , mbox , reg + i , val + i , 1 ) ;
if ( ret )
goto err ;
}
}
err :
return 0 ;
2008-09-15 22:01:52 +04:00
}
/* write single register */
2011-11-29 03:58:11 +04:00
static int af9013_wr_reg ( struct af9013_state * priv , u16 reg , u8 val )
2008-09-15 22:01:52 +04:00
{
2011-11-29 03:58:11 +04:00
return af9013_wr_regs ( priv , reg , & val , 1 ) ;
2008-09-15 22:01:52 +04:00
}
/* read single register */
2011-11-29 03:58:11 +04:00
static int af9013_rd_reg ( struct af9013_state * priv , u16 reg , u8 * val )
2008-09-15 22:01:52 +04:00
{
2011-11-29 03:58:11 +04:00
return af9013_rd_regs ( priv , reg , val , 1 ) ;
}
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
static int af9013_write_ofsm_regs ( struct af9013_state * state , u16 reg , u8 * val ,
u8 len )
{
u8 mbox = ( 1 < < 7 ) | ( 1 < < 6 ) | ( ( len - 1 ) < < 2 ) | ( 1 < < 1 ) | ( 1 < < 0 ) ;
return af9013_wr_regs_i2c ( state , mbox , reg , val , len ) ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
static int af9013_wr_reg_bits ( struct af9013_state * state , u16 reg , int pos ,
int len , u8 val )
2008-09-15 22:01:52 +04:00
{
int ret ;
u8 tmp , mask ;
2011-11-29 03:58:11 +04:00
/* no need for read if whole reg is written */
if ( len ! = 8 ) {
ret = af9013_rd_reg ( state , reg , & tmp ) ;
if ( ret )
return ret ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
mask = ( 0xff > > ( 8 - len ) ) < < pos ;
val < < = pos ;
tmp & = ~ mask ;
val | = tmp ;
}
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
return af9013_wr_reg ( state , reg , val ) ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
static int af9013_rd_reg_bits ( struct af9013_state * state , u16 reg , int pos ,
int len , u8 * val )
2008-09-15 22:01:52 +04:00
{
int ret ;
u8 tmp ;
2011-11-29 03:58:11 +04:00
ret = af9013_rd_reg ( state , reg , & tmp ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
return ret ;
2011-11-29 03:58:11 +04:00
* val = ( tmp > > pos ) ;
* val & = ( 0xff > > ( 8 - len ) ) ;
2008-09-15 22:01:52 +04:00
return 0 ;
}
static int af9013_set_gpio ( struct af9013_state * state , u8 gpio , u8 gpioval )
{
int ret ;
u8 pos ;
u16 addr ;
2011-11-29 03:58:11 +04:00
dbg ( " %s: gpio=%d gpioval=%02x " , __func__ , gpio , gpioval ) ;
/*
* GPIO0 & GPIO1 0xd735
* GPIO2 & GPIO3 0xd736
*/
2008-09-15 22:01:52 +04:00
switch ( gpio ) {
case 0 :
case 1 :
addr = 0xd735 ;
break ;
case 2 :
case 3 :
addr = 0xd736 ;
break ;
default :
err ( " invalid gpio:%d \n " , gpio ) ;
ret = - EINVAL ;
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
} ;
switch ( gpio ) {
case 0 :
case 2 :
pos = 0 ;
break ;
case 1 :
case 3 :
default :
pos = 4 ;
break ;
} ;
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg_bits ( state , addr , pos , 4 , gpioval ) ;
if ( ret )
goto err ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
2008-09-15 22:01:52 +04:00
return ret ;
}
static u32 af913_div ( u32 a , u32 b , u32 x )
{
u32 r = 0 , c = 0 , i ;
2011-11-29 03:58:11 +04:00
dbg ( " %s: a=%d b=%d x=%d " , __func__ , a , b , x ) ;
2008-09-15 22:01:52 +04:00
if ( a > b ) {
c = a / b ;
a = a - c * b ;
}
for ( i = 0 ; i < x ; i + + ) {
if ( a > = b ) {
r + = 1 ;
a - = b ;
}
a < < = 1 ;
r < < = 1 ;
}
r = ( c < < ( u32 ) x ) + r ;
2011-11-29 03:58:11 +04:00
dbg ( " %s: a=%d b=%d x=%d r=%x " , __func__ , a , b , x , r ) ;
2008-09-15 22:01:52 +04:00
return r ;
}
2011-11-29 03:58:11 +04:00
static int af9013_power_ctrl ( struct af9013_state * state , u8 onoff )
2008-09-15 22:01:52 +04:00
{
2011-11-29 03:58:11 +04:00
int ret , i ;
u8 tmp ;
2010-09-13 03:48:58 +04:00
2011-11-29 03:58:11 +04:00
dbg ( " %s: onoff=%d " , __func__ , onoff ) ;
/* enable reset */
ret = af9013_wr_reg_bits ( state , 0xd417 , 4 , 1 , 1 ) ;
if ( ret )
goto err ;
/* start reset mechanism */
ret = af9013_wr_reg ( state , 0xaeff , 1 ) ;
if ( ret )
goto err ;
/* wait reset performs */
for ( i = 0 ; i < 150 ; i + + ) {
ret = af9013_rd_reg_bits ( state , 0xd417 , 1 , 1 , & tmp ) ;
if ( ret )
goto err ;
if ( tmp )
break ; /* reset done */
usleep_range ( 5000 , 25000 ) ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
if ( ! tmp )
return - ETIMEDOUT ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
if ( onoff ) {
/* clear reset */
ret = af9013_wr_reg_bits ( state , 0xd417 , 1 , 1 , 0 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
/* disable reset */
ret = af9013_wr_reg_bits ( state , 0xd417 , 4 , 1 , 0 ) ;
/* power on */
ret = af9013_wr_reg_bits ( state , 0xd73a , 3 , 1 , 0 ) ;
} else {
/* power off */
ret = af9013_wr_reg_bits ( state , 0xd73a , 3 , 1 , 1 ) ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
2008-09-15 22:01:52 +04:00
return ret ;
}
2011-11-29 03:58:11 +04:00
static int af9013_statistics_ber_unc_start ( struct dvb_frontend * fe )
2008-09-15 22:01:52 +04:00
{
2011-11-29 03:58:11 +04:00
struct af9013_state * state = fe - > demodulator_priv ;
2008-09-15 22:01:52 +04:00
int ret ;
2011-11-29 03:58:11 +04:00
dbg ( " %s " , __func__ ) ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
/* reset and start BER counter */
ret = af9013_wr_reg_bits ( state , 0xd391 , 4 , 1 , 1 ) ;
if ( ret )
goto err ;
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
return ret ;
}
static int af9013_statistics_ber_unc_result ( struct dvb_frontend * fe )
{
struct af9013_state * state = fe - > demodulator_priv ;
int ret ;
u8 buf [ 5 ] ;
dbg ( " %s " , __func__ ) ;
/* check if error bit count is ready */
ret = af9013_rd_reg_bits ( state , 0xd391 , 4 , 1 , & buf [ 0 ] ) ;
if ( ret )
goto err ;
if ( ! buf [ 0 ] ) {
dbg ( " %s: not ready " , __func__ ) ;
return 0 ;
}
ret = af9013_rd_regs ( state , 0xd387 , buf , 5 ) ;
if ( ret )
goto err ;
state - > ber = ( buf [ 2 ] < < 16 ) | ( buf [ 1 ] < < 8 ) | buf [ 0 ] ;
state - > ucblocks + = ( buf [ 4 ] < < 8 ) | buf [ 3 ] ;
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
return ret ;
}
static int af9013_statistics_snr_start ( struct dvb_frontend * fe )
{
struct af9013_state * state = fe - > demodulator_priv ;
int ret ;
dbg ( " %s " , __func__ ) ;
/* start SNR meas */
ret = af9013_wr_reg_bits ( state , 0xd2e1 , 3 , 1 , 1 ) ;
if ( ret )
goto err ;
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
return ret ;
}
static int af9013_statistics_snr_result ( struct dvb_frontend * fe )
{
struct af9013_state * state = fe - > demodulator_priv ;
int ret , i , len ;
u8 buf [ 3 ] , tmp ;
u32 snr_val ;
const struct af9013_snr * uninitialized_var ( snr_lut ) ;
dbg ( " %s " , __func__ ) ;
/* check if SNR ready */
ret = af9013_rd_reg_bits ( state , 0xd2e1 , 3 , 1 , & tmp ) ;
if ( ret )
goto err ;
if ( ! tmp ) {
dbg ( " %s: not ready " , __func__ ) ;
return 0 ;
}
/* read value */
ret = af9013_rd_regs ( state , 0xd2e3 , buf , 3 ) ;
if ( ret )
goto err ;
snr_val = ( buf [ 2 ] < < 16 ) | ( buf [ 1 ] < < 8 ) | buf [ 0 ] ;
/* read current modulation */
ret = af9013_rd_reg ( state , 0xd3c1 , & tmp ) ;
if ( ret )
goto err ;
switch ( ( tmp > > 6 ) & 3 ) {
case 0 :
len = ARRAY_SIZE ( qpsk_snr_lut ) ;
snr_lut = qpsk_snr_lut ;
2008-09-15 22:01:52 +04:00
break ;
2011-11-29 03:58:11 +04:00
case 1 :
len = ARRAY_SIZE ( qam16_snr_lut ) ;
snr_lut = qam16_snr_lut ;
2008-09-15 22:01:52 +04:00
break ;
2011-11-29 03:58:11 +04:00
case 2 :
len = ARRAY_SIZE ( qam64_snr_lut ) ;
snr_lut = qam64_snr_lut ;
2008-09-15 22:01:52 +04:00
break ;
default :
2011-11-29 03:58:11 +04:00
goto err ;
break ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
for ( i = 0 ; i < len ; i + + ) {
tmp = snr_lut [ i ] . snr ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
if ( snr_val < snr_lut [ i ] . val )
break ;
}
state - > snr = tmp * 10 ; /* dB/10 */
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
return ret ;
}
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
static int af9013_statistics_signal_strength ( struct dvb_frontend * fe )
{
struct af9013_state * state = fe - > demodulator_priv ;
int ret = 0 ;
u8 buf [ 2 ] , rf_gain , if_gain ;
int signal_strength ;
dbg ( " %s " , __func__ ) ;
if ( ! state - > signal_strength_en )
return 0 ;
ret = af9013_rd_regs ( state , 0xd07c , buf , 2 ) ;
if ( ret )
goto err ;
rf_gain = buf [ 0 ] ;
if_gain = buf [ 1 ] ;
signal_strength = ( 0xffff / \
( 9 * ( state - > rf_50 + state - > if_50 ) - \
11 * ( state - > rf_80 + state - > if_80 ) ) ) * \
( 10 * ( rf_gain + if_gain ) - \
11 * ( state - > rf_80 + state - > if_80 ) ) ;
if ( signal_strength < 0 )
signal_strength = 0 ;
else if ( signal_strength > 0xffff )
signal_strength = 0xffff ;
state - > signal_strength = signal_strength ;
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
2008-09-15 22:01:52 +04:00
return ret ;
}
2011-11-29 03:58:11 +04:00
static void af9013_statistics_work ( struct work_struct * work )
2008-09-15 22:01:52 +04:00
{
2011-11-29 03:58:11 +04:00
struct af9013_state * state = container_of ( work ,
struct af9013_state , statistics_work . work ) ;
unsigned int next_msec ;
/* update only signal strength when demod is not locked */
if ( ! ( state - > fe_status & FE_HAS_LOCK ) ) {
state - > statistics_step = 0 ;
state - > ber = 0 ;
state - > snr = 0 ;
}
switch ( state - > statistics_step ) {
default :
state - > statistics_step = 0 ;
case 0 :
2012-04-20 15:04:48 +04:00
af9013_statistics_signal_strength ( & state - > fe ) ;
2011-11-29 03:58:11 +04:00
state - > statistics_step + + ;
next_msec = 300 ;
break ;
case 1 :
2012-04-20 15:04:48 +04:00
af9013_statistics_snr_start ( & state - > fe ) ;
2011-11-29 03:58:11 +04:00
state - > statistics_step + + ;
next_msec = 200 ;
break ;
case 2 :
2012-04-20 15:04:48 +04:00
af9013_statistics_ber_unc_start ( & state - > fe ) ;
2011-11-29 03:58:11 +04:00
state - > statistics_step + + ;
next_msec = 1000 ;
break ;
case 3 :
2012-04-20 15:04:48 +04:00
af9013_statistics_snr_result ( & state - > fe ) ;
2011-11-29 03:58:11 +04:00
state - > statistics_step + + ;
next_msec = 400 ;
break ;
case 4 :
2012-04-20 15:04:48 +04:00
af9013_statistics_ber_unc_result ( & state - > fe ) ;
2011-11-29 03:58:11 +04:00
state - > statistics_step + + ;
next_msec = 100 ;
break ;
}
schedule_delayed_work ( & state - > statistics_work ,
msecs_to_jiffies ( next_msec ) ) ;
}
static int af9013_get_tune_settings ( struct dvb_frontend * fe ,
struct dvb_frontend_tune_settings * fesettings )
{
fesettings - > min_delay_ms = 800 ;
fesettings - > step_size = 0 ;
fesettings - > max_drift = 0 ;
return 0 ;
}
2011-12-31 05:25:27 +04:00
static int af9013_set_frontend ( struct dvb_frontend * fe )
2011-11-29 03:58:11 +04:00
{
struct af9013_state * state = fe - > demodulator_priv ;
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
int ret , i , sampling_freq ;
bool auto_mode , spec_inv ;
u8 buf [ 6 ] ;
u32 if_frequency , freq_cw ;
dbg ( " %s: frequency=%d bandwidth_hz=%d " , __func__ ,
c - > frequency , c - > bandwidth_hz ) ;
/* program tuner */
if ( fe - > ops . tuner_ops . set_params )
2011-12-24 19:24:33 +04:00
fe - > ops . tuner_ops . set_params ( fe ) ;
2011-11-29 03:58:11 +04:00
/* program CFOE coefficients */
if ( c - > bandwidth_hz ! = state - > bandwidth_hz ) {
for ( i = 0 ; i < ARRAY_SIZE ( coeff_lut ) ; i + + ) {
if ( coeff_lut [ i ] . clock = = state - > config . clock & &
coeff_lut [ i ] . bandwidth_hz = = c - > bandwidth_hz ) {
break ;
}
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
ret = af9013_wr_regs ( state , 0xae00 , coeff_lut [ i ] . val ,
sizeof ( coeff_lut [ i ] . val ) ) ;
}
2011-11-13 07:26:17 +04:00
2011-11-29 03:58:11 +04:00
/* program frequency control */
if ( c - > bandwidth_hz ! = state - > bandwidth_hz | | state - > first_tune ) {
2011-11-13 07:26:17 +04:00
/* get used IF frequency */
if ( fe - > ops . tuner_ops . get_if_frequency )
2011-11-29 03:58:11 +04:00
fe - > ops . tuner_ops . get_if_frequency ( fe , & if_frequency ) ;
2011-11-13 07:26:17 +04:00
else
2011-11-29 03:58:11 +04:00
if_frequency = state - > config . if_frequency ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
sampling_freq = if_frequency ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
while ( sampling_freq > ( state - > config . clock / 2 ) )
sampling_freq - = state - > config . clock ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
if ( sampling_freq < 0 ) {
sampling_freq * = - 1 ;
spec_inv = state - > config . spec_inv ;
} else {
spec_inv = ! state - > config . spec_inv ;
}
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
freq_cw = af913_div ( sampling_freq , state - > config . clock , 23 ) ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
if ( spec_inv )
freq_cw = 0x800000 - freq_cw ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
buf [ 0 ] = ( freq_cw > > 0 ) & 0xff ;
buf [ 1 ] = ( freq_cw > > 8 ) & 0xff ;
buf [ 2 ] = ( freq_cw > > 16 ) & 0x7f ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
freq_cw = 0x800000 - freq_cw ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
buf [ 3 ] = ( freq_cw > > 0 ) & 0xff ;
buf [ 4 ] = ( freq_cw > > 8 ) & 0xff ;
buf [ 5 ] = ( freq_cw > > 16 ) & 0x7f ;
ret = af9013_wr_regs ( state , 0xd140 , buf , 3 ) ;
if ( ret )
goto err ;
ret = af9013_wr_regs ( state , 0x9be7 , buf , 6 ) ;
if ( ret )
goto err ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
/* clear TPS lock flag */
ret = af9013_wr_reg_bits ( state , 0xd330 , 3 , 1 , 1 ) ;
if ( ret )
goto err ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
/* clear MPEG2 lock flag */
ret = af9013_wr_reg_bits ( state , 0xd507 , 6 , 1 , 0 ) ;
if ( ret )
goto err ;
2009-07-11 03:03:43 +04:00
2011-11-29 03:58:11 +04:00
/* empty channel function */
ret = af9013_wr_reg_bits ( state , 0x9bfe , 0 , 1 , 0 ) ;
if ( ret )
goto err ;
/* empty DVB-T channel function */
ret = af9013_wr_reg_bits ( state , 0x9bc2 , 0 , 1 , 0 ) ;
if ( ret )
goto err ;
/* transmission parameters */
auto_mode = false ;
memset ( buf , 0 , 3 ) ;
switch ( c - > transmission_mode ) {
2008-09-15 22:01:52 +04:00
case TRANSMISSION_MODE_AUTO :
2011-11-29 03:58:11 +04:00
auto_mode = 1 ;
break ;
2008-09-15 22:01:52 +04:00
case TRANSMISSION_MODE_2K :
break ;
case TRANSMISSION_MODE_8K :
buf [ 0 ] | = ( 1 < < 0 ) ;
break ;
default :
2011-11-29 03:58:11 +04:00
dbg ( " %s: invalid transmission_mode " , __func__ ) ;
auto_mode = 1 ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
switch ( c - > guard_interval ) {
2008-09-15 22:01:52 +04:00
case GUARD_INTERVAL_AUTO :
2011-11-29 03:58:11 +04:00
auto_mode = 1 ;
break ;
2008-09-15 22:01:52 +04:00
case GUARD_INTERVAL_1_32 :
break ;
case GUARD_INTERVAL_1_16 :
buf [ 0 ] | = ( 1 < < 2 ) ;
break ;
case GUARD_INTERVAL_1_8 :
buf [ 0 ] | = ( 2 < < 2 ) ;
break ;
case GUARD_INTERVAL_1_4 :
buf [ 0 ] | = ( 3 < < 2 ) ;
break ;
default :
2011-11-29 03:58:11 +04:00
dbg ( " %s: invalid guard_interval " , __func__ ) ;
auto_mode = 1 ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
switch ( c - > hierarchy ) {
2008-09-15 22:01:52 +04:00
case HIERARCHY_AUTO :
2011-11-29 03:58:11 +04:00
auto_mode = 1 ;
break ;
2008-09-15 22:01:52 +04:00
case HIERARCHY_NONE :
break ;
case HIERARCHY_1 :
buf [ 0 ] | = ( 1 < < 4 ) ;
break ;
case HIERARCHY_2 :
buf [ 0 ] | = ( 2 < < 4 ) ;
break ;
case HIERARCHY_4 :
buf [ 0 ] | = ( 3 < < 4 ) ;
break ;
default :
2011-11-29 03:58:11 +04:00
dbg ( " %s: invalid hierarchy " , __func__ ) ;
auto_mode = 1 ;
2008-09-15 22:01:52 +04:00
} ;
2011-11-29 03:58:11 +04:00
switch ( c - > modulation ) {
2008-09-15 22:01:52 +04:00
case QAM_AUTO :
2011-11-29 03:58:11 +04:00
auto_mode = 1 ;
break ;
2008-09-15 22:01:52 +04:00
case QPSK :
break ;
case QAM_16 :
buf [ 1 ] | = ( 1 < < 6 ) ;
break ;
case QAM_64 :
buf [ 1 ] | = ( 2 < < 6 ) ;
break ;
default :
2011-11-29 03:58:11 +04:00
dbg ( " %s: invalid modulation " , __func__ ) ;
auto_mode = 1 ;
2008-09-15 22:01:52 +04:00
}
/* Use HP. How and which case we can switch to LP? */
buf [ 1 ] | = ( 1 < < 4 ) ;
2011-11-29 03:58:11 +04:00
switch ( c - > code_rate_HP ) {
2008-09-15 22:01:52 +04:00
case FEC_AUTO :
2011-11-29 03:58:11 +04:00
auto_mode = 1 ;
break ;
2008-09-15 22:01:52 +04:00
case FEC_1_2 :
break ;
case FEC_2_3 :
buf [ 2 ] | = ( 1 < < 0 ) ;
break ;
case FEC_3_4 :
buf [ 2 ] | = ( 2 < < 0 ) ;
break ;
case FEC_5_6 :
buf [ 2 ] | = ( 3 < < 0 ) ;
break ;
case FEC_7_8 :
buf [ 2 ] | = ( 4 < < 0 ) ;
break ;
default :
2011-11-29 03:58:11 +04:00
dbg ( " %s: invalid code_rate_HP " , __func__ ) ;
auto_mode = 1 ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
switch ( c - > code_rate_LP ) {
2008-09-15 22:01:52 +04:00
case FEC_AUTO :
2011-11-29 03:58:11 +04:00
auto_mode = 1 ;
break ;
2008-09-15 22:01:52 +04:00
case FEC_1_2 :
break ;
case FEC_2_3 :
buf [ 2 ] | = ( 1 < < 3 ) ;
break ;
case FEC_3_4 :
buf [ 2 ] | = ( 2 < < 3 ) ;
break ;
case FEC_5_6 :
buf [ 2 ] | = ( 3 < < 3 ) ;
break ;
case FEC_7_8 :
buf [ 2 ] | = ( 4 < < 3 ) ;
break ;
case FEC_NONE :
2011-11-29 03:58:11 +04:00
break ;
2008-09-15 22:01:52 +04:00
default :
2011-11-29 03:58:11 +04:00
dbg ( " %s: invalid code_rate_LP " , __func__ ) ;
auto_mode = 1 ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
switch ( c - > bandwidth_hz ) {
case 6000000 :
2008-09-15 22:01:52 +04:00
break ;
2011-11-29 03:58:11 +04:00
case 7000000 :
2008-09-15 22:01:52 +04:00
buf [ 1 ] | = ( 1 < < 2 ) ;
break ;
2011-11-29 03:58:11 +04:00
case 8000000 :
2008-09-15 22:01:52 +04:00
buf [ 1 ] | = ( 2 < < 2 ) ;
break ;
default :
2011-11-29 03:58:11 +04:00
dbg ( " %s: invalid bandwidth_hz " , __func__ ) ;
ret = - EINVAL ;
goto err ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
ret = af9013_wr_regs ( state , 0xd3c0 , buf , 3 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
if ( auto_mode ) {
/* clear easy mode flag */
ret = af9013_wr_reg ( state , 0xaefd , 0 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
dbg ( " %s: auto params " , __func__ ) ;
2008-09-15 22:01:52 +04:00
} else {
2011-11-29 03:58:11 +04:00
/* set easy mode flag */
ret = af9013_wr_reg ( state , 0xaefd , 1 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg ( state , 0xaefe , 0 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
dbg ( " %s: manual params " , __func__ ) ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
/* tune */
ret = af9013_wr_reg ( state , 0xffff , 0 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
state - > bandwidth_hz = c - > bandwidth_hz ;
state - > set_frontend_jiffies = jiffies ;
state - > first_tune = false ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
2008-09-15 22:01:52 +04:00
return ret ;
}
[media] dvb: don't require a parameter for get_frontend
Just like set_frontend, use the dvb cache properties for get_frontend.
This is more consistent, as both functions are now symetric. Also,
at the places get_frontend is called, it makes sense to update the
cache.
Most of this patch were generated by this small perl script:
while (<>) { $file .= $_; }
if ($file =~ m/\.get_frontend\s*=\s*([\d\w_]+)/) {
my $get = $1;
$file =~ s/($get)(\s*\([^\,\)]+)\,\s*struct\s+dtv_frontend_properties\s*\*\s*([_\d\w]+)\)\s*\{/\1\2)\n{\n\tstruct dtv_frontend_properties *\3 = &fe->dtv_property_cache;/g;
}
print $file;
Of course, the changes at dvb_frontend.[ch] were made by hand,
as well as the changes on a few other places, where get_frontend()
is called internally inside the driver.
On some places, get_frontend() were just a void function. Those
occurrences were removed, as the DVB core handles such cases.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2011-12-30 18:30:21 +04:00
static int af9013_get_frontend ( struct dvb_frontend * fe )
2008-09-15 22:01:52 +04:00
{
[media] dvb: don't require a parameter for get_frontend
Just like set_frontend, use the dvb cache properties for get_frontend.
This is more consistent, as both functions are now symetric. Also,
at the places get_frontend is called, it makes sense to update the
cache.
Most of this patch were generated by this small perl script:
while (<>) { $file .= $_; }
if ($file =~ m/\.get_frontend\s*=\s*([\d\w_]+)/) {
my $get = $1;
$file =~ s/($get)(\s*\([^\,\)]+)\,\s*struct\s+dtv_frontend_properties\s*\*\s*([_\d\w]+)\)\s*\{/\1\2)\n{\n\tstruct dtv_frontend_properties *\3 = &fe->dtv_property_cache;/g;
}
print $file;
Of course, the changes at dvb_frontend.[ch] were made by hand,
as well as the changes on a few other places, where get_frontend()
is called internally inside the driver.
On some places, get_frontend() were just a void function. Those
occurrences were removed, as the DVB core handles such cases.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2011-12-30 18:30:21 +04:00
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
2008-09-15 22:01:52 +04:00
struct af9013_state * state = fe - > demodulator_priv ;
int ret ;
2011-11-29 03:58:11 +04:00
u8 buf [ 3 ] ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
dbg ( " %s " , __func__ ) ;
ret = af9013_rd_regs ( state , 0xd3c0 , buf , 3 ) ;
if ( ret )
goto err ;
2008-09-15 22:01:52 +04:00
switch ( ( buf [ 1 ] > > 6 ) & 3 ) {
case 0 :
2011-11-29 03:58:11 +04:00
c - > modulation = QPSK ;
2008-09-15 22:01:52 +04:00
break ;
case 1 :
2011-11-29 03:58:11 +04:00
c - > modulation = QAM_16 ;
2008-09-15 22:01:52 +04:00
break ;
case 2 :
2011-11-29 03:58:11 +04:00
c - > modulation = QAM_64 ;
2008-09-15 22:01:52 +04:00
break ;
}
switch ( ( buf [ 0 ] > > 0 ) & 3 ) {
case 0 :
2011-11-29 03:58:11 +04:00
c - > transmission_mode = TRANSMISSION_MODE_2K ;
2008-09-15 22:01:52 +04:00
break ;
case 1 :
2011-11-29 03:58:11 +04:00
c - > transmission_mode = TRANSMISSION_MODE_8K ;
2008-09-15 22:01:52 +04:00
}
switch ( ( buf [ 0 ] > > 2 ) & 3 ) {
case 0 :
2012-01-03 20:47:35 +04:00
c - > guard_interval = GUARD_INTERVAL_1_32 ;
2008-09-15 22:01:52 +04:00
break ;
case 1 :
2012-01-03 20:47:35 +04:00
c - > guard_interval = GUARD_INTERVAL_1_16 ;
2008-09-15 22:01:52 +04:00
break ;
case 2 :
2012-01-03 20:47:35 +04:00
c - > guard_interval = GUARD_INTERVAL_1_8 ;
2008-09-15 22:01:52 +04:00
break ;
case 3 :
2012-01-03 20:47:35 +04:00
c - > guard_interval = GUARD_INTERVAL_1_4 ;
2008-09-15 22:01:52 +04:00
break ;
}
switch ( ( buf [ 0 ] > > 4 ) & 7 ) {
case 0 :
2011-11-29 03:58:11 +04:00
c - > hierarchy = HIERARCHY_NONE ;
2008-09-15 22:01:52 +04:00
break ;
case 1 :
2011-11-29 03:58:11 +04:00
c - > hierarchy = HIERARCHY_1 ;
2008-09-15 22:01:52 +04:00
break ;
case 2 :
2011-11-29 03:58:11 +04:00
c - > hierarchy = HIERARCHY_2 ;
2008-09-15 22:01:52 +04:00
break ;
case 3 :
2011-11-29 03:58:11 +04:00
c - > hierarchy = HIERARCHY_4 ;
2008-09-15 22:01:52 +04:00
break ;
}
switch ( ( buf [ 2 ] > > 0 ) & 7 ) {
case 0 :
2011-11-29 03:58:11 +04:00
c - > code_rate_HP = FEC_1_2 ;
2008-09-15 22:01:52 +04:00
break ;
case 1 :
2011-11-29 03:58:11 +04:00
c - > code_rate_HP = FEC_2_3 ;
break ;
case 2 :
c - > code_rate_HP = FEC_3_4 ;
break ;
case 3 :
c - > code_rate_HP = FEC_5_6 ;
break ;
case 4 :
c - > code_rate_HP = FEC_7_8 ;
break ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
switch ( ( buf [ 2 ] > > 3 ) & 7 ) {
case 0 :
c - > code_rate_LP = FEC_1_2 ;
break ;
case 1 :
c - > code_rate_LP = FEC_2_3 ;
break ;
case 2 :
c - > code_rate_LP = FEC_3_4 ;
break ;
case 3 :
c - > code_rate_LP = FEC_5_6 ;
break ;
case 4 :
c - > code_rate_LP = FEC_7_8 ;
break ;
}
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
switch ( ( buf [ 1 ] > > 2 ) & 3 ) {
case 0 :
c - > bandwidth_hz = 6000000 ;
break ;
case 1 :
c - > bandwidth_hz = 7000000 ;
break ;
case 2 :
c - > bandwidth_hz = 8000000 ;
break ;
2008-09-15 22:01:52 +04:00
}
return ret ;
2011-11-29 03:58:11 +04:00
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
2008-09-15 22:01:52 +04:00
return ret ;
}
static int af9013_read_status ( struct dvb_frontend * fe , fe_status_t * status )
{
struct af9013_state * state = fe - > demodulator_priv ;
2011-11-29 03:58:11 +04:00
int ret ;
2008-09-15 22:01:52 +04:00
u8 tmp ;
2011-11-29 03:58:11 +04:00
/*
* Return status from the cache if it is younger than 2000 ms with the
* exception of last tune is done during 4000 ms .
*/
if ( time_is_after_jiffies (
state - > read_status_jiffies + msecs_to_jiffies ( 2000 ) ) & &
time_is_before_jiffies (
state - > set_frontend_jiffies + msecs_to_jiffies ( 4000 ) )
) {
* status = state - > fe_status ;
return 0 ;
} else {
* status = 0 ;
}
2008-09-15 22:01:52 +04:00
/* MPEG2 lock */
2011-11-29 03:58:11 +04:00
ret = af9013_rd_reg_bits ( state , 0xd507 , 6 , 1 , & tmp ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
if ( tmp )
2010-06-18 03:56:27 +04:00
* status | = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
FE_HAS_SYNC | FE_HAS_LOCK ;
2008-09-15 22:01:52 +04:00
2010-06-18 03:56:27 +04:00
if ( ! * status ) {
/* TPS lock */
2011-11-29 03:58:11 +04:00
ret = af9013_rd_reg_bits ( state , 0xd330 , 3 , 1 , & tmp ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
if ( tmp )
2010-06-18 03:56:27 +04:00
* status | = FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
state - > fe_status = * status ;
state - > read_status_jiffies = jiffies ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
2008-09-15 22:01:52 +04:00
return ret ;
}
2011-11-29 03:58:11 +04:00
static int af9013_read_snr ( struct dvb_frontend * fe , u16 * snr )
2008-09-15 22:01:52 +04:00
{
struct af9013_state * state = fe - > demodulator_priv ;
2011-11-29 03:58:11 +04:00
* snr = state - > snr ;
return 0 ;
2008-09-15 22:01:52 +04:00
}
static int af9013_read_signal_strength ( struct dvb_frontend * fe , u16 * strength )
{
struct af9013_state * state = fe - > demodulator_priv ;
* strength = state - > signal_strength ;
2011-11-29 03:58:11 +04:00
return 0 ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
static int af9013_read_ber ( struct dvb_frontend * fe , u32 * ber )
2008-09-15 22:01:52 +04:00
{
struct af9013_state * state = fe - > demodulator_priv ;
2011-11-29 03:58:11 +04:00
* ber = state - > ber ;
return 0 ;
2008-09-15 22:01:52 +04:00
}
static int af9013_read_ucblocks ( struct dvb_frontend * fe , u32 * ucblocks )
{
struct af9013_state * state = fe - > demodulator_priv ;
* ucblocks = state - > ucblocks ;
2011-11-29 03:58:11 +04:00
return 0 ;
2008-09-15 22:01:52 +04:00
}
static int af9013_init ( struct dvb_frontend * fe )
{
struct af9013_state * state = fe - > demodulator_priv ;
int ret , i , len ;
2011-11-29 03:58:11 +04:00
u8 buf [ 3 ] , tmp ;
u32 adc_cw ;
const struct af9013_reg_bit * init ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
dbg ( " %s " , __func__ ) ;
2008-09-15 22:01:52 +04:00
/* power on */
ret = af9013_power_ctrl ( state , 1 ) ;
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* enable ADC */
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg ( state , 0xd73a , 0xa4 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* write API version to firmware */
2011-11-29 03:58:11 +04:00
ret = af9013_wr_regs ( state , 0x9bf2 , state - > config . api_version , 4 ) ;
if ( ret )
goto err ;
2008-09-15 22:01:52 +04:00
/* program ADC control */
2011-11-29 03:58:11 +04:00
switch ( state - > config . clock ) {
case 28800000 : /* 28.800 MHz */
tmp = 0 ;
break ;
case 20480000 : /* 20.480 MHz */
tmp = 1 ;
break ;
case 28000000 : /* 28.000 MHz */
tmp = 2 ;
break ;
case 25000000 : /* 25.000 MHz */
tmp = 3 ;
break ;
default :
err ( " invalid clock " ) ;
return - EINVAL ;
}
adc_cw = af913_div ( state - > config . clock , 1000000ul , 19 ) ;
buf [ 0 ] = ( adc_cw > > 0 ) & 0xff ;
buf [ 1 ] = ( adc_cw > > 8 ) & 0xff ;
buf [ 2 ] = ( adc_cw > > 16 ) & 0xff ;
ret = af9013_wr_regs ( state , 0xd180 , buf , 3 ) ;
if ( ret )
goto err ;
ret = af9013_wr_reg_bits ( state , 0x9bd2 , 0 , 4 , tmp ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* set I2C master clock */
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg ( state , 0xd416 , 0x14 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* set 16 embx */
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg_bits ( state , 0xd700 , 1 , 1 , 1 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* set no trigger */
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg_bits ( state , 0xd700 , 2 , 1 , 0 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* set read-update bit for constellation */
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg_bits ( state , 0xd371 , 1 , 1 , 1 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
/* settings for mp2if */
if ( state - > config . ts_mode = = AF9013_TS_USB ) {
/* AF9015 split PSB to 1.5k + 0.5k */
ret = af9013_wr_reg_bits ( state , 0xd50b , 2 , 1 , 1 ) ;
if ( ret )
goto err ;
} else {
/* AF9013 change the output bit to data7 */
ret = af9013_wr_reg_bits ( state , 0xd500 , 3 , 1 , 1 ) ;
if ( ret )
goto err ;
/* AF9013 set mpeg to full speed */
ret = af9013_wr_reg_bits ( state , 0xd502 , 4 , 1 , 1 ) ;
if ( ret )
goto err ;
}
ret = af9013_wr_reg_bits ( state , 0xd520 , 4 , 1 , 1 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* load OFSM settings */
2011-11-29 03:58:11 +04:00
dbg ( " %s: load ofsm settings " , __func__ ) ;
2008-09-15 22:01:52 +04:00
len = ARRAY_SIZE ( ofsm_init ) ;
init = ofsm_init ;
for ( i = 0 ; i < len ; i + + ) {
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg_bits ( state , init [ i ] . addr , init [ i ] . pos ,
2008-09-15 22:01:52 +04:00
init [ i ] . len , init [ i ] . val ) ;
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
}
/* load tuner specific settings */
2011-11-29 03:58:11 +04:00
dbg ( " %s: load tuner specific settings " , __func__ ) ;
2008-09-15 22:01:52 +04:00
switch ( state - > config . tuner ) {
case AF9013_TUNER_MXL5003D :
len = ARRAY_SIZE ( tuner_init_mxl5003d ) ;
init = tuner_init_mxl5003d ;
break ;
case AF9013_TUNER_MXL5005D :
case AF9013_TUNER_MXL5005R :
2010-09-09 21:53:59 +04:00
case AF9013_TUNER_MXL5007T :
2008-09-15 22:01:52 +04:00
len = ARRAY_SIZE ( tuner_init_mxl5005 ) ;
init = tuner_init_mxl5005 ;
break ;
case AF9013_TUNER_ENV77H11D5 :
len = ARRAY_SIZE ( tuner_init_env77h11d5 ) ;
init = tuner_init_env77h11d5 ;
break ;
case AF9013_TUNER_MT2060 :
len = ARRAY_SIZE ( tuner_init_mt2060 ) ;
init = tuner_init_mt2060 ;
break ;
case AF9013_TUNER_MC44S803 :
len = ARRAY_SIZE ( tuner_init_mc44s803 ) ;
init = tuner_init_mc44s803 ;
break ;
case AF9013_TUNER_QT1010 :
case AF9013_TUNER_QT1010A :
len = ARRAY_SIZE ( tuner_init_qt1010 ) ;
init = tuner_init_qt1010 ;
break ;
case AF9013_TUNER_MT2060_2 :
len = ARRAY_SIZE ( tuner_init_mt2060_2 ) ;
init = tuner_init_mt2060_2 ;
break ;
case AF9013_TUNER_TDA18271 :
2010-08-13 10:49:24 +04:00
case AF9013_TUNER_TDA18218 :
2008-09-15 22:01:52 +04:00
len = ARRAY_SIZE ( tuner_init_tda18271 ) ;
init = tuner_init_tda18271 ;
break ;
case AF9013_TUNER_UNKNOWN :
default :
len = ARRAY_SIZE ( tuner_init_unknown ) ;
init = tuner_init_unknown ;
break ;
}
for ( i = 0 ; i < len ; i + + ) {
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg_bits ( state , init [ i ] . addr , init [ i ] . pos ,
2008-09-15 22:01:52 +04:00
init [ i ] . len , init [ i ] . val ) ;
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
/* TS mode */
ret = af9013_wr_reg_bits ( state , 0xd500 , 1 , 2 , state - > config . ts_mode ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* enable lock led */
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg_bits ( state , 0xd730 , 0 , 1 , 1 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
/* check if we support signal strength */
if ( ! state - > signal_strength_en ) {
ret = af9013_rd_reg_bits ( state , 0x9bee , 0 , 1 ,
& state - > signal_strength_en ) ;
if ( ret )
goto err ;
}
2010-10-07 23:34:55 +04:00
2011-11-29 03:58:11 +04:00
/* read values needed for signal strength calculation */
if ( state - > signal_strength_en & & ! state - > rf_50 ) {
ret = af9013_rd_reg ( state , 0x9bbd , & state - > rf_50 ) ;
2010-10-07 23:34:55 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
ret = af9013_rd_reg ( state , 0x9bd0 , & state - > rf_80 ) ;
2010-10-07 23:34:55 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
ret = af9013_rd_reg ( state , 0x9be2 , & state - > if_50 ) ;
2010-10-07 23:34:55 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
ret = af9013_rd_reg ( state , 0x9be4 , & state - > if_80 ) ;
2010-10-07 23:34:55 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2010-10-07 23:34:55 +04:00
}
2011-11-29 03:58:11 +04:00
/* SNR */
ret = af9013_wr_reg ( state , 0xd2e2 , 1 ) ;
if ( ret )
goto err ;
/* BER / UCB */
buf [ 0 ] = ( 10000 > > 0 ) & 0xff ;
buf [ 1 ] = ( 10000 > > 8 ) & 0xff ;
ret = af9013_wr_regs ( state , 0xd385 , buf , 2 ) ;
if ( ret )
goto err ;
/* enable FEC monitor */
ret = af9013_wr_reg_bits ( state , 0xd392 , 1 , 1 , 1 ) ;
if ( ret )
goto err ;
state - > first_tune = true ;
schedule_delayed_work ( & state - > statistics_work , msecs_to_jiffies ( 400 ) ) ;
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
return ret ;
}
static int af9013_sleep ( struct dvb_frontend * fe )
{
struct af9013_state * state = fe - > demodulator_priv ;
int ret ;
dbg ( " %s " , __func__ ) ;
/* stop statistics polling */
cancel_delayed_work_sync ( & state - > statistics_work ) ;
/* disable lock led */
ret = af9013_wr_reg_bits ( state , 0xd730 , 0 , 1 , 0 ) ;
if ( ret )
goto err ;
/* power off */
ret = af9013_power_ctrl ( state , 0 ) ;
if ( ret )
goto err ;
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
return ret ;
}
static int af9013_i2c_gate_ctrl ( struct dvb_frontend * fe , int enable )
{
int ret ;
struct af9013_state * state = fe - > demodulator_priv ;
dbg ( " %s: enable=%d " , __func__ , enable ) ;
/* gate already open or close */
if ( state - > i2c_gate_state = = enable )
return 0 ;
if ( state - > config . ts_mode = = AF9013_TS_USB )
ret = af9013_wr_reg_bits ( state , 0xd417 , 3 , 1 , enable ) ;
else
ret = af9013_wr_reg_bits ( state , 0xd607 , 2 , 1 , enable ) ;
if ( ret )
goto err ;
state - > i2c_gate_state = enable ;
return ret ;
err :
dbg ( " %s: failed=%d " , __func__ , ret ) ;
2008-09-15 22:01:52 +04:00
return ret ;
}
2011-11-29 03:58:11 +04:00
static void af9013_release ( struct dvb_frontend * fe )
{
struct af9013_state * state = fe - > demodulator_priv ;
kfree ( state ) ;
}
2008-09-15 22:01:52 +04:00
static struct dvb_frontend_ops af9013_ops ;
static int af9013_download_firmware ( struct af9013_state * state )
{
2011-03-20 00:02:22 +03:00
int i , len , remaining , ret ;
2008-09-15 22:01:52 +04:00
const struct firmware * fw ;
u16 checksum = 0 ;
u8 val ;
u8 fw_params [ 4 ] ;
u8 * fw_file = AF9013_DEFAULT_FIRMWARE ;
msleep ( 100 ) ;
/* check whether firmware is already running */
2011-11-29 03:58:11 +04:00
ret = af9013_rd_reg ( state , 0x98be , & val ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
else
2011-11-29 03:58:11 +04:00
dbg ( " %s: firmware status=%02x " , __func__ , val ) ;
2008-09-15 22:01:52 +04:00
if ( val = = 0x0c ) /* fw is running, no need for download */
goto exit ;
info ( " found a '%s' in cold state, will try to load a firmware " ,
af9013_ops . info . name ) ;
/* request the firmware, this will block and timeout */
2009-04-26 12:43:59 +04:00
ret = request_firmware ( & fw , fw_file , state - > i2c - > dev . parent ) ;
2008-09-15 22:01:52 +04:00
if ( ret ) {
err ( " did not find the firmware file. (%s) "
" Please see linux/Documentation/dvb/ for more details " \
" on firmware-problems. (%d) " ,
fw_file , ret ) ;
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
}
info ( " downloading firmware from file '%s' " , fw_file ) ;
/* calc checksum */
for ( i = 0 ; i < fw - > size ; i + + )
checksum + = fw - > data [ i ] ;
fw_params [ 0 ] = checksum > > 8 ;
fw_params [ 1 ] = checksum & 0xff ;
fw_params [ 2 ] = fw - > size > > 8 ;
fw_params [ 3 ] = fw - > size & 0xff ;
/* write fw checksum & size */
ret = af9013_write_ofsm_regs ( state , 0x50fc ,
fw_params , sizeof ( fw_params ) ) ;
if ( ret )
2011-11-29 03:58:11 +04:00
goto err_release ;
2008-09-15 22:01:52 +04:00
2011-03-20 00:02:22 +03:00
# define FW_ADDR 0x5100 /* firmware start address */
# define LEN_MAX 16 /* max packet size */
for ( remaining = fw - > size ; remaining > 0 ; remaining - = LEN_MAX ) {
len = remaining ;
if ( len > LEN_MAX )
len = LEN_MAX ;
2008-09-15 22:01:52 +04:00
2011-03-20 00:02:22 +03:00
ret = af9013_write_ofsm_regs ( state ,
FW_ADDR + fw - > size - remaining ,
( u8 * ) & fw - > data [ fw - > size - remaining ] , len ) ;
2008-09-15 22:01:52 +04:00
if ( ret ) {
2011-03-20 00:02:22 +03:00
err ( " firmware download failed:%d " , ret ) ;
2011-11-29 03:58:11 +04:00
goto err_release ;
2008-09-15 22:01:52 +04:00
}
}
/* request boot firmware */
2011-11-29 03:58:11 +04:00
ret = af9013_wr_reg ( state , 0xe205 , 1 ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err_release ;
2008-09-15 22:01:52 +04:00
for ( i = 0 ; i < 15 ; i + + ) {
msleep ( 100 ) ;
/* check firmware status */
2011-11-29 03:58:11 +04:00
ret = af9013_rd_reg ( state , 0x98be , & val ) ;
2008-09-15 22:01:52 +04:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err_release ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
dbg ( " %s: firmware status=%02x " , __func__ , val ) ;
2008-09-15 22:01:52 +04:00
if ( val = = 0x0c | | val = = 0x04 ) /* success or fail */
break ;
}
if ( val = = 0x04 ) {
err ( " firmware did not run " ) ;
2011-11-29 03:58:11 +04:00
ret = - ENODEV ;
2008-09-15 22:01:52 +04:00
} else if ( val ! = 0x0c ) {
err ( " firmware boot timeout " ) ;
2011-11-29 03:58:11 +04:00
ret = - ENODEV ;
2008-09-15 22:01:52 +04:00
}
2011-11-29 03:58:11 +04:00
err_release :
2008-09-15 22:01:52 +04:00
release_firmware ( fw ) ;
2011-11-29 03:58:11 +04:00
err :
2008-09-15 22:01:52 +04:00
exit :
if ( ! ret )
info ( " found a '%s' in warm state. " , af9013_ops . info . name ) ;
return ret ;
}
struct dvb_frontend * af9013_attach ( const struct af9013_config * config ,
struct i2c_adapter * i2c )
{
int ret ;
struct af9013_state * state = NULL ;
2010-06-18 04:16:12 +04:00
u8 buf [ 4 ] , i ;
2008-09-15 22:01:52 +04:00
/* allocate memory for the internal state */
state = kzalloc ( sizeof ( struct af9013_state ) , GFP_KERNEL ) ;
if ( state = = NULL )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
/* setup the state */
state - > i2c = i2c ;
memcpy ( & state - > config , config , sizeof ( struct af9013_config ) ) ;
/* download firmware */
2011-11-29 03:58:11 +04:00
if ( state - > config . ts_mode ! = AF9013_TS_USB ) {
2008-09-15 22:01:52 +04:00
ret = af9013_download_firmware ( state ) ;
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
}
/* firmware version */
2011-11-29 03:58:11 +04:00
ret = af9013_rd_regs ( state , 0x5103 , buf , 4 ) ;
2011-03-19 23:18:18 +03:00
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2011-03-19 23:18:18 +03:00
2011-11-29 03:58:11 +04:00
info ( " firmware version %d.%d.%d.%d " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] , buf [ 3 ] ) ;
2008-09-15 22:01:52 +04:00
/* set GPIOs */
for ( i = 0 ; i < sizeof ( state - > config . gpio ) ; i + + ) {
ret = af9013_set_gpio ( state , i , state - > config . gpio [ i ] ) ;
if ( ret )
2011-11-29 03:58:11 +04:00
goto err ;
2008-09-15 22:01:52 +04:00
}
/* create dvb_frontend */
2011-11-29 03:58:11 +04:00
memcpy ( & state - > fe . ops , & af9013_ops ,
2008-09-15 22:01:52 +04:00
sizeof ( struct dvb_frontend_ops ) ) ;
2011-11-29 03:58:11 +04:00
state - > fe . demodulator_priv = state ;
INIT_DELAYED_WORK ( & state - > statistics_work , af9013_statistics_work ) ;
2008-09-15 22:01:52 +04:00
2011-11-29 03:58:11 +04:00
return & state - > fe ;
err :
2008-09-15 22:01:52 +04:00
kfree ( state ) ;
return NULL ;
}
EXPORT_SYMBOL ( af9013_attach ) ;
static struct dvb_frontend_ops af9013_ops = {
2011-12-31 05:25:27 +04:00
. delsys = { SYS_DVBT } ,
2008-09-15 22:01:52 +04:00
. info = {
2011-11-29 03:58:11 +04:00
. name = " Afatech AF9013 " ,
2008-09-15 22:01:52 +04:00
. frequency_min = 174000000 ,
. frequency_max = 862000000 ,
. frequency_stepsize = 250000 ,
. frequency_tolerance = 0 ,
2011-11-29 03:58:11 +04:00
. caps = FE_CAN_FEC_1_2 |
FE_CAN_FEC_2_3 |
FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 |
FE_CAN_FEC_7_8 |
FE_CAN_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_QAM_16 |
FE_CAN_QAM_64 |
FE_CAN_QAM_AUTO |
2008-09-15 22:01:52 +04:00
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER |
FE_CAN_MUTE_TS
} ,
. release = af9013_release ,
2011-11-29 03:58:11 +04:00
2008-09-15 22:01:52 +04:00
. init = af9013_init ,
. sleep = af9013_sleep ,
2011-11-29 03:58:11 +04:00
. get_tune_settings = af9013_get_tune_settings ,
2011-12-31 05:25:27 +04:00
. set_frontend = af9013_set_frontend ,
. get_frontend = af9013_get_frontend ,
2008-09-15 22:01:52 +04:00
. read_status = af9013_read_status ,
. read_snr = af9013_read_snr ,
2011-11-29 03:58:11 +04:00
. read_signal_strength = af9013_read_signal_strength ,
. read_ber = af9013_read_ber ,
2008-09-15 22:01:52 +04:00
. read_ucblocks = af9013_read_ucblocks ,
2011-11-29 03:58:11 +04:00
. i2c_gate_ctrl = af9013_i2c_gate_ctrl ,
} ;
2008-09-15 22:01:52 +04:00
MODULE_AUTHOR ( " Antti Palosaari <crope@iki.fi> " ) ;
MODULE_DESCRIPTION ( " Afatech AF9013 DVB-T demodulator driver " ) ;
MODULE_LICENSE ( " GPL " ) ;