2006-02-28 14:34:59 +03:00
/*
* Driver for Zarlink DVB - T ZL10353 demodulator
*
* Copyright ( C ) 2006 Christopher Pascoe < c . pascoe @ itee . uq . edu . au >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
*
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA . =
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/string.h>
# include <linux/slab.h>
# include "dvb_frontend.h"
# include "zl10353_priv.h"
# include "zl10353.h"
struct zl10353_state {
struct i2c_adapter * i2c ;
struct dvb_frontend frontend ;
struct zl10353_config config ;
} ;
2007-02-10 16:19:11 +03:00
static int debug ;
# define dprintk(args...) \
do { \
if ( debug ) printk ( KERN_DEBUG " zl10353: " args ) ; \
} while ( 0 )
2006-02-28 14:34:59 +03:00
static int debug_regs = 0 ;
static int zl10353_single_write ( struct dvb_frontend * fe , u8 reg , u8 val )
{
struct zl10353_state * state = fe - > demodulator_priv ;
u8 buf [ 2 ] = { reg , val } ;
struct i2c_msg msg = { . addr = state - > config . demod_address , . flags = 0 ,
. buf = buf , . len = 2 } ;
int err = i2c_transfer ( state - > i2c , & msg , 1 ) ;
if ( err ! = 1 ) {
printk ( " zl10353: write to reg %x failed (err = %d)! \n " , reg , err ) ;
return err ;
}
return 0 ;
}
2007-02-07 03:50:36 +03:00
static int zl10353_write ( struct dvb_frontend * fe , u8 * ibuf , int ilen )
2006-02-28 14:34:59 +03:00
{
int err , i ;
for ( i = 0 ; i < ilen - 1 ; i + + )
if ( ( err = zl10353_single_write ( fe , ibuf [ 0 ] + i , ibuf [ i + 1 ] ) ) )
return err ;
return 0 ;
}
static int zl10353_read_register ( struct zl10353_state * state , u8 reg )
{
int ret ;
u8 b0 [ 1 ] = { reg } ;
u8 b1 [ 1 ] = { 0 } ;
struct i2c_msg msg [ 2 ] = { { . addr = state - > config . demod_address ,
. flags = 0 ,
. buf = b0 , . len = 1 } ,
{ . addr = state - > config . demod_address ,
. flags = I2C_M_RD ,
. buf = b1 , . len = 1 } } ;
ret = i2c_transfer ( state - > i2c , msg , 2 ) ;
if ( ret ! = 2 ) {
printk ( " %s: readreg error (reg=%d, ret==%i) \n " ,
__FUNCTION__ , reg , ret ) ;
return ret ;
}
return b1 [ 0 ] ;
}
2006-03-15 22:17:11 +03:00
static void zl10353_dump_regs ( struct dvb_frontend * fe )
2006-02-28 14:34:59 +03:00
{
struct zl10353_state * state = fe - > demodulator_priv ;
char buf [ 52 ] , buf2 [ 4 ] ;
int ret ;
u8 reg ;
/* Dump all registers. */
for ( reg = 0 ; ; reg + + ) {
if ( reg % 16 = = 0 ) {
if ( reg )
printk ( KERN_DEBUG " %s \n " , buf ) ;
sprintf ( buf , " %02x: " , reg ) ;
}
ret = zl10353_read_register ( state , reg ) ;
if ( ret > = 0 )
sprintf ( buf2 , " %02x " , ( u8 ) ret ) ;
else
strcpy ( buf2 , " -- " ) ;
strcat ( buf , buf2 ) ;
if ( reg = = 0xff )
break ;
}
printk ( KERN_DEBUG " %s \n " , buf ) ;
}
2007-02-10 16:19:11 +03:00
static void zl10353_calc_nominal_rate ( struct dvb_frontend * fe ,
enum fe_bandwidth bandwidth ,
u16 * nominal_rate )
{
2007-11-19 09:47:07 +03:00
u32 adc_clock = 45056 ; /* 45.056 MHz */
2007-02-10 16:19:11 +03:00
u8 bw ;
struct zl10353_state * state = fe - > demodulator_priv ;
if ( state - > config . adc_clock )
adc_clock = state - > config . adc_clock ;
switch ( bandwidth ) {
case BANDWIDTH_6_MHZ :
bw = 6 ;
break ;
case BANDWIDTH_7_MHZ :
bw = 7 ;
break ;
case BANDWIDTH_8_MHZ :
default :
bw = 8 ;
break ;
}
2007-11-19 09:47:07 +03:00
* nominal_rate = ( bw * ( 1 < < 23 ) / 7 * 125 + adc_clock / 2 ) / adc_clock ;
2007-02-10 16:19:11 +03:00
dprintk ( " %s: bw %d, adc_clock %d => 0x%x \n " ,
__FUNCTION__ , bw , adc_clock , * nominal_rate ) ;
}
2006-02-28 14:34:59 +03:00
static int zl10353_sleep ( struct dvb_frontend * fe )
{
static u8 zl10353_softdown [ ] = { 0x50 , 0x0C , 0x44 } ;
zl10353_write ( fe , zl10353_softdown , sizeof ( zl10353_softdown ) ) ;
return 0 ;
}
static int zl10353_set_parameters ( struct dvb_frontend * fe ,
struct dvb_frontend_parameters * param )
{
2006-04-19 00:47:12 +04:00
struct zl10353_state * state = fe - > demodulator_priv ;
2007-02-10 16:19:11 +03:00
u16 nominal_rate ;
2006-02-28 14:34:59 +03:00
u8 pllbuf [ 6 ] = { 0x67 } ;
/* These settings set "auto-everything" and start the FSM. */
zl10353_single_write ( fe , 0x55 , 0x80 ) ;
udelay ( 200 ) ;
zl10353_single_write ( fe , 0xEA , 0x01 ) ;
udelay ( 200 ) ;
zl10353_single_write ( fe , 0xEA , 0x00 ) ;
zl10353_single_write ( fe , 0x56 , 0x28 ) ;
zl10353_single_write ( fe , 0x89 , 0x20 ) ;
zl10353_single_write ( fe , 0x5E , 0x00 ) ;
2007-02-10 16:19:11 +03:00
zl10353_calc_nominal_rate ( fe , param - > u . ofdm . bandwidth , & nominal_rate ) ;
zl10353_single_write ( fe , TRL_NOMINAL_RATE_1 , msb ( nominal_rate ) ) ;
zl10353_single_write ( fe , TRL_NOMINAL_RATE_0 , lsb ( nominal_rate ) ) ;
2006-08-10 10:17:42 +04:00
zl10353_single_write ( fe , 0x6C , 0xCD ) ;
zl10353_single_write ( fe , 0x6D , 0x7E ) ;
2007-02-10 16:19:08 +03:00
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
2006-02-28 14:34:59 +03:00
2007-11-19 09:32:06 +03:00
/*
* If there is no tuner attached to the secondary I2C bus , we call
* set_params to program a potential tuner attached somewhere else .
* Otherwise , we update the PLL registers via calc_regs .
*/
2006-04-19 00:47:12 +04:00
if ( state - > config . no_tuner ) {
2006-05-14 12:01:31 +04:00
if ( fe - > ops . tuner_ops . set_params ) {
fe - > ops . tuner_ops . set_params ( fe , param ) ;
2007-02-10 16:19:08 +03:00
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
2006-04-19 00:47:12 +04:00
}
2007-11-19 09:32:06 +03:00
} else if ( fe - > ops . tuner_ops . calc_regs ) {
fe - > ops . tuner_ops . calc_regs ( fe , param , pllbuf + 1 , 5 ) ;
2006-04-19 00:47:11 +04:00
pllbuf [ 1 ] < < = 1 ;
2007-11-19 09:32:06 +03:00
zl10353_write ( fe , pllbuf , sizeof ( pllbuf ) ) ;
2006-04-19 00:47:11 +04:00
}
2006-02-28 14:34:59 +03:00
2006-08-10 10:17:42 +04:00
zl10353_single_write ( fe , 0x5F , 0x13 ) ;
2007-11-19 09:32:06 +03:00
/* If no attached tuner or invalid PLL registers, just start the FSM. */
if ( state - > config . no_tuner | | fe - > ops . tuner_ops . calc_regs = = NULL )
zl10353_single_write ( fe , FSM_GO , 0x01 ) ;
else
zl10353_single_write ( fe , TUNER_GO , 0x01 ) ;
2006-02-28 14:34:59 +03:00
udelay ( 250 ) ;
zl10353_single_write ( fe , 0xE4 , 0x00 ) ;
zl10353_single_write ( fe , 0xE5 , 0x2A ) ;
zl10353_single_write ( fe , 0xE9 , 0x02 ) ;
zl10353_single_write ( fe , 0xE7 , 0x40 ) ;
zl10353_single_write ( fe , 0xE8 , 0x10 ) ;
return 0 ;
}
static int zl10353_read_status ( struct dvb_frontend * fe , fe_status_t * status )
{
struct zl10353_state * state = fe - > demodulator_priv ;
int s6 , s7 , s8 ;
if ( ( s6 = zl10353_read_register ( state , STATUS_6 ) ) < 0 )
return - EREMOTEIO ;
if ( ( s7 = zl10353_read_register ( state , STATUS_7 ) ) < 0 )
return - EREMOTEIO ;
if ( ( s8 = zl10353_read_register ( state , STATUS_8 ) ) < 0 )
return - EREMOTEIO ;
* status = 0 ;
if ( s6 & ( 1 < < 2 ) )
* status | = FE_HAS_CARRIER ;
if ( s6 & ( 1 < < 1 ) )
* status | = FE_HAS_VITERBI ;
if ( s6 & ( 1 < < 5 ) )
* status | = FE_HAS_LOCK ;
if ( s7 & ( 1 < < 4 ) )
* status | = FE_HAS_SYNC ;
if ( s8 & ( 1 < < 6 ) )
* status | = FE_HAS_SIGNAL ;
if ( ( * status & ( FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC ) ) ! =
( FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC ) )
* status & = ~ FE_HAS_LOCK ;
return 0 ;
}
2007-02-10 16:17:57 +03:00
static int zl10353_read_ber ( struct dvb_frontend * fe , u32 * ber )
{
struct zl10353_state * state = fe - > demodulator_priv ;
2007-02-10 16:19:16 +03:00
* ber = zl10353_read_register ( state , RS_ERR_CNT_2 ) < < 16 |
zl10353_read_register ( state , RS_ERR_CNT_1 ) < < 8 |
zl10353_read_register ( state , RS_ERR_CNT_0 ) ;
2007-02-10 16:17:57 +03:00
return 0 ;
}
static int zl10353_read_signal_strength ( struct dvb_frontend * fe , u16 * strength )
{
struct zl10353_state * state = fe - > demodulator_priv ;
2007-02-10 16:19:16 +03:00
u16 signal = zl10353_read_register ( state , AGC_GAIN_1 ) < < 10 |
zl10353_read_register ( state , AGC_GAIN_0 ) < < 2 | 3 ;
2007-02-10 16:17:57 +03:00
* strength = ~ signal ;
return 0 ;
}
2006-02-28 14:34:59 +03:00
static int zl10353_read_snr ( struct dvb_frontend * fe , u16 * snr )
{
struct zl10353_state * state = fe - > demodulator_priv ;
u8 _snr ;
if ( debug_regs )
zl10353_dump_regs ( fe ) ;
_snr = zl10353_read_register ( state , SNR ) ;
* snr = ( _snr < < 8 ) | _snr ;
return 0 ;
}
2007-02-10 16:17:57 +03:00
static int zl10353_read_ucblocks ( struct dvb_frontend * fe , u32 * ucblocks )
{
struct zl10353_state * state = fe - > demodulator_priv ;
2007-02-10 16:19:16 +03:00
* ucblocks = zl10353_read_register ( state , RS_UBC_1 ) < < 8 |
zl10353_read_register ( state , RS_UBC_0 ) ;
2007-02-10 16:17:57 +03:00
return 0 ;
}
2006-02-28 14:34:59 +03:00
static int zl10353_get_tune_settings ( struct dvb_frontend * fe ,
struct dvb_frontend_tune_settings
* fe_tune_settings )
{
fe_tune_settings - > min_delay_ms = 1000 ;
fe_tune_settings - > step_size = 0 ;
fe_tune_settings - > max_drift = 0 ;
return 0 ;
}
static int zl10353_init ( struct dvb_frontend * fe )
{
struct zl10353_state * state = fe - > demodulator_priv ;
u8 zl10353_reset_attach [ 6 ] = { 0x50 , 0x03 , 0x64 , 0x46 , 0x15 , 0x0F } ;
int rc = 0 ;
if ( debug_regs )
zl10353_dump_regs ( fe ) ;
2006-08-10 10:17:16 +04:00
if ( state - > config . parallel_ts )
zl10353_reset_attach [ 2 ] & = ~ 0x20 ;
2006-02-28 14:34:59 +03:00
/* Do a "hard" reset if not already done */
2006-08-10 10:17:16 +04:00
if ( zl10353_read_register ( state , 0x50 ) ! = zl10353_reset_attach [ 1 ] | |
zl10353_read_register ( state , 0x51 ) ! = zl10353_reset_attach [ 2 ] ) {
2006-02-28 14:34:59 +03:00
rc = zl10353_write ( fe , zl10353_reset_attach ,
sizeof ( zl10353_reset_attach ) ) ;
if ( debug_regs )
zl10353_dump_regs ( fe ) ;
}
return 0 ;
}
2007-02-10 16:19:08 +03:00
static int zl10353_i2c_gate_ctrl ( struct dvb_frontend * fe , int enable )
{
u8 val = 0x0a ;
if ( enable )
val | = 0x10 ;
return zl10353_single_write ( fe , 0x62 , val ) ;
}
2006-02-28 14:34:59 +03:00
static void zl10353_release ( struct dvb_frontend * fe )
{
struct zl10353_state * state = fe - > demodulator_priv ;
kfree ( state ) ;
}
static struct dvb_frontend_ops zl10353_ops ;
struct dvb_frontend * zl10353_attach ( const struct zl10353_config * config ,
struct i2c_adapter * i2c )
{
struct zl10353_state * state = NULL ;
/* allocate memory for the internal state */
state = kzalloc ( sizeof ( struct zl10353_state ) , GFP_KERNEL ) ;
if ( state = = NULL )
goto error ;
/* setup the state */
state - > i2c = i2c ;
memcpy ( & state - > config , config , sizeof ( struct zl10353_config ) ) ;
/* check if the demod is there */
if ( zl10353_read_register ( state , CHIP_ID ) ! = ID_ZL10353 )
goto error ;
/* create dvb_frontend */
2006-05-14 12:01:31 +04:00
memcpy ( & state - > frontend . ops , & zl10353_ops , sizeof ( struct dvb_frontend_ops ) ) ;
2006-02-28 14:34:59 +03:00
state - > frontend . demodulator_priv = state ;
return & state - > frontend ;
error :
kfree ( state ) ;
return NULL ;
}
static struct dvb_frontend_ops zl10353_ops = {
. info = {
. name = " Zarlink ZL10353 DVB-T " ,
. type = FE_OFDM ,
. frequency_min = 174000000 ,
. frequency_max = 862000000 ,
. frequency_stepsize = 166667 ,
. frequency_tolerance = 0 ,
. 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 |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
FE_CAN_MUTE_TS
} ,
. release = zl10353_release ,
. init = zl10353_init ,
. sleep = zl10353_sleep ,
2007-02-10 16:19:08 +03:00
. i2c_gate_ctrl = zl10353_i2c_gate_ctrl ,
2006-08-08 16:10:08 +04:00
. write = zl10353_write ,
2006-02-28 14:34:59 +03:00
. set_frontend = zl10353_set_parameters ,
. get_tune_settings = zl10353_get_tune_settings ,
. read_status = zl10353_read_status ,
2007-02-10 16:17:57 +03:00
. read_ber = zl10353_read_ber ,
. read_signal_strength = zl10353_read_signal_strength ,
2006-02-28 14:34:59 +03:00
. read_snr = zl10353_read_snr ,
2007-02-10 16:17:57 +03:00
. read_ucblocks = zl10353_read_ucblocks ,
2006-02-28 14:34:59 +03:00
} ;
2007-02-10 16:19:11 +03:00
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " Turn on/off frontend debugging (default:off). " ) ;
2006-02-28 14:34:59 +03:00
module_param ( debug_regs , int , 0644 ) ;
MODULE_PARM_DESC ( debug_regs , " Turn on/off frontend register dumps (default:off). " ) ;
MODULE_DESCRIPTION ( " Zarlink ZL10353 DVB-T demodulator driver " ) ;
MODULE_AUTHOR ( " Chris Pascoe " ) ;
MODULE_LICENSE ( " GPL " ) ;
EXPORT_SYMBOL ( zl10353_attach ) ;