2005-07-07 17:58:29 -07:00
/*
2005-08-08 09:22:43 -07:00
* Support for LGDT3302 and LGDT3303 - VSB / QAM
2005-07-07 17:58:29 -07:00
*
* Copyright ( C ) 2005 Wilson Michaels < wilsonmichaels @ earthlink . net >
*
* 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 .
*
*/
/*
* NOTES ABOUT THIS DRIVER
*
2005-08-08 09:22:43 -07:00
* This Linux driver supports :
* DViCO FusionHDTV 3 Gold - Q
* DViCO FusionHDTV 3 Gold - T
* DViCO FusionHDTV 5 Gold
2005-11-08 21:35:12 -08:00
* DViCO FusionHDTV 5 Lite
2006-01-09 15:32:42 -02:00
* DViCO FusionHDTV 5 USB Gold
2005-11-08 21:35:32 -08:00
* Air2PC / AirStar 2 ATSC 3 rd generation ( HD5000 )
2006-04-10 09:40:40 -03:00
* pcHDTV HD5500
2005-07-07 17:58:29 -07:00
*
*/
2018-03-09 10:53:28 -05:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2005-07-07 17:58:29 -07:00
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
2005-10-30 15:03:48 -08:00
# include <linux/string.h>
# include <linux/slab.h>
2005-07-07 17:58:29 -07:00
# include <asm/byteorder.h>
2017-12-28 13:03:51 -05:00
# include <media/dvb_frontend.h>
# include <media/dvb_math.h>
2005-07-27 11:46:00 -07:00
# include "lgdt330x_priv.h"
# include "lgdt330x.h"
2005-07-07 17:58:29 -07:00
2006-10-29 13:35:39 -03:00
/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
/* #define USE_EQMSE */
2008-04-22 14:41:48 -03:00
static int debug ;
2005-07-07 17:58:29 -07:00
module_param ( debug , int , 0644 ) ;
2018-03-09 10:53:27 -05:00
MODULE_PARM_DESC ( debug , " Turn on/off lgdt330x frontend debugging (default:off). " ) ;
2018-03-09 10:53:28 -05:00
# define dprintk(fmt, arg...) do { \
if ( debug ) \
printk ( KERN_DEBUG pr_fmt ( " %s: " fmt ) , \
__func__ , # # arg ) ; \
2005-07-07 17:58:29 -07:00
} while ( 0 )
2018-03-09 10:53:27 -05:00
struct lgdt330x_state {
struct i2c_adapter * i2c ;
2005-07-07 17:58:29 -07:00
/* Configuration settings */
2018-03-09 10:53:27 -05:00
const struct lgdt330x_config * config ;
2005-07-07 17:58:29 -07:00
struct dvb_frontend frontend ;
/* Demodulator private data */
2015-06-07 14:53:52 -03:00
enum fe_modulation current_modulation ;
2006-10-29 13:35:39 -03:00
u32 snr ; /* Result of last SNR calculation */
2005-07-07 17:58:29 -07:00
/* Tuner private data */
u32 current_frequency ;
} ;
2018-03-09 10:53:27 -05:00
static int i2c_write_demod_bytes ( struct lgdt330x_state * state ,
u8 * buf , /* data bytes to send */
int len /* number of bytes to send */ )
2005-07-07 17:58:29 -07:00
{
2018-03-09 10:53:27 -05:00
struct i2c_msg msg = {
. addr = state - > config - > demod_address ,
. flags = 0 ,
. buf = buf ,
. len = 2
} ;
2005-07-27 11:45:54 -07:00
int i ;
2005-08-08 09:22:43 -07:00
int err ;
2005-07-07 17:58:29 -07:00
2018-03-09 10:53:27 -05:00
for ( i = 0 ; i < len - 1 ; i + = 2 ) {
err = i2c_transfer ( state - > i2c , & msg , 1 ) ;
if ( err ! = 1 ) {
2018-03-09 10:53:28 -05:00
pr_warn ( " %s: error (addr %02x <- %02x, err = %i) \n " ,
__func__ , msg . buf [ 0 ] , msg . buf [ 1 ] , err ) ;
2005-07-12 13:58:37 -07:00
if ( err < 0 )
return err ;
else
return - EREMOTEIO ;
2005-07-07 17:58:29 -07:00
}
2005-08-08 09:22:43 -07:00
msg . buf + = 2 ;
2005-07-07 17:58:29 -07:00
}
return 0 ;
}
/*
* This routine writes the register ( reg ) to the demod bus
* then reads the data returned for ( len ) bytes .
*/
2012-02-14 14:32:41 -03:00
static int i2c_read_demod_bytes ( struct lgdt330x_state * state ,
enum I2C_REG reg , u8 * buf , int len )
2005-07-07 17:58:29 -07:00
{
2018-03-09 10:53:27 -05:00
u8 wr [ ] = { reg } ;
struct i2c_msg msg [ ] = {
{
. addr = state - > config - > demod_address ,
. flags = 0 ,
. buf = wr ,
. len = 1
} , {
. addr = state - > config - > demod_address ,
. flags = I2C_M_RD ,
. buf = buf ,
. len = len
} ,
2005-07-07 17:58:29 -07:00
} ;
int ret ;
2018-03-09 10:53:27 -05:00
2005-07-07 17:58:29 -07:00
ret = i2c_transfer ( state - > i2c , msg , 2 ) ;
if ( ret ! = 2 ) {
2018-03-09 10:53:28 -05:00
pr_warn ( " %s: addr 0x%02x select 0x%02x error (ret == %i) \n " ,
__func__ , state - > config - > demod_address , reg , ret ) ;
2012-02-14 14:32:41 -03:00
if ( ret > = 0 )
ret = - EIO ;
2005-07-07 17:58:29 -07:00
} else {
ret = 0 ;
}
return ret ;
}
/* Software reset */
2018-03-09 10:53:27 -05:00
static int lgdt3302_sw_reset ( struct lgdt330x_state * state )
2005-07-07 17:58:29 -07:00
{
u8 ret ;
u8 reset [ ] = {
IRQ_MASK ,
2018-03-09 10:53:27 -05:00
/*
* bit 6 is active low software reset
* bits 5 - 0 are 1 to mask interrupts
*/
0x00
2005-07-07 17:58:29 -07:00
} ;
2005-08-08 09:22:43 -07:00
ret = i2c_write_demod_bytes ( state ,
2005-09-06 15:19:40 -07:00
reset , sizeof ( reset ) ) ;
2005-07-07 17:58:29 -07:00
if ( ret = = 0 ) {
2005-08-08 09:22:43 -07:00
/* force reset high (inactive) and unmask interrupts */
reset [ 1 ] = 0x7f ;
ret = i2c_write_demod_bytes ( state ,
2005-09-06 15:19:40 -07:00
reset , sizeof ( reset ) ) ;
2005-07-07 17:58:29 -07:00
}
return ret ;
}
2018-03-09 10:53:27 -05:00
static int lgdt3303_sw_reset ( struct lgdt330x_state * state )
2005-08-08 09:22:43 -07:00
{
u8 ret ;
u8 reset [ ] = {
0x02 ,
0x00 /* bit 0 is active low software reset */
} ;
ret = i2c_write_demod_bytes ( state ,
2005-09-06 15:19:40 -07:00
reset , sizeof ( reset ) ) ;
2005-08-08 09:22:43 -07:00
if ( ret = = 0 ) {
/* force reset high (inactive) */
reset [ 1 ] = 0x01 ;
ret = i2c_write_demod_bytes ( state ,
2005-09-06 15:19:40 -07:00
reset , sizeof ( reset ) ) ;
2005-08-08 09:22:43 -07:00
}
return ret ;
}
2018-03-09 10:53:27 -05:00
static int lgdt330x_sw_reset ( struct lgdt330x_state * state )
2005-08-08 09:22:43 -07:00
{
switch ( state - > config - > demod_chip ) {
case LGDT3302 :
2018-03-09 10:53:27 -05:00
return lgdt3302_sw_reset ( state ) ;
2005-08-08 09:22:43 -07:00
case LGDT3303 :
2018-03-09 10:53:27 -05:00
return lgdt3303_sw_reset ( state ) ;
2005-08-08 09:22:43 -07:00
default :
return - ENODEV ;
}
}
2018-03-09 10:53:27 -05:00
static int lgdt330x_init ( struct dvb_frontend * fe )
2005-07-07 17:58:29 -07:00
{
2018-03-09 10:53:27 -05:00
/*
* Hardware reset is done using gpio [ 0 ] of cx23880x chip .
2005-07-07 17:58:29 -07:00
* I ' d like to do it here , but don ' t know how to find chip address .
* cx88 - cards . c arranges for the reset bit to be inactive ( high ) .
* Maybe there needs to be a callable function in cx88 - core or
2018-03-09 10:53:27 -05:00
* the caller of this function needs to do it .
*/
2005-07-07 17:58:29 -07:00
2005-08-08 09:22:43 -07:00
/*
* Array of byte pairs < address , value >
* to initialize each different chip
*/
static u8 lgdt3302_init_data [ ] = {
2018-03-09 10:53:27 -05:00
/* Use 50MHz param values from spec sheet since xtal is 50 */
/*
* Change the value of NCOCTFV [ 25 : 0 ] of carrier
* recovery center frequency register
*/
2005-08-08 09:22:43 -07:00
VSB_CARRIER_FREQ0 , 0x00 ,
VSB_CARRIER_FREQ1 , 0x87 ,
VSB_CARRIER_FREQ2 , 0x8e ,
VSB_CARRIER_FREQ3 , 0x01 ,
2018-03-09 10:53:27 -05:00
/*
* Change the TPCLK pin polarity
* data is valid on falling clock
*/
2005-08-08 09:22:43 -07:00
DEMUX_CONTROL , 0xfb ,
2018-03-09 10:53:27 -05:00
/*
* Change the value of IFBW [ 11 : 0 ] of
* AGC IF / RF loop filter bandwidth register
*/
2005-08-08 09:22:43 -07:00
AGC_RF_BANDWIDTH0 , 0x40 ,
AGC_RF_BANDWIDTH1 , 0x93 ,
AGC_RF_BANDWIDTH2 , 0x00 ,
2018-03-09 10:53:27 -05:00
/*
* Change the value of bit 6 , ' nINAGCBY ' and
* ' NSSEL [ 1 : 0 ] of ACG function control register 2
*/
2005-08-08 09:22:43 -07:00
AGC_FUNC_CTRL2 , 0xc6 ,
2018-03-09 10:53:27 -05:00
/*
* Change the value of bit 6 ' RFFIX '
* of AGC function control register 3
*/
2005-08-08 09:22:43 -07:00
AGC_FUNC_CTRL3 , 0x40 ,
2018-03-09 10:53:27 -05:00
/*
* Set the value of ' INLVTHD ' register 0x2a / 0x2c
* to 0x7fe
*/
2005-08-08 09:22:43 -07:00
AGC_DELAY0 , 0x07 ,
AGC_DELAY2 , 0xfe ,
2018-03-09 10:53:27 -05:00
/*
* Change the value of IAGCBW [ 15 : 8 ]
* of inner AGC loop filter bandwidth
*/
2005-08-08 09:22:43 -07:00
AGC_LOOP_BANDWIDTH0 , 0x08 ,
AGC_LOOP_BANDWIDTH1 , 0x9a
} ;
static u8 lgdt3303_init_data [ ] = {
0x4c , 0x14
} ;
2008-06-28 02:06:50 -03:00
static u8 flip_1_lgdt3303_init_data [ ] = {
2005-11-08 21:35:32 -08:00
0x4c , 0x14 ,
0x87 , 0xf3
} ;
2008-06-28 02:06:50 -03:00
static u8 flip_2_lgdt3303_init_data [ ] = {
0x4c , 0x14 ,
0x87 , 0xda
} ;
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2005-08-08 09:22:43 -07:00
char * chip_name ;
int err ;
switch ( state - > config - > demod_chip ) {
case LGDT3302 :
chip_name = " LGDT3302 " ;
err = i2c_write_demod_bytes ( state , lgdt3302_init_data ,
2005-09-06 15:19:40 -07:00
sizeof ( lgdt3302_init_data ) ) ;
break ;
2005-08-08 09:22:43 -07:00
case LGDT3303 :
chip_name = " LGDT3303 " ;
2008-06-28 02:06:50 -03:00
switch ( state - > config - > clock_polarity_flip ) {
case 2 :
err = i2c_write_demod_bytes ( state ,
2018-03-09 10:53:27 -05:00
flip_2_lgdt3303_init_data ,
sizeof ( flip_2_lgdt3303_init_data ) ) ;
2008-06-28 02:06:50 -03:00
break ;
case 1 :
err = i2c_write_demod_bytes ( state ,
2018-03-09 10:53:27 -05:00
flip_1_lgdt3303_init_data ,
sizeof ( flip_1_lgdt3303_init_data ) ) ;
2008-06-28 02:06:50 -03:00
break ;
case 0 :
default :
2005-11-08 21:35:32 -08:00
err = i2c_write_demod_bytes ( state , lgdt3303_init_data ,
sizeof ( lgdt3303_init_data ) ) ;
}
2005-09-06 15:19:40 -07:00
break ;
2005-08-08 09:22:43 -07:00
default :
chip_name = " undefined " ;
2018-03-09 10:53:27 -05:00
printk ( KERN_WARNING " Only LGDT3302 and LGDT3303 are supported chips. \n " ) ;
2005-08-08 09:22:43 -07:00
err = - ENODEV ;
}
2018-03-09 10:53:29 -05:00
dprintk ( " Initialized the %s chip \n " , chip_name ) ;
2005-08-08 09:22:43 -07:00
if ( err < 0 )
return err ;
2018-03-09 10:53:27 -05:00
return lgdt330x_sw_reset ( state ) ;
2005-07-07 17:58:29 -07:00
}
2018-03-09 10:53:27 -05:00
static int lgdt330x_read_ber ( struct dvb_frontend * fe , u32 * ber )
2005-07-07 17:58:29 -07:00
{
2005-08-08 09:22:43 -07:00
* ber = 0 ; /* Not supplied by the demod chips */
2005-07-07 17:58:29 -07:00
return 0 ;
}
2018-03-09 10:53:27 -05:00
static int lgdt330x_read_ucblocks ( struct dvb_frontend * fe , u32 * ucblocks )
2005-07-07 17:58:29 -07:00
{
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2005-08-08 09:22:43 -07:00
int err ;
2005-07-07 17:58:29 -07:00
u8 buf [ 2 ] ;
2011-12-15 10:16:09 -03:00
* ucblocks = 0 ;
2005-08-08 09:22:43 -07:00
switch ( state - > config - > demod_chip ) {
case LGDT3302 :
err = i2c_read_demod_bytes ( state , LGDT3302_PACKET_ERR_COUNTER1 ,
2005-09-06 15:19:40 -07:00
buf , sizeof ( buf ) ) ;
break ;
2005-08-08 09:22:43 -07:00
case LGDT3303 :
err = i2c_read_demod_bytes ( state , LGDT3303_PACKET_ERR_COUNTER1 ,
2005-09-06 15:19:40 -07:00
buf , sizeof ( buf ) ) ;
break ;
2005-08-08 09:22:43 -07:00
default :
2018-03-09 10:53:27 -05:00
printk ( KERN_WARNING " Only LGDT3302 and LGDT3303 are supported chips. \n " ) ;
2005-08-08 09:22:43 -07:00
err = - ENODEV ;
}
2011-12-15 10:16:09 -03:00
if ( err < 0 )
return err ;
2005-07-07 17:58:29 -07:00
* ucblocks = ( buf [ 0 ] < < 8 ) | buf [ 1 ] ;
return 0 ;
}
2011-12-26 11:25:21 -03:00
static int lgdt330x_set_parameters ( struct dvb_frontend * fe )
2005-07-07 17:58:29 -07:00
{
2011-12-26 11:25:21 -03:00
struct dtv_frontend_properties * p = & fe - > dtv_property_cache ;
2005-08-08 09:22:43 -07:00
/*
* Array of byte pairs < address , value >
* to initialize 8 VSB for lgdt3303 chip 50 MHz IF
*/
static u8 lgdt3303_8vsb_44_data [ ] = {
0x04 , 0x00 ,
0x0d , 0x40 ,
2006-11-28 02:35:02 -03:00
0x0e , 0x87 ,
0x0f , 0x8e ,
0x10 , 0x01 ,
2018-03-09 10:53:27 -05:00
0x47 , 0x8b
} ;
2005-08-08 09:22:43 -07:00
/*
* Array of byte pairs < address , value >
* to initialize QAM for lgdt3303 chip
*/
static u8 lgdt3303_qam_data [ ] = {
0x04 , 0x00 ,
0x0d , 0x00 ,
0x0e , 0x00 ,
0x0f , 0x00 ,
0x10 , 0x00 ,
0x51 , 0x63 ,
0x47 , 0x66 ,
0x48 , 0x66 ,
0x4d , 0x1a ,
0x49 , 0x08 ,
2018-03-09 10:53:27 -05:00
0x4a , 0x9b
} ;
2005-08-08 09:22:43 -07:00
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2005-07-07 17:58:29 -07:00
static u8 top_ctrl_cfg [ ] = { TOP_CONTROL , 0x03 } ;
2011-12-15 10:30:38 -03:00
int err = 0 ;
2005-07-07 17:58:29 -07:00
/* Change only if we are actually changing the modulation */
2011-12-26 11:25:21 -03:00
if ( state - > current_modulation ! = p - > modulation ) {
switch ( p - > modulation ) {
2005-07-07 17:58:29 -07:00
case VSB_8 :
2018-03-09 10:53:28 -05:00
dprintk ( " VSB_8 MODE \n " ) ;
2005-07-07 17:58:29 -07:00
2005-08-08 09:22:43 -07:00
/* Select VSB mode */
top_ctrl_cfg [ 1 ] = 0x03 ;
2005-07-27 11:45:55 -07:00
/* Select ANT connector if supported by card */
if ( state - > config - > pll_rf_set )
state - > config - > pll_rf_set ( fe , 1 ) ;
2005-08-08 09:22:43 -07:00
if ( state - > config - > demod_chip = = LGDT3303 ) {
2018-03-09 10:53:27 -05:00
err = i2c_write_demod_bytes ( state ,
lgdt3303_8vsb_44_data ,
2005-09-06 15:19:40 -07:00
sizeof ( lgdt3303_8vsb_44_data ) ) ;
2005-08-08 09:22:43 -07:00
}
2005-07-07 17:58:29 -07:00
break ;
case QAM_64 :
2018-03-09 10:53:28 -05:00
dprintk ( " QAM_64 MODE \n " ) ;
2005-07-07 17:58:29 -07:00
2005-08-08 09:22:43 -07:00
/* Select QAM_64 mode */
top_ctrl_cfg [ 1 ] = 0x00 ;
2005-07-27 11:45:55 -07:00
/* Select CABLE connector if supported by card */
if ( state - > config - > pll_rf_set )
state - > config - > pll_rf_set ( fe , 0 ) ;
2005-08-08 09:22:43 -07:00
if ( state - > config - > demod_chip = = LGDT3303 ) {
2018-03-09 10:53:27 -05:00
err = i2c_write_demod_bytes ( state ,
lgdt3303_qam_data ,
sizeof ( lgdt3303_qam_data ) ) ;
2005-08-08 09:22:43 -07:00
}
2005-07-07 17:58:29 -07:00
break ;
case QAM_256 :
2018-03-09 10:53:28 -05:00
dprintk ( " QAM_256 MODE \n " ) ;
2005-07-07 17:58:29 -07:00
2005-08-08 09:22:43 -07:00
/* Select QAM_256 mode */
top_ctrl_cfg [ 1 ] = 0x01 ;
2005-07-27 11:45:55 -07:00
/* Select CABLE connector if supported by card */
if ( state - > config - > pll_rf_set )
state - > config - > pll_rf_set ( fe , 0 ) ;
2005-08-08 09:22:43 -07:00
if ( state - > config - > demod_chip = = LGDT3303 ) {
2018-03-09 10:53:27 -05:00
err = i2c_write_demod_bytes ( state ,
lgdt3303_qam_data ,
sizeof ( lgdt3303_qam_data ) ) ;
2005-08-08 09:22:43 -07:00
}
2005-07-07 17:58:29 -07:00
break ;
default :
2018-03-09 10:53:28 -05:00
pr_warn ( " %s: Modulation type(%d) UNSUPPORTED \n " ,
__func__ , p - > modulation ) ;
2005-07-07 17:58:29 -07:00
return - 1 ;
}
2011-12-15 10:30:38 -03:00
if ( err < 0 )
2018-03-09 10:53:28 -05:00
pr_warn ( " %s: error blasting bytes to lgdt3303 for modulation type(%d) \n " ,
__func__ , p - > modulation ) ;
2011-12-15 10:30:38 -03:00
2005-08-08 09:22:43 -07:00
/*
2018-03-09 10:53:27 -05:00
* select serial or parallel MPEG hardware interface
2005-08-08 09:22:43 -07:00
* Serial : 0x04 for LGDT3302 or 0x40 for LGDT3303
* Parallel : 0x00
*/
top_ctrl_cfg [ 1 ] | = state - > config - > serial_mpeg ;
2005-07-07 17:58:29 -07:00
/* Select the requested mode */
2005-08-08 09:22:43 -07:00
i2c_write_demod_bytes ( state , top_ctrl_cfg ,
2005-09-06 15:19:40 -07:00
sizeof ( top_ctrl_cfg ) ) ;
if ( state - > config - > set_ts_params )
state - > config - > set_ts_params ( fe , 0 ) ;
2011-12-26 11:25:21 -03:00
state - > current_modulation = p - > modulation ;
2005-07-07 17:58:29 -07:00
}
2005-09-06 15:19:40 -07:00
/* Tune to the specified frequency */
2006-05-14 05:01:31 -03:00
if ( fe - > ops . tuner_ops . set_params ) {
2011-12-24 12:24:33 -03:00
fe - > ops . tuner_ops . set_params ( fe ) ;
2018-03-09 10:53:27 -05:00
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
2006-04-18 17:47:11 -03:00
}
2005-09-06 15:19:40 -07:00
/* Keep track of the new frequency */
2018-03-09 10:53:27 -05:00
/*
* FIXME this is the wrong way to do this . . .
* The tuner is shared with the video4linux analog API
*/
2011-12-26 11:25:21 -03:00
state - > current_frequency = p - > frequency ;
2005-09-06 15:19:40 -07:00
2018-03-09 10:53:27 -05:00
lgdt330x_sw_reset ( state ) ;
2005-07-07 17:58:29 -07:00
return 0 ;
}
2016-02-04 12:58:30 -02:00
static int lgdt330x_get_frontend ( struct dvb_frontend * fe ,
struct dtv_frontend_properties * p )
2005-07-07 17:58:29 -07:00
{
2005-07-27 11:46:00 -07:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2016-02-04 12:58:30 -02:00
2011-12-26 11:25:21 -03:00
p - > frequency = state - > current_frequency ;
2005-07-07 17:58:29 -07:00
return 0 ;
}
2015-06-07 14:53:52 -03:00
static int lgdt3302_read_status ( struct dvb_frontend * fe ,
enum fe_status * status )
2005-07-07 17:58:29 -07:00
{
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2005-07-07 17:58:29 -07:00
u8 buf [ 3 ] ;
* status = 0 ; /* Reset status result */
2005-07-07 17:58:43 -07:00
/* AGC status register */
2005-08-08 09:22:43 -07:00
i2c_read_demod_bytes ( state , AGC_STATUS , buf , 1 ) ;
2018-03-09 10:53:28 -05:00
dprintk ( " AGC_STATUS = 0x%02x \n " , buf [ 0 ] ) ;
2018-03-09 10:53:27 -05:00
if ( ( buf [ 0 ] & 0x0c ) = = 0x8 ) {
/*
* Test signal does not exist flag
* as well as the AGC lock flag .
*/
2005-07-07 17:58:43 -07:00
* status | = FE_HAS_SIGNAL ;
}
2005-08-08 09:22:43 -07:00
/*
* You must set the Mask bits to 1 in the IRQ_MASK in order
* to see that status bit in the IRQ_STATUS register .
* This is done in SwReset ( ) ;
*/
2018-03-09 10:53:27 -05:00
2005-07-07 17:58:29 -07:00
/* signal status */
2005-08-08 09:22:43 -07:00
i2c_read_demod_bytes ( state , TOP_CONTROL , buf , sizeof ( buf ) ) ;
2018-03-09 10:53:28 -05:00
dprintk ( " TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x \n " ,
buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2005-07-07 17:58:29 -07:00
/* sync status */
2018-03-09 10:53:27 -05:00
if ( ( buf [ 2 ] & 0x03 ) = = 0x01 )
2005-07-07 17:58:29 -07:00
* status | = FE_HAS_SYNC ;
/* FEC error status */
if ( ( buf [ 2 ] & 0x0c ) = = 0x08 ) {
* status | = FE_HAS_LOCK ;
* status | = FE_HAS_VITERBI ;
}
/* Carrier Recovery Lock Status Register */
2005-08-08 09:22:43 -07:00
i2c_read_demod_bytes ( state , CARRIER_LOCK , buf , 1 ) ;
2018-03-09 10:53:28 -05:00
dprintk ( " CARRIER_LOCK = 0x%02x \n " , buf [ 0 ] ) ;
2005-07-07 17:58:29 -07:00
switch ( state - > current_modulation ) {
case QAM_256 :
case QAM_64 :
tree-wide: fix assorted typos all over the place
That is "success", "unknown", "through", "performance", "[re|un]mapping"
, "access", "default", "reasonable", "[con]currently", "temperature"
, "channel", "[un]used", "application", "example","hierarchy", "therefore"
, "[over|under]flow", "contiguous", "threshold", "enough" and others.
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2009-11-14 13:09:05 -02:00
/* Need to understand why there are 3 lock levels here */
2005-07-07 17:58:29 -07:00
if ( ( buf [ 0 ] & 0x07 ) = = 0x07 )
* status | = FE_HAS_CARRIER ;
break ;
case VSB_8 :
if ( ( buf [ 0 ] & 0x80 ) = = 0x80 )
* status | = FE_HAS_CARRIER ;
break ;
default :
2018-03-09 10:53:28 -05:00
pr_warn ( " %s: Modulation set to unsupported value \n " ,
__func__ ) ;
2005-07-07 17:58:29 -07:00
}
return 0 ;
}
2015-06-07 14:53:52 -03:00
static int lgdt3303_read_status ( struct dvb_frontend * fe ,
enum fe_status * status )
2005-08-08 09:22:43 -07:00
{
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2005-08-08 09:22:43 -07:00
int err ;
u8 buf [ 3 ] ;
* status = 0 ; /* Reset status result */
/* lgdt3303 AGC status register */
err = i2c_read_demod_bytes ( state , 0x58 , buf , 1 ) ;
if ( err < 0 )
return err ;
2018-03-09 10:53:28 -05:00
dprintk ( " AGC_STATUS = 0x%02x \n " , buf [ 0 ] ) ;
2018-03-09 10:53:27 -05:00
if ( ( buf [ 0 ] & 0x21 ) = = 0x01 ) {
/*
* Test input signal does not exist flag
* as well as the AGC lock flag .
*/
2005-08-08 09:22:43 -07:00
* status | = FE_HAS_SIGNAL ;
}
/* Carrier Recovery Lock Status Register */
i2c_read_demod_bytes ( state , CARRIER_LOCK , buf , 1 ) ;
2018-03-09 10:53:28 -05:00
dprintk ( " CARRIER_LOCK = 0x%02x \n " , buf [ 0 ] ) ;
2005-08-08 09:22:43 -07:00
switch ( state - > current_modulation ) {
case QAM_256 :
case QAM_64 :
tree-wide: fix assorted typos all over the place
That is "success", "unknown", "through", "performance", "[re|un]mapping"
, "access", "default", "reasonable", "[con]currently", "temperature"
, "channel", "[un]used", "application", "example","hierarchy", "therefore"
, "[over|under]flow", "contiguous", "threshold", "enough" and others.
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2009-11-14 13:09:05 -02:00
/* Need to understand why there are 3 lock levels here */
2005-08-08 09:22:43 -07:00
if ( ( buf [ 0 ] & 0x07 ) = = 0x07 )
* status | = FE_HAS_CARRIER ;
else
break ;
i2c_read_demod_bytes ( state , 0x8a , buf , 1 ) ;
if ( ( buf [ 0 ] & 0x04 ) = = 0x04 )
* status | = FE_HAS_SYNC ;
if ( ( buf [ 0 ] & 0x01 ) = = 0x01 )
* status | = FE_HAS_LOCK ;
if ( ( buf [ 0 ] & 0x08 ) = = 0x08 )
* status | = FE_HAS_VITERBI ;
break ;
case VSB_8 :
if ( ( buf [ 0 ] & 0x80 ) = = 0x80 )
* status | = FE_HAS_CARRIER ;
else
break ;
i2c_read_demod_bytes ( state , 0x38 , buf , 1 ) ;
if ( ( buf [ 0 ] & 0x02 ) = = 0x00 )
* status | = FE_HAS_SYNC ;
if ( ( buf [ 0 ] & 0x01 ) = = 0x01 ) {
* status | = FE_HAS_LOCK ;
* status | = FE_HAS_VITERBI ;
}
break ;
default :
2018-03-09 10:53:28 -05:00
pr_warn ( " %s: Modulation set to unsupported value \n " ,
__func__ ) ;
2005-08-08 09:22:43 -07:00
}
return 0 ;
}
2018-03-09 10:53:27 -05:00
/*
* Calculate SNR estimation ( scaled by 2 ^ 24 )
*
* 8 - VSB SNR equations from LGDT3302 and LGDT3303 datasheets , QAM
* equations from LGDT3303 datasheet . VSB is the same between the ' 02
* and ' 03 , so maybe QAM is too ? Perhaps someone with a newer datasheet
* that has QAM information could verify ?
*
* For 8 - VSB : ( two ways , take your pick )
* LGDT3302 :
* SNR_EQ = 10 * log10 ( 25 * 24 ^ 2 / EQ_MSE )
* LGDT3303 :
* SNR_EQ = 10 * log10 ( 25 * 32 ^ 2 / EQ_MSE )
* LGDT3302 & LGDT3303 :
* SNR_PT = 10 * log10 ( 25 * 32 ^ 2 / PT_MSE ) ( we use this one )
* For 64 - QAM :
* SNR = 10 * log10 ( 688128 / MSEQAM )
* For 256 - QAM :
* SNR = 10 * log10 ( 696320 / MSEQAM )
*
* We re - write the snr equation as :
* SNR * 2 ^ 24 = 10 * ( c - intlog10 ( MSE ) )
* Where for 256 - QAM , c = log10 ( 696320 ) * 2 ^ 24 , and so on .
*/
2006-10-29 13:35:39 -03:00
static u32 calculate_snr ( u32 mse , u32 c )
2005-07-07 17:58:29 -07:00
{
2006-10-29 13:35:39 -03:00
if ( mse = = 0 ) /* No signal */
return 0 ;
mse = intlog10 ( mse ) ;
if ( mse > c ) {
2018-03-09 10:53:27 -05:00
/*
* Negative SNR , which is possible , but realisticly the
* demod will lose lock before the signal gets this bad .
* The API only allows for unsigned values , so just return 0
*/
2006-10-29 13:35:39 -03:00
return 0 ;
}
2018-03-09 10:53:27 -05:00
return 10 * ( c - mse ) ;
2005-07-07 17:58:29 -07:00
}
2018-03-09 10:53:27 -05:00
static int lgdt3302_read_snr ( struct dvb_frontend * fe , u16 * snr )
2005-07-07 17:58:29 -07:00
{
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2006-10-29 13:35:39 -03:00
u8 buf [ 5 ] ; /* read data buffer */
u32 noise ; /* noise value */
u32 c ; /* per-modulation SNR calculation constant */
2005-07-07 17:58:29 -07:00
2018-03-09 10:53:27 -05:00
switch ( state - > current_modulation ) {
2006-10-29 13:35:39 -03:00
case VSB_8 :
i2c_read_demod_bytes ( state , LGDT3302_EQPH_ERR0 , buf , 5 ) ;
# ifdef USE_EQMSE
/* Use Equalizer Mean-Square Error Register */
/* SNR for ranges from -15.61 to +41.58 */
2005-07-07 17:58:29 -07:00
noise = ( ( buf [ 0 ] & 7 ) < < 16 ) | ( buf [ 1 ] < < 8 ) | buf [ 2 ] ;
2006-10-29 13:35:39 -03:00
c = 69765745 ; /* log10(25*24^2)*2^24 */
2005-07-07 17:58:29 -07:00
# else
2006-10-29 13:35:39 -03:00
/* Use Phase Tracker Mean-Square Error Register */
/* SNR for ranges from -13.11 to +44.08 */
2018-03-09 10:53:27 -05:00
noise = ( ( buf [ 0 ] & 7 < < 3 ) < < 13 ) | ( buf [ 3 ] < < 8 ) | buf [ 4 ] ;
2006-10-29 13:35:39 -03:00
c = 73957994 ; /* log10(25*32^2)*2^24 */
# endif
break ;
case QAM_64 :
case QAM_256 :
i2c_read_demod_bytes ( state , CARRIER_MSEQAM1 , buf , 2 ) ;
2005-08-08 09:22:43 -07:00
noise = ( ( buf [ 0 ] & 3 ) < < 8 ) | buf [ 1 ] ;
2006-10-29 13:35:39 -03:00
c = state - > current_modulation = = QAM_64 ? 97939837 : 98026066 ;
/* log10(688128)*2^24 and log10(696320)*2^24 */
break ;
default :
2018-03-09 10:53:28 -05:00
pr_err ( " %s: Modulation set to unsupported value \n " ,
2008-04-08 23:20:00 -03:00
__func__ ) ;
2006-10-29 13:35:39 -03:00
return - EREMOTEIO ; /* return -EDRIVER_IS_GIBBERED; */
2005-07-07 17:58:29 -07:00
}
2006-10-29 13:35:39 -03:00
state - > snr = calculate_snr ( noise , c ) ;
* snr = ( state - > snr ) > > 16 ; /* Convert from 8.24 fixed-point to 8.8 */
2005-07-07 17:58:29 -07:00
2018-03-09 10:53:28 -05:00
dprintk ( " noise = 0x%08x, snr = %d.%02d dB \n " , noise ,
2018-03-09 10:53:27 -05:00
state - > snr > > 24 , ( ( ( state - > snr > > 8 ) & 0xffff ) * 100 ) > > 16 ) ;
2005-07-07 17:58:29 -07:00
return 0 ;
}
2018-03-09 10:53:27 -05:00
static int lgdt3303_read_snr ( struct dvb_frontend * fe , u16 * snr )
2005-08-08 09:22:43 -07:00
{
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2006-10-29 13:35:39 -03:00
u8 buf [ 5 ] ; /* read data buffer */
u32 noise ; /* noise value */
u32 c ; /* per-modulation SNR calculation constant */
2005-08-08 09:22:43 -07:00
2018-03-09 10:53:27 -05:00
switch ( state - > current_modulation ) {
2006-10-29 13:35:39 -03:00
case VSB_8 :
i2c_read_demod_bytes ( state , LGDT3303_EQPH_ERR0 , buf , 5 ) ;
# ifdef USE_EQMSE
/* Use Equalizer Mean-Square Error Register */
/* SNR for ranges from -16.12 to +44.08 */
noise = ( ( buf [ 0 ] & 0x78 ) < < 13 ) | ( buf [ 1 ] < < 8 ) | buf [ 2 ] ;
c = 73957994 ; /* log10(25*32^2)*2^24 */
# else
/* Use Phase Tracker Mean-Square Error Register */
/* SNR for ranges from -13.11 to +44.08 */
2005-08-08 09:22:43 -07:00
noise = ( ( buf [ 0 ] & 7 ) < < 16 ) | ( buf [ 3 ] < < 8 ) | buf [ 4 ] ;
2006-10-29 13:35:39 -03:00
c = 73957994 ; /* log10(25*32^2)*2^24 */
# endif
break ;
case QAM_64 :
case QAM_256 :
i2c_read_demod_bytes ( state , CARRIER_MSEQAM1 , buf , 2 ) ;
2005-08-08 09:22:43 -07:00
noise = ( buf [ 0 ] < < 8 ) | buf [ 1 ] ;
2006-10-29 13:35:39 -03:00
c = state - > current_modulation = = QAM_64 ? 97939837 : 98026066 ;
/* log10(688128)*2^24 and log10(696320)*2^24 */
break ;
default :
2018-03-09 10:53:28 -05:00
pr_err ( " %s: Modulation set to unsupported value \n " ,
2008-04-08 23:20:00 -03:00
__func__ ) ;
2006-10-29 13:35:39 -03:00
return - EREMOTEIO ; /* return -EDRIVER_IS_GIBBERED; */
2005-08-08 09:22:43 -07:00
}
2006-10-29 13:35:39 -03:00
state - > snr = calculate_snr ( noise , c ) ;
* snr = ( state - > snr ) > > 16 ; /* Convert from 8.24 fixed-point to 8.8 */
2018-03-09 10:53:28 -05:00
dprintk ( " noise = 0x%08x, snr = %d.%02d dB \n " , noise ,
2006-10-29 13:35:39 -03:00
state - > snr > > 24 , ( ( ( state - > snr > > 8 ) & 0xffff ) * 100 ) > > 16 ) ;
return 0 ;
}
2018-03-09 10:53:27 -05:00
static int lgdt330x_read_signal_strength ( struct dvb_frontend * fe , u16 * strength )
2006-10-29 13:35:39 -03:00
{
/* Calculate Strength from SNR up to 35dB */
2018-03-09 10:53:27 -05:00
/*
* Even though the SNR can go higher than 35 dB , there is some comfort
* factor in having a range of strong signals that can show at 100 %
*/
struct lgdt330x_state * state = fe - > demodulator_priv ;
2006-10-29 13:35:39 -03:00
u16 snr ;
int ret ;
2005-08-08 09:22:43 -07:00
2006-10-29 13:35:39 -03:00
ret = fe - > ops . read_snr ( fe , & snr ) ;
if ( ret ! = 0 )
return ret ;
/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
/* scale the range 0 - 35*2^24 into 0 - 65535 */
if ( state - > snr > = 8960 * 0x10000 )
* strength = 0xffff ;
else
* strength = state - > snr / 8960 ;
2005-08-08 09:22:43 -07:00
return 0 ;
}
2018-03-09 10:53:27 -05:00
static int
lgdt330x_get_tune_settings ( struct dvb_frontend * fe ,
struct dvb_frontend_tune_settings * fe_tune_settings )
2005-07-07 17:58:29 -07:00
{
/* I have no idea about this - it may not be needed */
fe_tune_settings - > min_delay_ms = 500 ;
fe_tune_settings - > step_size = 0 ;
fe_tune_settings - > max_drift = 0 ;
return 0 ;
}
2018-03-09 10:53:27 -05:00
static void lgdt330x_release ( struct dvb_frontend * fe )
2005-07-07 17:58:29 -07:00
{
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = fe - > demodulator_priv ;
2005-07-07 17:58:29 -07:00
kfree ( state ) ;
}
2016-08-09 18:32:21 -03:00
static const struct dvb_frontend_ops lgdt3302_ops ;
static const struct dvb_frontend_ops lgdt3303_ops ;
2005-07-07 17:58:29 -07:00
2018-03-09 10:53:27 -05:00
struct dvb_frontend * lgdt330x_attach ( const struct lgdt330x_config * config ,
struct i2c_adapter * i2c )
2005-07-07 17:58:29 -07:00
{
2018-03-09 10:53:27 -05:00
struct lgdt330x_state * state = NULL ;
2005-07-07 17:58:29 -07:00
u8 buf [ 1 ] ;
/* Allocate memory for the internal state */
2018-03-09 10:53:27 -05:00
state = kzalloc ( sizeof ( * state ) , GFP_KERNEL ) ;
if ( ! state )
2005-07-07 17:58:29 -07:00
goto error ;
/* Setup the state */
state - > config = config ;
state - > i2c = i2c ;
2006-05-14 05:01:31 -03:00
/* Create dvb_frontend */
2005-08-08 09:22:43 -07:00
switch ( config - > demod_chip ) {
case LGDT3302 :
2018-03-09 10:53:27 -05:00
memcpy ( & state - > frontend . ops , & lgdt3302_ops ,
sizeof ( struct dvb_frontend_ops ) ) ;
2005-08-08 09:22:43 -07:00
break ;
case LGDT3303 :
2018-03-09 10:53:27 -05:00
memcpy ( & state - > frontend . ops , & lgdt3303_ops ,
sizeof ( struct dvb_frontend_ops ) ) ;
2005-08-08 09:22:43 -07:00
break ;
default :
goto error ;
}
2006-05-14 05:01:31 -03:00
state - > frontend . demodulator_priv = state ;
2005-08-08 09:22:43 -07:00
2005-07-07 17:58:29 -07:00
/* Verify communication with demod chip */
2005-08-08 09:22:43 -07:00
if ( i2c_read_demod_bytes ( state , 2 , buf , 1 ) )
2005-07-07 17:58:29 -07:00
goto error ;
state - > current_frequency = - 1 ;
state - > current_modulation = - 1 ;
2018-03-09 10:53:29 -05:00
pr_info ( " Demod loaded for LGDT330%s chip \n " ,
config - > demod_chip = = LGDT3302 ? " 2 " : " 3 " ) ;
2005-07-07 17:58:29 -07:00
return & state - > frontend ;
error :
2005-11-07 01:01:31 -08:00
kfree ( state ) ;
2018-03-09 10:53:28 -05:00
dprintk ( " ERROR \n " ) ;
2005-07-07 17:58:29 -07:00
return NULL ;
}
2018-03-09 10:53:27 -05:00
EXPORT_SYMBOL ( lgdt330x_attach ) ;
2005-07-07 17:58:29 -07:00
2016-08-09 18:32:21 -03:00
static const struct dvb_frontend_ops lgdt3302_ops = {
2011-12-26 11:25:21 -03:00
. delsys = { SYS_ATSC , SYS_DVBC_ANNEX_B } ,
2005-08-08 09:22:43 -07:00
. info = {
2018-03-09 10:53:27 -05:00
. name = " LG Electronics LGDT3302 VSB/QAM Frontend " ,
. frequency_min = 54000000 ,
. frequency_max = 858000000 ,
. frequency_stepsize = 62500 ,
2005-11-08 21:35:55 -08:00
. symbol_rate_min = 5056941 , /* QAM 64 */
. symbol_rate_max = 10762000 , /* VSB 8 */
2005-08-08 09:22:43 -07:00
. caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
} ,
. init = lgdt330x_init ,
2011-12-26 11:25:21 -03:00
. set_frontend = lgdt330x_set_parameters ,
. get_frontend = lgdt330x_get_frontend ,
2005-08-08 09:22:43 -07:00
. get_tune_settings = lgdt330x_get_tune_settings ,
. read_status = lgdt3302_read_status ,
. read_ber = lgdt330x_read_ber ,
. read_signal_strength = lgdt330x_read_signal_strength ,
. read_snr = lgdt3302_read_snr ,
. read_ucblocks = lgdt330x_read_ucblocks ,
. release = lgdt330x_release ,
} ;
2016-08-09 18:32:21 -03:00
static const struct dvb_frontend_ops lgdt3303_ops = {
2011-12-26 11:25:21 -03:00
. delsys = { SYS_ATSC , SYS_DVBC_ANNEX_B } ,
2005-07-07 17:58:29 -07:00
. info = {
2018-03-09 10:53:27 -05:00
. name = " LG Electronics LGDT3303 VSB/QAM Frontend " ,
. frequency_min = 54000000 ,
. frequency_max = 858000000 ,
. frequency_stepsize = 62500 ,
2005-11-08 21:35:55 -08:00
. symbol_rate_min = 5056941 , /* QAM 64 */
. symbol_rate_max = 10762000 , /* VSB 8 */
2005-07-07 17:58:29 -07:00
. caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
} ,
2005-07-27 11:46:00 -07:00
. init = lgdt330x_init ,
2011-12-26 11:25:21 -03:00
. set_frontend = lgdt330x_set_parameters ,
. get_frontend = lgdt330x_get_frontend ,
2005-07-27 11:46:00 -07:00
. get_tune_settings = lgdt330x_get_tune_settings ,
2005-08-08 09:22:43 -07:00
. read_status = lgdt3303_read_status ,
2005-07-27 11:46:00 -07:00
. read_ber = lgdt330x_read_ber ,
. read_signal_strength = lgdt330x_read_signal_strength ,
2005-08-08 09:22:43 -07:00
. read_snr = lgdt3303_read_snr ,
2005-07-27 11:46:00 -07:00
. read_ucblocks = lgdt330x_read_ucblocks ,
. release = lgdt330x_release ,
2005-07-07 17:58:29 -07:00
} ;
2005-08-08 09:22:43 -07:00
MODULE_DESCRIPTION ( " LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver " ) ;
2005-07-07 17:58:29 -07:00
MODULE_AUTHOR ( " Wilson Michaels " ) ;
MODULE_LICENSE ( " GPL " ) ;