2005-04-16 15:20:36 -07:00
/*
2005-05-16 21:54:41 -07:00
Frontend / Card driver for TwinHan DST Frontend
Copyright ( C ) 2003 Jamie Honan
Copyright ( C ) 2004 , 2005 Manu Abraham ( manu @ kromtek . com )
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
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 .
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
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 .
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
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 .
2005-04-16 15:20:36 -07:00
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/string.h>
# include <linux/slab.h>
# include <linux/vmalloc.h>
# include <linux/delay.h>
# include <asm/div64.h>
# include "dvb_frontend.h"
# include "dst_priv.h"
2005-05-16 21:54:41 -07:00
# include "dst_common.h"
static unsigned int verbose = 1 ;
module_param ( verbose , int , 0644 ) ;
MODULE_PARM_DESC ( verbose , " verbose startup messages, default is 1 (yes) " ) ;
static unsigned int dst_addons ;
module_param ( dst_addons , int , 0644 ) ;
2005-05-16 21:54:45 -07:00
MODULE_PARM_DESC ( dst_addons , " CA daughterboard, default is 0 (No addons) " ) ;
2005-04-16 15:20:36 -07:00
2005-09-09 13:03:00 -07:00
# define HAS_LOCK 1
# define ATTEMPT_TUNE 2
# define HAS_POWER 4
# define DST_ERROR 0
# define DST_NOTICE 1
# define DST_INFO 2
# define DST_DEBUG 3
# define dprintk(x, y, z, format, arg...) do { \
if ( z ) { \
if ( ( x > DST_ERROR ) & & ( x > y ) ) \
printk ( KERN_ERR " %s: " format " \n " , __FUNCTION__ , # # arg ) ; \
else if ( ( x > DST_NOTICE ) & & ( x > y ) ) \
printk ( KERN_NOTICE " %s: " format " \n " , __FUNCTION__ , # # arg ) ; \
else if ( ( x > DST_INFO ) & & ( x > y ) ) \
printk ( KERN_INFO " %s: " format " \n " , __FUNCTION__ , # # arg ) ; \
else if ( ( x > DST_DEBUG ) & & ( x > y ) ) \
printk ( KERN_DEBUG " %s: " format " \n " , __FUNCTION__ , # # arg ) ; \
} else { \
if ( x > y ) \
printk ( format , # # arg ) ; \
} \
} while ( 0 )
static void dst_packsize ( struct dst_state * state , int psize )
2005-04-16 15:20:36 -07:00
{
union dst_gpio_packet bits ;
bits . psize = psize ;
bt878_device_control ( state - > bt , DST_IG_TS , & bits ) ;
}
2005-09-09 13:03:00 -07:00
int dst_gpio_outb ( struct dst_state * state , u32 mask , u32 enbb , u32 outhigh , int delay )
2005-04-16 15:20:36 -07:00
{
union dst_gpio_packet enb ;
union dst_gpio_packet bits ;
int err ;
enb . enb . mask = mask ;
enb . enb . enable = enbb ;
2005-05-16 21:54:41 -07:00
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " mask=[%04x], enbb=[%04x], outhigh=[%04x] " , mask , enbb , outhigh ) ;
2005-04-16 15:20:36 -07:00
if ( ( err = bt878_device_control ( state - > bt , DST_IG_ENABLE , & enb ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " dst_gpio_enb error (err == %i, mask == %02x, enb == %02x) " , err , mask , enbb ) ;
2005-04-16 15:20:36 -07:00
return - EREMOTEIO ;
}
2005-05-16 21:54:43 -07:00
udelay ( 1000 ) ;
2005-04-16 15:20:36 -07:00
/* because complete disabling means no output, no need to do output packet */
if ( enbb = = 0 )
return 0 ;
2005-05-16 21:54:41 -07:00
if ( delay )
msleep ( 10 ) ;
2005-04-16 15:20:36 -07:00
bits . outp . mask = enbb ;
bits . outp . highvals = outhigh ;
if ( ( err = bt878_device_control ( state - > bt , DST_IG_WRITE , & bits ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x) " , err , enbb , outhigh ) ;
2005-04-16 15:20:36 -07:00
return - EREMOTEIO ;
}
2005-09-09 13:03:00 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( dst_gpio_outb ) ;
2005-04-16 15:20:36 -07:00
2005-09-09 13:03:00 -07:00
int dst_gpio_inb ( struct dst_state * state , u8 * result )
2005-04-16 15:20:36 -07:00
{
union dst_gpio_packet rd_packet ;
int err ;
* result = 0 ;
if ( ( err = bt878_device_control ( state - > bt , DST_IG_READ , & rd_packet ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " dst_gpio_inb error (err == %i) \n " , err ) ;
2005-04-16 15:20:36 -07:00
return - EREMOTEIO ;
}
* result = ( u8 ) rd_packet . rd . value ;
2005-09-09 13:03:00 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( dst_gpio_inb ) ;
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
int rdc_reset_state ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " Resetting state machine " ) ;
2005-05-16 21:54:41 -07:00
if ( dst_gpio_outb ( state , RDC_8820_INT , RDC_8820_INT , 0 , NO_DELAY ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " dst_gpio_outb ERROR ! " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-04-16 15:20:36 -07:00
msleep ( 10 ) ;
2005-05-16 21:54:41 -07:00
if ( dst_gpio_outb ( state , RDC_8820_INT , RDC_8820_INT , RDC_8820_INT , NO_DELAY ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " dst_gpio_outb ERROR ! " ) ;
2005-05-16 21:54:41 -07:00
msleep ( 10 ) ;
return - 1 ;
}
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( rdc_reset_state ) ;
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
int rdc_8820_reset ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " Resetting DST " ) ;
2005-05-16 21:54:41 -07:00
if ( dst_gpio_outb ( state , RDC_8820_RESET , RDC_8820_RESET , 0 , NO_DELAY ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " dst_gpio_outb ERROR ! " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-05-16 21:54:43 -07:00
udelay ( 1000 ) ;
2005-05-16 21:54:41 -07:00
if ( dst_gpio_outb ( state , RDC_8820_RESET , RDC_8820_RESET , RDC_8820_RESET , DELAY ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " dst_gpio_outb ERROR ! " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( rdc_8820_reset ) ;
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
int dst_pio_enable ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:41 -07:00
if ( dst_gpio_outb ( state , ~ 0 , RDC_8820_PIO_0_ENABLE , 0 , NO_DELAY ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " dst_gpio_outb ERROR ! " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-05-16 21:54:43 -07:00
udelay ( 1000 ) ;
2005-09-09 13:03:00 -07:00
2005-05-16 21:54:41 -07:00
return 0 ;
}
EXPORT_SYMBOL ( dst_pio_enable ) ;
int dst_pio_disable ( struct dst_state * state )
{
if ( dst_gpio_outb ( state , ~ 0 , RDC_8820_PIO_0_DISABLE , RDC_8820_PIO_0_DISABLE , NO_DELAY ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " dst_gpio_outb ERROR ! " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-05-16 21:54:43 -07:00
if ( state - > type_flags & DST_TYPE_HAS_FW_1 )
udelay ( 1000 ) ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( dst_pio_disable ) ;
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
int dst_wait_dst_ready ( struct dst_state * state , u8 delay_mode )
2005-04-16 15:20:36 -07:00
{
u8 reply ;
int i ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < 200 ; i + + ) {
2005-05-16 21:54:41 -07:00
if ( dst_gpio_inb ( state , & reply ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " dst_gpio_inb ERROR ! " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
if ( ( reply & RDC_8820_PIO_0_ENABLE ) = = 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " dst wait ready after %d " , i ) ;
2005-04-16 15:20:36 -07:00
return 1 ;
}
2005-05-16 21:54:44 -07:00
msleep ( 10 ) ;
2005-05-16 21:54:41 -07:00
}
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_NOTICE , 1 , " dst wait NOT ready after %d " , i ) ;
2005-05-16 21:54:41 -07:00
return 0 ;
}
EXPORT_SYMBOL ( dst_wait_dst_ready ) ;
int dst_error_recovery ( struct dst_state * state )
{
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_NOTICE , 1 , " Trying to return from previous errors. " ) ;
2005-05-16 21:54:41 -07:00
dst_pio_disable ( state ) ;
msleep ( 10 ) ;
dst_pio_enable ( state ) ;
msleep ( 10 ) ;
return 0 ;
}
EXPORT_SYMBOL ( dst_error_recovery ) ;
int dst_error_bailout ( struct dst_state * state )
{
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " Trying to bailout from previous error. " ) ;
2005-05-16 21:54:41 -07:00
rdc_8820_reset ( state ) ;
dst_pio_disable ( state ) ;
msleep ( 10 ) ;
return 0 ;
}
EXPORT_SYMBOL ( dst_error_bailout ) ;
2005-09-09 13:03:00 -07:00
int dst_comm_init ( struct dst_state * state )
2005-05-16 21:54:41 -07:00
{
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " Initializing DST. " ) ;
2005-05-16 21:54:41 -07:00
if ( ( dst_pio_enable ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " PIO Enable Failed " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
if ( ( rdc_reset_state ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " RDC 8820 State RESET Failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:43 -07:00
if ( state - > type_flags & DST_TYPE_HAS_FW_1 )
msleep ( 100 ) ;
else
msleep ( 5 ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( dst_comm_init ) ;
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
int write_dst ( struct dst_state * state , u8 * data , u8 len )
2005-04-16 15:20:36 -07:00
{
struct i2c_msg msg = {
2005-09-09 13:03:00 -07:00
. addr = state - > config - > demod_address ,
. flags = 0 ,
. buf = data ,
. len = len
2005-04-16 15:20:36 -07:00
} ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
int err ;
2005-09-09 13:03:00 -07:00
u8 cnt , i ;
dprintk ( verbose , DST_NOTICE , 0 , " writing [ " ) ;
for ( i = 0 ; i < len ; i + + )
dprintk ( verbose , DST_NOTICE , 0 , " %02x " , data [ i ] ) ;
dprintk ( verbose , DST_NOTICE , 0 , " ] \n " ) ;
2005-05-16 21:54:41 -07:00
for ( cnt = 0 ; cnt < 2 ; cnt + + ) {
2005-04-16 15:20:36 -07:00
if ( ( err = i2c_transfer ( state - > i2c , & msg , 1 ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " _write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x) " , err , len , data [ 0 ] ) ;
2005-05-16 21:54:41 -07:00
dst_error_recovery ( state ) ;
2005-04-16 15:20:36 -07:00
continue ;
} else
break ;
}
2005-05-16 21:54:41 -07:00
if ( cnt > = 2 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " RDC 8820 RESET " ) ;
2005-05-16 21:54:41 -07:00
dst_error_bailout ( state ) ;
return - 1 ;
}
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( write_dst ) ;
2005-04-16 15:20:36 -07:00
2005-09-09 13:03:00 -07:00
int read_dst ( struct dst_state * state , u8 * ret , u8 len )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct i2c_msg msg = {
. addr = state - > config - > demod_address ,
. flags = I2C_M_RD ,
. buf = ret ,
. len = len
} ;
2005-04-16 15:20:36 -07:00
int err ;
int cnt ;
2005-05-16 21:54:41 -07:00
for ( cnt = 0 ; cnt < 2 ; cnt + + ) {
2005-04-16 15:20:36 -07:00
if ( ( err = i2c_transfer ( state - > i2c , & msg , 1 ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x) " , err , len , ret [ 0 ] ) ;
2005-05-16 21:54:41 -07:00
dst_error_recovery ( state ) ;
2005-04-16 15:20:36 -07:00
continue ;
} else
break ;
}
2005-05-16 21:54:41 -07:00
if ( cnt > = 2 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " RDC 8820 RESET " ) ;
2005-05-16 21:54:41 -07:00
dst_error_bailout ( state ) ;
return - 1 ;
}
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " reply is 0x%x " , ret [ 0 ] ) ;
for ( err = 1 ; err < len ; err + + )
dprintk ( verbose , DST_DEBUG , 0 , " 0x%x " , ret [ err ] ) ;
if ( err > 1 )
dprintk ( verbose , DST_DEBUG , 0 , " \n " ) ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( read_dst ) ;
2005-04-16 15:20:36 -07:00
2005-07-07 17:57:50 -07:00
static int dst_set_polarization ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
2005-07-07 17:57:50 -07:00
switch ( state - > voltage ) {
2005-09-09 13:03:00 -07:00
case SEC_VOLTAGE_13 : /* Vertical */
dprintk ( verbose , DST_INFO , 1 , " Polarization=[Vertical] " ) ;
state - > tx_tuna [ 8 ] & = ~ 0x40 ;
break ;
case SEC_VOLTAGE_18 : /* Horizontal */
dprintk ( verbose , DST_INFO , 1 , " Polarization=[Horizontal] " ) ;
state - > tx_tuna [ 8 ] | = 0x40 ;
break ;
case SEC_VOLTAGE_OFF :
break ;
2005-07-07 17:57:50 -07:00
}
return 0 ;
}
static int dst_set_freq ( struct dst_state * state , u32 freq )
{
2005-04-16 15:20:36 -07:00
state - > frequency = freq ;
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " set Frequency %u " , freq ) ;
2005-04-16 15:20:36 -07:00
if ( state - > dst_type = = DST_TYPE_IS_SAT ) {
freq = freq / 1000 ;
if ( freq < 950 | | freq > 2150 )
return - EINVAL ;
2005-07-07 17:57:50 -07:00
state - > tx_tuna [ 2 ] = ( freq > > 8 ) ;
state - > tx_tuna [ 3 ] = ( u8 ) freq ;
state - > tx_tuna [ 4 ] = 0x01 ;
state - > tx_tuna [ 8 ] & = ~ 0x04 ;
if ( state - > type_flags & DST_TYPE_HAS_OBS_REGS ) {
if ( freq < 1531 )
state - > tx_tuna [ 8 ] | = 0x04 ;
}
2005-04-16 15:20:36 -07:00
} else if ( state - > dst_type = = DST_TYPE_IS_TERR ) {
freq = freq / 1000 ;
if ( freq < 137000 | | freq > 858000 )
return - EINVAL ;
2005-07-07 17:57:50 -07:00
state - > tx_tuna [ 2 ] = ( freq > > 16 ) & 0xff ;
state - > tx_tuna [ 3 ] = ( freq > > 8 ) & 0xff ;
state - > tx_tuna [ 4 ] = ( u8 ) freq ;
2005-04-16 15:20:36 -07:00
} else if ( state - > dst_type = = DST_TYPE_IS_CABLE ) {
2005-09-09 13:03:02 -07:00
freq = freq / 1000 ;
2005-07-07 17:57:50 -07:00
state - > tx_tuna [ 2 ] = ( freq > > 16 ) & 0xff ;
state - > tx_tuna [ 3 ] = ( freq > > 8 ) & 0xff ;
state - > tx_tuna [ 4 ] = ( u8 ) freq ;
2005-04-16 15:20:36 -07:00
} else
return - EINVAL ;
2005-09-09 13:03:00 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_set_bandwidth ( struct dst_state * state , fe_bandwidth_t bandwidth )
2005-04-16 15:20:36 -07:00
{
state - > bandwidth = bandwidth ;
if ( state - > dst_type ! = DST_TYPE_IS_TERR )
return 0 ;
switch ( bandwidth ) {
2005-09-09 13:03:00 -07:00
case BANDWIDTH_6_MHZ :
if ( state - > dst_hw_cap & DST_TYPE_HAS_CA )
state - > tx_tuna [ 7 ] = 0x06 ;
else {
state - > tx_tuna [ 6 ] = 0x06 ;
state - > tx_tuna [ 7 ] = 0x00 ;
}
break ;
case BANDWIDTH_7_MHZ :
if ( state - > dst_hw_cap & DST_TYPE_HAS_CA )
state - > tx_tuna [ 7 ] = 0x07 ;
else {
state - > tx_tuna [ 6 ] = 0x07 ;
state - > tx_tuna [ 7 ] = 0x00 ;
}
break ;
case BANDWIDTH_8_MHZ :
if ( state - > dst_hw_cap & DST_TYPE_HAS_CA )
state - > tx_tuna [ 7 ] = 0x08 ;
else {
state - > tx_tuna [ 6 ] = 0x08 ;
state - > tx_tuna [ 7 ] = 0x00 ;
}
break ;
default :
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2005-09-09 13:03:00 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_set_inversion ( struct dst_state * state , fe_spectral_inversion_t inversion )
2005-04-16 15:20:36 -07:00
{
state - > inversion = inversion ;
switch ( inversion ) {
2005-09-09 13:03:00 -07:00
case INVERSION_OFF : /* Inversion = Normal */
state - > tx_tuna [ 8 ] & = ~ 0x80 ;
break ;
case INVERSION_ON :
state - > tx_tuna [ 8 ] | = 0x80 ;
break ;
default :
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2005-09-09 13:03:00 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_set_fec ( struct dst_state * state , fe_code_rate_t fec )
2005-04-16 15:20:36 -07:00
{
state - > fec = fec ;
return 0 ;
}
2005-09-09 13:03:00 -07:00
static fe_code_rate_t dst_get_fec ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
return state - > fec ;
}
2005-09-09 13:03:00 -07:00
static int dst_set_symbolrate ( struct dst_state * state , u32 srate )
2005-04-16 15:20:36 -07:00
{
u32 symcalc ;
u64 sval ;
state - > symbol_rate = srate ;
if ( state - > dst_type = = DST_TYPE_IS_TERR ) {
return 0 ;
}
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " set symrate %u " , srate ) ;
2005-04-16 15:20:36 -07:00
srate / = 1000 ;
if ( state - > type_flags & DST_TYPE_HAS_SYMDIV ) {
sval = srate ;
sval < < = 20 ;
do_div ( sval , 88000 ) ;
symcalc = ( u32 ) sval ;
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " set symcalc %u " , symcalc ) ;
2005-09-09 13:02:58 -07:00
state - > tx_tuna [ 5 ] = ( u8 ) ( symcalc > > 12 ) ;
state - > tx_tuna [ 6 ] = ( u8 ) ( symcalc > > 4 ) ;
state - > tx_tuna [ 7 ] = ( u8 ) ( symcalc < < 4 ) ;
2005-04-16 15:20:36 -07:00
} else {
2005-09-09 13:02:58 -07:00
state - > tx_tuna [ 5 ] = ( u8 ) ( srate > > 16 ) & 0x7f ;
state - > tx_tuna [ 6 ] = ( u8 ) ( srate > > 8 ) ;
state - > tx_tuna [ 7 ] = ( u8 ) srate ;
}
state - > tx_tuna [ 8 ] & = ~ 0x20 ;
if ( state - > type_flags & DST_TYPE_HAS_OBS_REGS ) {
if ( srate > 8000 )
state - > tx_tuna [ 8 ] | = 0x20 ;
2005-04-16 15:20:36 -07:00
}
return 0 ;
}
2005-07-07 17:57:50 -07:00
static int dst_set_modulation ( struct dst_state * state , fe_modulation_t modulation )
{
if ( state - > dst_type ! = DST_TYPE_IS_CABLE )
return 0 ;
state - > modulation = modulation ;
switch ( modulation ) {
2005-09-09 13:03:00 -07:00
case QAM_16 :
state - > tx_tuna [ 8 ] = 0x10 ;
break ;
case QAM_32 :
state - > tx_tuna [ 8 ] = 0x20 ;
break ;
case QAM_64 :
state - > tx_tuna [ 8 ] = 0x40 ;
break ;
case QAM_128 :
state - > tx_tuna [ 8 ] = 0x80 ;
break ;
case QAM_256 :
state - > tx_tuna [ 8 ] = 0x00 ;
break ;
case QPSK :
case QAM_AUTO :
case VSB_8 :
case VSB_16 :
default :
return - EINVAL ;
2005-07-07 17:57:50 -07:00
}
return 0 ;
}
static fe_modulation_t dst_get_modulation ( struct dst_state * state )
{
return state - > modulation ;
}
2005-09-09 13:03:00 -07:00
u8 dst_check_sum ( u8 * buf , u32 len )
2005-04-16 15:20:36 -07:00
{
u32 i ;
u8 val = 0 ;
if ( ! len )
return 0 ;
for ( i = 0 ; i < len ; i + + ) {
val + = buf [ i ] ;
}
return ( ( ~ val ) + 1 ) ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( dst_check_sum ) ;
2005-04-16 15:20:36 -07:00
static void dst_type_flags_print ( u32 type_flags )
{
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 0 , " DST type flags : " ) ;
2005-04-16 15:20:36 -07:00
if ( type_flags & DST_TYPE_HAS_NEWTUNE )
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 0 , " 0x%x newtuner " , DST_TYPE_HAS_NEWTUNE ) ;
2005-04-16 15:20:36 -07:00
if ( type_flags & DST_TYPE_HAS_TS204 )
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 0 , " 0x%x ts204 " , DST_TYPE_HAS_TS204 ) ;
2005-04-16 15:20:36 -07:00
if ( type_flags & DST_TYPE_HAS_SYMDIV )
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 0 , " 0x%x symdiv " , DST_TYPE_HAS_SYMDIV ) ;
2005-05-16 21:54:41 -07:00
if ( type_flags & DST_TYPE_HAS_FW_1 )
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 0 , " 0x%x firmware version = 1 " , DST_TYPE_HAS_FW_1 ) ;
2005-05-16 21:54:41 -07:00
if ( type_flags & DST_TYPE_HAS_FW_2 )
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 0 , " 0x%x firmware version = 2 " , DST_TYPE_HAS_FW_2 ) ;
2005-05-16 21:54:41 -07:00
if ( type_flags & DST_TYPE_HAS_FW_3 )
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 0 , " 0x%x firmware version = 3 " , DST_TYPE_HAS_FW_3 ) ;
dprintk ( verbose , DST_ERROR , 0 , " \n " ) ;
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:41 -07:00
2005-09-09 13:03:00 -07:00
static int dst_type_print ( u8 type )
2005-04-16 15:20:36 -07:00
{
char * otype ;
switch ( type ) {
case DST_TYPE_IS_SAT :
otype = " satellite " ;
break ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
case DST_TYPE_IS_TERR :
otype = " terrestrial " ;
break ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
case DST_TYPE_IS_CABLE :
otype = " cable " ;
break ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
default :
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " invalid dst type %d " , type ) ;
2005-04-16 15:20:36 -07:00
return - EINVAL ;
}
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " DST type: %s " , otype ) ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
/*
Known cards list
Satellite
- - - - - - - - - - - - - - - - - - -
2005-05-16 21:54:42 -07:00
200103 A
2005-05-16 21:54:41 -07:00
VP - 1020 DST - MOT LG ( old ) , TS = 188
VP - 1020 DST - 03 T LG ( new ) , TS = 204
VP - 1022 DST - 03 T LG ( new ) , TS = 204
VP - 1025 DST - 03 T LG ( new ) , TS = 204
VP - 1030 DSTMCI , LG ( new ) , TS = 188
VP - 1032 DSTMCI , LG ( new ) , TS = 188
Cable
- - - - - - - - - - - - - - - - - - -
VP - 2030 DCT - CI , Samsung , TS = 204
VP - 2021 DCT - CI , Unknown , TS = 204
VP - 2031 DCT - CI , Philips , TS = 188
VP - 2040 DCT - CI , Philips , TS = 188 , with CA daughter board
VP - 2040 DCT - CI , Philips , TS = 204 , without CA daughter board
Terrestrial
- - - - - - - - - - - - - - - - - - -
VP - 3050 DTTNXT TS = 188
VP - 3040 DTT - CI , Philips , TS = 188
VP - 3040 DTT - CI , Philips , TS = 204
ATSC
- - - - - - - - - - - - - - - - - - -
VP - 3220 ATSCDI , TS = 188
VP - 3250 ATSCAD , TS = 188
*/
struct dst_types dst_tlist [ ] = {
2005-05-16 21:54:42 -07:00
{
. device_id = " 200103A " ,
. offset = 0 ,
. dst_type = DST_TYPE_IS_SAT ,
2005-07-07 17:57:50 -07:00
. type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS ,
2005-05-16 21:54:42 -07:00
. dst_feature = 0
} , /* obsolete */
2005-05-16 21:54:41 -07:00
{
. device_id = " DST-020 " ,
. offset = 0 ,
. dst_type = DST_TYPE_IS_SAT ,
. type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 ,
. dst_feature = 0
} , /* obsolete */
{
. device_id = " DST-030 " ,
. offset = 0 ,
. dst_type = DST_TYPE_IS_SAT ,
. type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1 ,
. dst_feature = 0
} , /* obsolete */
{
. device_id = " DST-03T " ,
. offset = 0 ,
. dst_type = DST_TYPE_IS_SAT ,
. type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2 ,
. dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
| DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO
} ,
{
. device_id = " DST-MOT " ,
. offset = 0 ,
. dst_type = DST_TYPE_IS_SAT ,
. type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 ,
. dst_feature = 0
} , /* obsolete */
{
. device_id = " DST-CI " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_SAT ,
. type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1 ,
. dst_feature = DST_TYPE_HAS_CA
2005-05-16 21:54:43 -07:00
} , /* An OEM board */
2005-05-16 21:54:41 -07:00
{
. device_id = " DSTMCI " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_SAT ,
2005-07-07 17:57:50 -07:00
. type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT ,
2005-05-16 21:54:41 -07:00
. dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
} ,
{
. device_id = " DSTFCI " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_SAT ,
. type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1 ,
. dst_feature = 0
} , /* unknown to vendor */
{
. device_id = " DCT-CI " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_CABLE ,
2005-05-16 21:54:43 -07:00
. type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
2005-09-09 13:03:01 -07:00
| DST_TYPE_HAS_FW_2 ,
2005-05-16 21:54:41 -07:00
. dst_feature = DST_TYPE_HAS_CA
} ,
{
. device_id = " DCTNEW " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_CABLE ,
2005-09-09 13:03:01 -07:00
. type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD ,
2005-05-16 21:54:41 -07:00
. dst_feature = 0
} ,
{
. device_id = " DTT-CI " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_TERR ,
2005-11-08 21:35:09 -08:00
. type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE ,
. dst_feature = DST_TYPE_HAS_CA
2005-05-16 21:54:41 -07:00
} ,
{
. device_id = " DTTDIG " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_TERR ,
. type_flags = DST_TYPE_HAS_FW_2 ,
. dst_feature = 0
} ,
{
. device_id = " DTTNXT " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_TERR ,
. type_flags = DST_TYPE_HAS_FW_2 ,
. dst_feature = DST_TYPE_HAS_ANALOG
} ,
{
. device_id = " ATSCDI " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_ATSC ,
. type_flags = DST_TYPE_HAS_FW_2 ,
. dst_feature = 0
} ,
{
. device_id = " ATSCAD " ,
. offset = 1 ,
. dst_type = DST_TYPE_IS_ATSC ,
. type_flags = DST_TYPE_HAS_FW_2 ,
. dst_feature = 0
} ,
{ }
} ;
2005-09-09 13:03:01 -07:00
static int dst_get_mac ( struct dst_state * state )
{
u8 get_mac [ ] = { 0x00 , 0x0a , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
get_mac [ 7 ] = dst_check_sum ( get_mac , 7 ) ;
if ( dst_command ( state , get_mac , 8 ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " Unsupported Command " ) ;
return - 1 ;
}
memset ( & state - > mac_address , ' \0 ' , 8 ) ;
memcpy ( & state - > mac_address , & state - > rxbuffer , 6 ) ;
dprintk ( verbose , DST_ERROR , 1 , " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x] " ,
state - > mac_address [ 0 ] , state - > mac_address [ 1 ] , state - > mac_address [ 2 ] ,
state - > mac_address [ 4 ] , state - > mac_address [ 5 ] , state - > mac_address [ 6 ] ) ;
return 0 ;
}
static int dst_fw_ver ( struct dst_state * state )
{
u8 get_ver [ ] = { 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
get_ver [ 7 ] = dst_check_sum ( get_ver , 7 ) ;
if ( dst_command ( state , get_ver , 8 ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " Unsupported Command " ) ;
return - 1 ;
}
memset ( & state - > fw_version , ' \0 ' , 8 ) ;
memcpy ( & state - > fw_version , & state - > rxbuffer , 8 ) ;
dprintk ( verbose , DST_ERROR , 1 , " Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x " ,
state - > fw_version [ 0 ] > > 4 , state - > fw_version [ 0 ] & 0x0f ,
state - > fw_version [ 1 ] ,
state - > fw_version [ 5 ] , state - > fw_version [ 6 ] ,
state - > fw_version [ 4 ] , state - > fw_version [ 3 ] , state - > fw_version [ 2 ] ) ;
return 0 ;
}
static int dst_card_type ( struct dst_state * state )
{
u8 get_type [ ] = { 0x00 , 0x11 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
get_type [ 7 ] = dst_check_sum ( get_type , 7 ) ;
if ( dst_command ( state , get_type , 8 ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " Unsupported Command " ) ;
return - 1 ;
}
memset ( & state - > card_info , ' \0 ' , 8 ) ;
memcpy ( & state - > card_info , & state - > rxbuffer , 8 ) ;
dprintk ( verbose , DST_ERROR , 1 , " Device Model=[%s] " , & state - > card_info [ 0 ] ) ;
return 0 ;
}
static int dst_get_vendor ( struct dst_state * state )
{
u8 get_vendor [ ] = { 0x00 , 0x12 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
get_vendor [ 7 ] = dst_check_sum ( get_vendor , 7 ) ;
if ( dst_command ( state , get_vendor , 8 ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " Unsupported Command " ) ;
return - 1 ;
}
memset ( & state - > vendor , ' \0 ' , 8 ) ;
memcpy ( & state - > vendor , & state - > rxbuffer , 8 ) ;
dprintk ( verbose , DST_ERROR , 1 , " Vendor=[%s] " , & state - > vendor [ 0 ] ) ;
return 0 ;
}
2005-05-16 21:54:41 -07:00
2005-11-08 21:35:09 -08:00
static int dst_get_tuner_info ( struct dst_state * state )
{
u8 get_tuner_1 [ ] = { 0x00 , 0x13 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
u8 get_tuner_2 [ ] = { 0x00 , 0x0b , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
get_tuner_1 [ 7 ] = dst_check_sum ( get_tuner_1 , 7 ) ;
get_tuner_2 [ 7 ] = dst_check_sum ( get_tuner_2 , 7 ) ;
if ( state - > type_flags & DST_TYPE_HAS_MULTI_FE ) {
if ( dst_command ( state , get_tuner_2 , 8 ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " Unsupported Command " ) ;
return - 1 ;
}
} else {
if ( dst_command ( state , get_tuner_1 , 8 ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " Unsupported Command " ) ;
return - 1 ;
}
}
memset ( & state - > board_info , ' \0 ' , 8 ) ;
memcpy ( & state - > board_info , & state - > rxbuffer , 8 ) ;
if ( state - > type_flags & DST_TYPE_HAS_MULTI_FE ) {
if ( state - > board_info [ 1 ] = = 0x0b ) {
if ( state - > type_flags & DST_TYPE_HAS_TS204 )
state - > type_flags & = ~ DST_TYPE_HAS_TS204 ;
state - > type_flags | = DST_TYPE_HAS_NEWTUNE ;
dprintk ( verbose , DST_INFO , 1 , " DST type has TS=188 " ) ;
} else {
if ( state - > type_flags & DST_TYPE_HAS_NEWTUNE )
state - > type_flags & = ~ DST_TYPE_HAS_NEWTUNE ;
state - > type_flags | = DST_TYPE_HAS_TS204 ;
dprintk ( verbose , DST_INFO , 1 , " DST type has TS=204 " ) ;
}
} else {
if ( state - > board_info [ 0 ] = = 0xbc ) {
if ( state - > type_flags & DST_TYPE_HAS_TS204 )
state - > type_flags & = ~ DST_TYPE_HAS_TS204 ;
state - > type_flags | = DST_TYPE_HAS_NEWTUNE ;
dprintk ( verbose , DST_INFO , 1 , " DST type has TS=188, Daughterboard=[%d] " , state - > board_info [ 1 ] ) ;
} else if ( state - > board_info [ 0 ] = = 0xcc ) {
if ( state - > type_flags & DST_TYPE_HAS_NEWTUNE )
state - > type_flags & = ~ DST_TYPE_HAS_NEWTUNE ;
state - > type_flags | = DST_TYPE_HAS_TS204 ;
dprintk ( verbose , DST_INFO , 1 , " DST type has TS=204 Daughterboard=[%d] " , state - > board_info [ 1 ] ) ;
}
}
return 0 ;
}
2005-05-16 21:54:41 -07:00
static int dst_get_device_id ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:41 -07:00
u8 reply ;
2005-04-16 15:20:36 -07:00
int i ;
2005-05-16 21:54:41 -07:00
struct dst_types * p_dst_type ;
u8 use_dst_type = 0 ;
u32 use_type_flags = 0 ;
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
static u8 device_type [ 8 ] = { 0x00 , 0x06 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xff } ;
2005-04-16 15:20:36 -07:00
2005-05-16 21:54:41 -07:00
device_type [ 7 ] = dst_check_sum ( device_type , 7 ) ;
if ( write_dst ( state , device_type , FIXED_COMM ) )
return - 1 ; /* Write failed */
if ( ( dst_pio_disable ( state ) ) < 0 )
return - 1 ;
if ( read_dst ( state , & reply , GET_ACK ) )
return - 1 ; /* Read failure */
if ( reply ! = ACK ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " Write not Acknowledged! [Reply=0x%02x] " , reply ) ;
2005-05-16 21:54:41 -07:00
return - 1 ; /* Unack'd write */
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:41 -07:00
if ( ! dst_wait_dst_ready ( state , DEVICE_INIT ) )
return - 1 ; /* DST not ready yet */
if ( read_dst ( state , state - > rxbuffer , FIXED_COMM ) )
return - 1 ;
dst_pio_disable ( state ) ;
if ( state - > rxbuffer [ 7 ] ! = dst_check_sum ( state - > rxbuffer , 7 ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " Checksum failure! " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ; /* Checksum failure */
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:41 -07:00
state - > rxbuffer [ 7 ] = ' \0 ' ;
2005-09-09 13:03:00 -07:00
for ( i = 0 , p_dst_type = dst_tlist ; i < ARRAY_SIZE ( dst_tlist ) ; i + + , p_dst_type + + ) {
2005-05-16 21:54:41 -07:00
if ( ! strncmp ( & state - > rxbuffer [ p_dst_type - > offset ] , p_dst_type - > device_id , strlen ( p_dst_type - > device_id ) ) ) {
use_type_flags = p_dst_type - > type_flags ;
use_dst_type = p_dst_type - > dst_type ;
/* Card capabilities */
state - > dst_hw_cap = p_dst_type - > dst_feature ;
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " Recognise [%s] \n " , p_dst_type - > device_id ) ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
break ;
}
}
2005-05-16 21:54:41 -07:00
if ( i > = sizeof ( dst_tlist ) / sizeof ( dst_tlist [ 0 ] ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " Unable to recognize %s or %s " , & state - > rxbuffer [ 0 ] , & state - > rxbuffer [ 1 ] ) ;
dprintk ( verbose , DST_ERROR , 1 , " please email linux-dvb@linuxtv.org with this type in " ) ;
2005-04-16 15:20:36 -07:00
use_dst_type = DST_TYPE_IS_SAT ;
use_type_flags = DST_TYPE_HAS_SYMDIV ;
}
2005-05-16 21:54:41 -07:00
dst_type_print ( use_dst_type ) ;
2005-04-16 15:20:36 -07:00
state - > type_flags = use_type_flags ;
state - > dst_type = use_dst_type ;
dst_type_flags_print ( state - > type_flags ) ;
if ( state - > type_flags & DST_TYPE_HAS_TS204 ) {
dst_packsize ( state , 204 ) ;
}
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
static int dst_probe ( struct dst_state * state )
{
if ( ( rdc_8820_reset ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " RDC 8820 RESET Failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-05-16 21:54:45 -07:00
if ( dst_addons & DST_TYPE_HAS_CA )
msleep ( 4000 ) ;
else
msleep ( 100 ) ;
2005-05-16 21:54:41 -07:00
if ( ( dst_comm_init ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " DST Initialization Failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-05-16 21:54:43 -07:00
msleep ( 100 ) ;
2005-05-16 21:54:41 -07:00
if ( dst_get_device_id ( state ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " unknown device. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-09-09 13:03:01 -07:00
if ( dst_get_mac ( state ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " MAC: Unsupported command " ) ;
return 0 ;
}
2005-11-08 21:35:09 -08:00
if ( ( state - > type_flags & DST_TYPE_HAS_MULTI_FE ) | | ( state - > type_flags & DST_TYPE_HAS_FW_BUILD ) ) {
if ( dst_get_tuner_info ( state ) < 0 )
dprintk ( verbose , DST_INFO , 1 , " Tuner: Unsupported command " ) ;
}
2005-09-09 13:03:01 -07:00
if ( state - > type_flags & DST_TYPE_HAS_FW_BUILD ) {
if ( dst_fw_ver ( state ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " FW: Unsupported command " ) ;
return 0 ;
}
if ( dst_card_type ( state ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " Card: Unsupported command " ) ;
return 0 ;
}
if ( dst_get_vendor ( state ) < 0 ) {
dprintk ( verbose , DST_INFO , 1 , " Vendor: Unsupported command " ) ;
return 0 ;
}
}
2005-05-16 21:54:41 -07:00
return 0 ;
}
2005-09-09 13:03:00 -07:00
int dst_command ( struct dst_state * state , u8 * data , u8 len )
2005-04-16 15:20:36 -07:00
{
u8 reply ;
2005-05-16 21:54:41 -07:00
if ( ( dst_comm_init ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_NOTICE , 1 , " DST Communication Initialization Failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
if ( write_dst ( state , data , len ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " Tring to recover.. " ) ;
2005-05-16 21:54:41 -07:00
if ( ( dst_error_recovery ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " Recovery Failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
return - 1 ;
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:41 -07:00
if ( ( dst_pio_disable ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " PIO Disable Failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:43 -07:00
if ( state - > type_flags & DST_TYPE_HAS_FW_1 )
udelay ( 3000 ) ;
2005-05-16 21:54:41 -07:00
if ( read_dst ( state , & reply , GET_ACK ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " Trying to recover.. " ) ;
2005-05-16 21:54:41 -07:00
if ( ( dst_error_recovery ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " Recovery Failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
return - 1 ;
}
if ( reply ! = ACK ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " write not acknowledged 0x%02x " , reply ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
2005-04-16 15:20:36 -07:00
}
if ( len > = 2 & & data [ 0 ] = = 0 & & ( data [ 1 ] = = 1 | | data [ 1 ] = = 3 ) )
return 0 ;
2005-05-16 21:54:43 -07:00
if ( state - > type_flags & DST_TYPE_HAS_FW_1 )
udelay ( 3000 ) ;
else
udelay ( 2000 ) ;
2005-05-16 21:54:41 -07:00
if ( ! dst_wait_dst_ready ( state , NO_DELAY ) )
return - 1 ;
if ( read_dst ( state , state - > rxbuffer , FIXED_COMM ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " Trying to recover.. " ) ;
2005-05-16 21:54:41 -07:00
if ( ( dst_error_recovery ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " Recovery failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
return - 1 ;
2005-04-16 15:20:36 -07:00
}
if ( state - > rxbuffer [ 7 ] ! = dst_check_sum ( state - > rxbuffer , 7 ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " checksum failure " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( dst_command ) ;
2005-04-16 15:20:36 -07:00
2005-09-09 13:03:00 -07:00
static int dst_get_signal ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
int retval ;
u8 get_signal [ ] = { 0x00 , 0x05 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xfb } ;
2005-09-09 13:02:52 -07:00
//dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
2005-04-16 15:20:36 -07:00
if ( ( state - > diseq_flags & ATTEMPT_TUNE ) = = 0 ) {
state - > decode_lock = state - > decode_strength = state - > decode_snr = 0 ;
return 0 ;
}
if ( 0 = = ( state - > diseq_flags & HAS_LOCK ) ) {
state - > decode_lock = state - > decode_strength = state - > decode_snr = 0 ;
return 0 ;
}
if ( time_after_eq ( jiffies , state - > cur_jiff + ( HZ / 5 ) ) ) {
retval = dst_command ( state , get_signal , 8 ) ;
if ( retval < 0 )
return retval ;
if ( state - > dst_type = = DST_TYPE_IS_SAT ) {
state - > decode_lock = ( ( state - > rxbuffer [ 6 ] & 0x10 ) = = 0 ) ? 1 : 0 ;
state - > decode_strength = state - > rxbuffer [ 5 ] < < 8 ;
state - > decode_snr = state - > rxbuffer [ 2 ] < < 8 | state - > rxbuffer [ 3 ] ;
} else if ( ( state - > dst_type = = DST_TYPE_IS_TERR ) | | ( state - > dst_type = = DST_TYPE_IS_CABLE ) ) {
state - > decode_lock = ( state - > rxbuffer [ 1 ] ) ? 1 : 0 ;
state - > decode_strength = state - > rxbuffer [ 4 ] < < 8 ;
state - > decode_snr = state - > rxbuffer [ 3 ] < < 8 ;
}
state - > cur_jiff = jiffies ;
}
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_tone_power_cmd ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
u8 paket [ 8 ] = { 0x00 , 0x09 , 0xff , 0xff , 0x01 , 0x00 , 0x00 , 0x00 } ;
if ( state - > dst_type = = DST_TYPE_IS_TERR )
return 0 ;
2005-05-28 15:51:51 -07:00
paket [ 4 ] = state - > tx_tuna [ 4 ] ;
2005-05-28 15:51:51 -07:00
paket [ 2 ] = state - > tx_tuna [ 2 ] ;
2005-05-28 15:51:48 -07:00
paket [ 3 ] = state - > tx_tuna [ 3 ] ;
2005-05-16 21:54:41 -07:00
paket [ 7 ] = dst_check_sum ( paket , 7 ) ;
2005-04-16 15:20:36 -07:00
dst_command ( state , paket , 8 ) ;
2005-05-28 15:51:48 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_get_tuna ( struct dst_state * state )
2005-04-16 15:20:36 -07:00
{
int retval ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
if ( ( state - > diseq_flags & ATTEMPT_TUNE ) = = 0 )
return 0 ;
state - > diseq_flags & = ~ ( HAS_LOCK ) ;
2005-05-16 21:54:41 -07:00
if ( ! dst_wait_dst_ready ( state , NO_DELAY ) )
2005-04-16 15:20:36 -07:00
return 0 ;
2005-09-09 13:03:00 -07:00
if ( state - > type_flags & DST_TYPE_HAS_NEWTUNE )
2005-04-16 15:20:36 -07:00
/* how to get variable length reply ???? */
retval = read_dst ( state , state - > rx_tuna , 10 ) ;
2005-09-09 13:03:00 -07:00
else
2005-05-16 21:54:41 -07:00
retval = read_dst ( state , & state - > rx_tuna [ 2 ] , FIXED_COMM ) ;
2005-04-16 15:20:36 -07:00
if ( retval < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " read not successful " ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
if ( state - > type_flags & DST_TYPE_HAS_NEWTUNE ) {
if ( state - > rx_tuna [ 9 ] ! = dst_check_sum ( & state - > rx_tuna [ 0 ] , 9 ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " checksum failure ? " ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
} else {
if ( state - > rx_tuna [ 9 ] ! = dst_check_sum ( & state - > rx_tuna [ 2 ] , 7 ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " checksum failure? " ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
}
if ( state - > rx_tuna [ 2 ] = = 0 & & state - > rx_tuna [ 3 ] = = 0 )
return 0 ;
state - > decode_freq = ( ( state - > rx_tuna [ 2 ] & 0x7f ) < < 8 ) + state - > rx_tuna [ 3 ] ;
state - > decode_lock = 1 ;
state - > diseq_flags | = HAS_LOCK ;
2005-07-07 17:57:50 -07:00
2005-04-16 15:20:36 -07:00
return 1 ;
}
2005-09-09 13:03:00 -07:00
static int dst_set_voltage ( struct dvb_frontend * fe , fe_sec_voltage_t voltage ) ;
2005-04-16 15:20:36 -07:00
2005-09-09 13:03:00 -07:00
static int dst_write_tuna ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int retval ;
u8 reply ;
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_INFO , 1 , " type_flags 0x%x " , state - > type_flags ) ;
2005-04-16 15:20:36 -07:00
state - > decode_freq = 0 ;
state - > decode_lock = state - > decode_strength = state - > decode_snr = 0 ;
if ( state - > dst_type = = DST_TYPE_IS_SAT ) {
if ( ! ( state - > diseq_flags & HAS_POWER ) )
dst_set_voltage ( fe , SEC_VOLTAGE_13 ) ;
}
state - > diseq_flags & = ~ ( HAS_LOCK | ATTEMPT_TUNE ) ;
2005-05-16 21:54:41 -07:00
if ( ( dst_comm_init ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " DST Communication initialization failed. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
2005-04-16 15:20:36 -07:00
if ( state - > type_flags & DST_TYPE_HAS_NEWTUNE ) {
state - > tx_tuna [ 9 ] = dst_check_sum ( & state - > tx_tuna [ 0 ] , 9 ) ;
retval = write_dst ( state , & state - > tx_tuna [ 0 ] , 10 ) ;
} else {
state - > tx_tuna [ 9 ] = dst_check_sum ( & state - > tx_tuna [ 2 ] , 7 ) ;
2005-05-16 21:54:41 -07:00
retval = write_dst ( state , & state - > tx_tuna [ 2 ] , FIXED_COMM ) ;
2005-04-16 15:20:36 -07:00
}
if ( retval < 0 ) {
2005-05-16 21:54:41 -07:00
dst_pio_disable ( state ) ;
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " write not successful " ) ;
2005-04-16 15:20:36 -07:00
return retval ;
}
2005-05-16 21:54:41 -07:00
if ( ( dst_pio_disable ( state ) ) < 0 ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " DST PIO disable failed ! " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
}
if ( ( read_dst ( state , & reply , GET_ACK ) < 0 ) ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " read verify not successful. " ) ;
2005-05-16 21:54:41 -07:00
return - 1 ;
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:41 -07:00
if ( reply ! = ACK ) {
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " write not acknowledged 0x%02x " , reply ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
state - > diseq_flags | = ATTEMPT_TUNE ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
return dst_get_tuna ( state ) ;
}
/*
* line22k0 0x00 , 0x09 , 0x00 , 0xff , 0x01 , 0x00 , 0x00 , 0x00
* line22k1 0x00 , 0x09 , 0x01 , 0xff , 0x01 , 0x00 , 0x00 , 0x00
* line22k2 0x00 , 0x09 , 0x02 , 0xff , 0x01 , 0x00 , 0x00 , 0x00
* tone 0x00 , 0x09 , 0xff , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
* data 0x00 , 0x09 , 0xff , 0x01 , 0x01 , 0x00 , 0x00 , 0x00
* power_off 0x00 , 0x09 , 0xff , 0xff , 0x00 , 0x00 , 0x00 , 0x00
* power_on 0x00 , 0x09 , 0xff , 0xff , 0x01 , 0x00 , 0x00 , 0x00
* Diseqc 1 0x00 , 0x08 , 0x04 , 0xe0 , 0x10 , 0x38 , 0xf0 , 0xec
* Diseqc 2 0x00 , 0x08 , 0x04 , 0xe0 , 0x10 , 0x38 , 0xf4 , 0xe8
* Diseqc 3 0x00 , 0x08 , 0x04 , 0xe0 , 0x10 , 0x38 , 0xf8 , 0xe4
* Diseqc 4 0x00 , 0x08 , 0x04 , 0xe0 , 0x10 , 0x38 , 0xfc , 0xe0
*/
2005-09-09 13:03:00 -07:00
static int dst_set_diseqc ( struct dvb_frontend * fe , struct dvb_diseqc_master_cmd * cmd )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
u8 paket [ 8 ] = { 0x00 , 0x08 , 0x04 , 0xe0 , 0x10 , 0x38 , 0xf0 , 0xec } ;
2005-05-28 15:51:52 -07:00
if ( state - > dst_type ! = DST_TYPE_IS_SAT )
2005-04-16 15:20:36 -07:00
return 0 ;
if ( cmd - > msg_len = = 0 | | cmd - > msg_len > 4 )
return - EINVAL ;
memcpy ( & paket [ 3 ] , cmd - > msg , cmd - > msg_len ) ;
paket [ 7 ] = dst_check_sum ( & paket [ 0 ] , 7 ) ;
dst_command ( state , paket , 8 ) ;
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_set_voltage ( struct dvb_frontend * fe , fe_sec_voltage_t voltage )
2005-04-16 15:20:36 -07:00
{
int need_cmd ;
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
state - > voltage = voltage ;
2005-05-28 15:51:52 -07:00
if ( state - > dst_type ! = DST_TYPE_IS_SAT )
2005-04-16 15:20:36 -07:00
return 0 ;
need_cmd = 0 ;
2005-05-16 21:54:41 -07:00
2005-09-09 13:03:00 -07:00
switch ( voltage ) {
case SEC_VOLTAGE_13 :
case SEC_VOLTAGE_18 :
if ( ( state - > diseq_flags & HAS_POWER ) = = 0 )
2005-04-16 15:20:36 -07:00
need_cmd = 1 ;
2005-09-09 13:03:00 -07:00
state - > diseq_flags | = HAS_POWER ;
state - > tx_tuna [ 4 ] = 0x01 ;
break ;
case SEC_VOLTAGE_OFF :
need_cmd = 1 ;
state - > diseq_flags & = ~ ( HAS_POWER | HAS_LOCK | ATTEMPT_TUNE ) ;
state - > tx_tuna [ 4 ] = 0x00 ;
break ;
default :
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2005-09-09 13:03:00 -07:00
2005-05-16 21:54:41 -07:00
if ( need_cmd )
2005-04-16 15:20:36 -07:00
dst_tone_power_cmd ( state ) ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_set_tone ( struct dvb_frontend * fe , fe_sec_tone_mode_t tone )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
state - > tone = tone ;
2005-05-28 15:51:52 -07:00
if ( state - > dst_type ! = DST_TYPE_IS_SAT )
2005-04-16 15:20:36 -07:00
return 0 ;
switch ( tone ) {
2005-09-09 13:03:00 -07:00
case SEC_TONE_OFF :
if ( state - > type_flags & DST_TYPE_HAS_OBS_REGS )
state - > tx_tuna [ 2 ] = 0x00 ;
else
state - > tx_tuna [ 2 ] = 0xff ;
break ;
2005-05-16 21:54:41 -07:00
2005-09-09 13:03:00 -07:00
case SEC_TONE_ON :
state - > tx_tuna [ 2 ] = 0x02 ;
break ;
default :
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
dst_tone_power_cmd ( state ) ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-05-28 15:51:48 -07:00
static int dst_send_burst ( struct dvb_frontend * fe , fe_sec_mini_cmd_t minicmd )
{
struct dst_state * state = fe - > demodulator_priv ;
2005-05-28 15:51:52 -07:00
if ( state - > dst_type ! = DST_TYPE_IS_SAT )
2005-05-28 15:51:48 -07:00
return 0 ;
state - > minicmd = minicmd ;
switch ( minicmd ) {
2005-09-09 13:03:00 -07:00
case SEC_MINI_A :
state - > tx_tuna [ 3 ] = 0x02 ;
break ;
case SEC_MINI_B :
state - > tx_tuna [ 3 ] = 0xff ;
break ;
2005-05-28 15:51:48 -07:00
}
dst_tone_power_cmd ( state ) ;
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_init ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
static u8 sat_tuna_188 [ ] = { 0x09 , 0x00 , 0x03 , 0xb6 , 0x01 , 0x00 , 0x73 , 0x21 , 0x00 , 0x00 } ;
static u8 sat_tuna_204 [ ] = { 0x00 , 0x00 , 0x03 , 0xb6 , 0x01 , 0x55 , 0xbd , 0x50 , 0x00 , 0x00 } ;
static u8 ter_tuna_188 [ ] = { 0x09 , 0x00 , 0x03 , 0xb6 , 0x01 , 0x07 , 0x00 , 0x00 , 0x00 , 0x00 } ;
static u8 ter_tuna_204 [ ] = { 0x00 , 0x00 , 0x03 , 0xb6 , 0x01 , 0x07 , 0x00 , 0x00 , 0x00 , 0x00 } ;
static u8 cab_tuna_204 [ ] = { 0x00 , 0x00 , 0x03 , 0xb6 , 0x01 , 0x07 , 0x00 , 0x00 , 0x00 , 0x00 } ;
static u8 cab_tuna_188 [ ] = { 0x09 , 0x00 , 0x03 , 0xb6 , 0x01 , 0x07 , 0x00 , 0x00 , 0x00 , 0x00 } ;
2005-07-07 17:57:50 -07:00
state - > inversion = INVERSION_OFF ;
2005-04-16 15:20:36 -07:00
state - > voltage = SEC_VOLTAGE_13 ;
state - > tone = SEC_TONE_OFF ;
state - > diseq_flags = 0 ;
state - > k22 = 0x02 ;
state - > bandwidth = BANDWIDTH_7_MHZ ;
state - > cur_jiff = jiffies ;
2005-09-09 13:03:00 -07:00
if ( state - > dst_type = = DST_TYPE_IS_SAT )
memcpy ( state - > tx_tuna , ( ( state - > type_flags & DST_TYPE_HAS_NEWTUNE ) ? sat_tuna_188 : sat_tuna_204 ) , sizeof ( sat_tuna_204 ) ) ;
else if ( state - > dst_type = = DST_TYPE_IS_TERR )
memcpy ( state - > tx_tuna , ( ( state - > type_flags & DST_TYPE_HAS_NEWTUNE ) ? ter_tuna_188 : ter_tuna_204 ) , sizeof ( ter_tuna_204 ) ) ;
else if ( state - > dst_type = = DST_TYPE_IS_CABLE )
memcpy ( state - > tx_tuna , ( ( state - > type_flags & DST_TYPE_HAS_NEWTUNE ) ? cab_tuna_188 : cab_tuna_204 ) , sizeof ( cab_tuna_204 ) ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_read_status ( struct dvb_frontend * fe , fe_status_t * status )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
* status = 0 ;
if ( state - > diseq_flags & HAS_LOCK ) {
2005-07-07 17:57:50 -07:00
// dst_get_signal(state); // don't require(?) to ask MCU
2005-04-16 15:20:36 -07:00
if ( state - > decode_lock )
* status | = FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI ;
}
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_read_signal_strength ( struct dvb_frontend * fe , u16 * strength )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
dst_get_signal ( state ) ;
* strength = state - > decode_strength ;
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_read_snr ( struct dvb_frontend * fe , u16 * snr )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
dst_get_signal ( state ) ;
* snr = state - > decode_snr ;
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_set_frontend ( struct dvb_frontend * fe , struct dvb_frontend_parameters * p )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
dst_set_freq ( state , p - > frequency ) ;
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " Set Frequency=[%d] " , p - > frequency ) ;
2005-05-16 21:54:41 -07:00
2005-04-16 15:20:36 -07:00
if ( state - > dst_type = = DST_TYPE_IS_SAT ) {
2005-07-07 17:57:50 -07:00
if ( state - > type_flags & DST_TYPE_HAS_OBS_REGS )
dst_set_inversion ( state , p - > inversion ) ;
2005-04-16 15:20:36 -07:00
dst_set_fec ( state , p - > u . qpsk . fec_inner ) ;
dst_set_symbolrate ( state , p - > u . qpsk . symbol_rate ) ;
2005-07-07 17:57:50 -07:00
dst_set_polarization ( state ) ;
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_DEBUG , 1 , " Set Symbolrate=[%d] " , p - > u . qpsk . symbol_rate ) ;
2005-05-16 21:54:41 -07:00
2005-09-09 13:03:00 -07:00
} else if ( state - > dst_type = = DST_TYPE_IS_TERR )
2005-04-16 15:20:36 -07:00
dst_set_bandwidth ( state , p - > u . ofdm . bandwidth ) ;
2005-09-09 13:03:00 -07:00
else if ( state - > dst_type = = DST_TYPE_IS_CABLE ) {
2005-04-16 15:20:36 -07:00
dst_set_fec ( state , p - > u . qam . fec_inner ) ;
dst_set_symbolrate ( state , p - > u . qam . symbol_rate ) ;
2005-07-07 17:57:50 -07:00
dst_set_modulation ( state , p - > u . qam . modulation ) ;
2005-04-16 15:20:36 -07:00
}
dst_write_tuna ( fe ) ;
return 0 ;
}
2005-09-09 13:03:00 -07:00
static int dst_get_frontend ( struct dvb_frontend * fe , struct dvb_frontend_parameters * p )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
p - > frequency = state - > decode_freq ;
if ( state - > dst_type = = DST_TYPE_IS_SAT ) {
2005-07-07 17:57:50 -07:00
if ( state - > type_flags & DST_TYPE_HAS_OBS_REGS )
p - > inversion = state - > inversion ;
2005-04-16 15:20:36 -07:00
p - > u . qpsk . symbol_rate = state - > symbol_rate ;
p - > u . qpsk . fec_inner = dst_get_fec ( state ) ;
} else if ( state - > dst_type = = DST_TYPE_IS_TERR ) {
p - > u . ofdm . bandwidth = state - > bandwidth ;
} else if ( state - > dst_type = = DST_TYPE_IS_CABLE ) {
p - > u . qam . symbol_rate = state - > symbol_rate ;
p - > u . qam . fec_inner = dst_get_fec ( state ) ;
2005-07-07 17:57:50 -07:00
p - > u . qam . modulation = dst_get_modulation ( state ) ;
2005-04-16 15:20:36 -07:00
}
return 0 ;
}
2005-09-09 13:03:00 -07:00
static void dst_release ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2005-09-09 13:03:00 -07:00
struct dst_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
kfree ( state ) ;
}
static struct dvb_frontend_ops dst_dvbt_ops ;
static struct dvb_frontend_ops dst_dvbs_ops ;
static struct dvb_frontend_ops dst_dvbc_ops ;
2005-09-09 13:03:00 -07:00
struct dst_state * dst_attach ( struct dst_state * state , struct dvb_adapter * dvb_adapter )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:41 -07:00
/* check if the ASIC is there */
if ( dst_probe ( state ) < 0 ) {
2005-11-07 01:01:31 -08:00
kfree ( state ) ;
2005-05-16 21:54:41 -07:00
return NULL ;
}
2005-04-16 15:20:36 -07:00
/* determine settings based on type */
switch ( state - > dst_type ) {
case DST_TYPE_IS_TERR :
memcpy ( & state - > ops , & dst_dvbt_ops , sizeof ( struct dvb_frontend_ops ) ) ;
break ;
case DST_TYPE_IS_CABLE :
memcpy ( & state - > ops , & dst_dvbc_ops , sizeof ( struct dvb_frontend_ops ) ) ;
break ;
case DST_TYPE_IS_SAT :
memcpy ( & state - > ops , & dst_dvbs_ops , sizeof ( struct dvb_frontend_ops ) ) ;
break ;
default :
2005-09-09 13:03:00 -07:00
dprintk ( verbose , DST_ERROR , 1 , " unknown DST type. please report to the LinuxTV.org DVB mailinglist. " ) ;
2005-11-07 01:01:31 -08:00
kfree ( state ) ;
2005-05-16 21:54:41 -07:00
return NULL ;
2005-04-16 15:20:36 -07:00
}
/* create dvb_frontend */
state - > frontend . ops = & state - > ops ;
state - > frontend . demodulator_priv = state ;
2005-05-16 21:54:41 -07:00
return state ; /* Manu (DST is a card not a frontend) */
2005-04-16 15:20:36 -07:00
}
2005-05-16 21:54:41 -07:00
EXPORT_SYMBOL ( dst_attach ) ;
2005-04-16 15:20:36 -07:00
static struct dvb_frontend_ops dst_dvbt_ops = {
. info = {
. name = " DST DVB-T " ,
. type = FE_OFDM ,
. frequency_min = 137000000 ,
. frequency_max = 858000000 ,
. frequency_stepsize = 166667 ,
. caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
} ,
. release = dst_release ,
. init = dst_init ,
. set_frontend = dst_set_frontend ,
. get_frontend = dst_get_frontend ,
. read_status = dst_read_status ,
. read_signal_strength = dst_read_signal_strength ,
. read_snr = dst_read_snr ,
} ;
static struct dvb_frontend_ops dst_dvbs_ops = {
. info = {
. name = " DST DVB-S " ,
. type = FE_QPSK ,
. frequency_min = 950000 ,
. frequency_max = 2150000 ,
. frequency_stepsize = 1000 , /* kHz for QPSK frontends */
. frequency_tolerance = 29500 ,
. symbol_rate_min = 1000000 ,
. symbol_rate_max = 45000000 ,
/* . symbol_rate_tolerance = ???,*/
. caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
} ,
. release = dst_release ,
. init = dst_init ,
. set_frontend = dst_set_frontend ,
. get_frontend = dst_get_frontend ,
. read_status = dst_read_status ,
. read_signal_strength = dst_read_signal_strength ,
. read_snr = dst_read_snr ,
2005-05-28 15:51:48 -07:00
. diseqc_send_burst = dst_send_burst ,
2005-04-16 15:20:36 -07:00
. diseqc_send_master_cmd = dst_set_diseqc ,
. set_voltage = dst_set_voltage ,
. set_tone = dst_set_tone ,
} ;
static struct dvb_frontend_ops dst_dvbc_ops = {
. info = {
. name = " DST DVB-C " ,
. type = FE_QAM ,
. frequency_stepsize = 62500 ,
. frequency_min = 51000000 ,
. frequency_max = 858000000 ,
. symbol_rate_min = 1000000 ,
. symbol_rate_max = 45000000 ,
/* . symbol_rate_tolerance = ???,*/
. caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO
} ,
. release = dst_release ,
. init = dst_init ,
. set_frontend = dst_set_frontend ,
. get_frontend = dst_get_frontend ,
. read_status = dst_read_status ,
. read_signal_strength = dst_read_signal_strength ,
. read_snr = dst_read_snr ,
} ;
MODULE_DESCRIPTION ( " DST DVB-S/T/C Combo Frontend driver " ) ;
2005-05-16 21:54:41 -07:00
MODULE_AUTHOR ( " Jamie Honan, Manu Abraham " ) ;
2005-04-16 15:20:36 -07:00
MODULE_LICENSE ( " GPL " ) ;