2019-05-20 09:19:02 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07:00
/*
2008-04-12 15:04:49 -03:00
Driver for Zarlink VP310 / MT312 / ZL10313 Satellite Channel Decoder
2005-04-16 15:20:36 -07:00
Copyright ( C ) 2003 Andreas Oberritter < obi @ linuxtv . org >
2008-04-12 15:04:49 -03:00
Copyright ( C ) 2008 Matthias Schwarzott < zzam @ gentoo . org >
2005-04-16 15:20:36 -07:00
References :
http : //products.zarlink.com/product_profiles/MT312.htm
http : //products.zarlink.com/product_profiles/SL1935.htm
*/
# include <linux/delay.h>
# include <linux/errno.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/module.h>
2005-10-30 15:03:48 -08:00
# include <linux/string.h>
# include <linux/slab.h>
2005-04-16 15:20:36 -07:00
2017-12-28 13:03:51 -05:00
# include <media/dvb_frontend.h>
2005-04-16 15:20:36 -07:00
# include "mt312_priv.h"
# include "mt312.h"
2013-11-02 05:05:18 -03:00
/* Max transfer size done by I2C transfer functions */
# define MAX_XFER_SIZE 64
2005-04-16 15:20:36 -07:00
struct mt312_state {
2007-12-21 08:56:44 -03:00
struct i2c_adapter * i2c ;
2005-04-16 15:20:36 -07:00
/* configuration settings */
2007-12-21 08:56:44 -03:00
const struct mt312_config * config ;
2005-04-16 15:20:36 -07:00
struct dvb_frontend frontend ;
u8 id ;
2008-04-12 15:04:48 -03:00
unsigned long xtal ;
u8 freq_mult ;
2005-04-16 15:20:36 -07:00
} ;
static int debug ;
# define dprintk(args...) \
do { \
2007-12-21 08:56:44 -03:00
if ( debug ) \
printk ( KERN_DEBUG " mt312: " args ) ; \
2005-04-16 15:20:36 -07:00
} while ( 0 )
# define MT312_PLL_CLK 10000000UL /* 10 MHz */
2008-04-12 15:04:49 -03:00
# define MT312_PLL_CLK_10_111 10111000UL /* 10.111 MHz */
2005-04-16 15:20:36 -07:00
2007-12-21 08:56:44 -03:00
static int mt312_read ( struct mt312_state * state , const enum mt312_reg_addr reg ,
2008-04-12 15:04:46 -03:00
u8 * buf , const size_t count )
2005-04-16 15:20:36 -07:00
{
int ret ;
struct i2c_msg msg [ 2 ] ;
u8 regbuf [ 1 ] = { reg } ;
msg [ 0 ] . addr = state - > config - > demod_address ;
msg [ 0 ] . flags = 0 ;
msg [ 0 ] . buf = regbuf ;
msg [ 0 ] . len = 1 ;
msg [ 1 ] . addr = state - > config - > demod_address ;
msg [ 1 ] . flags = I2C_M_RD ;
msg [ 1 ] . buf = buf ;
msg [ 1 ] . len = count ;
ret = i2c_transfer ( state - > i2c , msg , 2 ) ;
if ( ret ! = 2 ) {
2009-05-20 04:57:10 -03:00
printk ( KERN_DEBUG " %s: ret == %d \n " , __func__ , ret ) ;
2005-04-16 15:20:36 -07:00
return - EREMOTEIO ;
}
2007-12-21 08:56:44 -03:00
if ( debug ) {
2005-04-16 15:20:36 -07:00
int i ;
dprintk ( " R(%d): " , reg & 0x7f ) ;
for ( i = 0 ; i < count ; i + + )
2009-07-02 16:17:28 -03:00
printk ( KERN_CONT " %02x " , buf [ i ] ) ;
2005-04-16 15:20:36 -07:00
printk ( " \n " ) ;
}
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_write ( struct mt312_state * state , const enum mt312_reg_addr reg ,
2008-04-12 15:04:46 -03:00
const u8 * src , const size_t count )
2005-04-16 15:20:36 -07:00
{
int ret ;
2013-11-02 05:05:18 -03:00
u8 buf [ MAX_XFER_SIZE ] ;
2005-04-16 15:20:36 -07:00
struct i2c_msg msg ;
2013-11-02 05:05:18 -03:00
if ( 1 + count > sizeof ( buf ) ) {
printk ( KERN_WARNING
2014-09-24 20:35:12 -03:00
" mt312: write: len=%zu is too big! \n " , count ) ;
2013-11-02 05:05:18 -03:00
return - EINVAL ;
}
2007-12-21 08:56:44 -03:00
if ( debug ) {
2005-04-16 15:20:36 -07:00
int i ;
dprintk ( " W(%d): " , reg & 0x7f ) ;
for ( i = 0 ; i < count ; i + + )
2009-07-02 16:17:28 -03:00
printk ( KERN_CONT " %02x " , src [ i ] ) ;
2005-04-16 15:20:36 -07:00
printk ( " \n " ) ;
}
buf [ 0 ] = reg ;
memcpy ( & buf [ 1 ] , src , count ) ;
msg . addr = state - > config - > demod_address ;
msg . flags = 0 ;
msg . buf = buf ;
msg . len = count + 1 ;
ret = i2c_transfer ( state - > i2c , & msg , 1 ) ;
if ( ret ! = 1 ) {
2008-04-08 23:20:00 -03:00
dprintk ( " %s: ret == %d \n " , __func__ , ret ) ;
2005-04-16 15:20:36 -07:00
return - EREMOTEIO ;
}
return 0 ;
}
2007-12-21 08:56:44 -03:00
static inline int mt312_readreg ( struct mt312_state * state ,
2005-04-16 15:20:36 -07:00
const enum mt312_reg_addr reg , u8 * val )
{
return mt312_read ( state , reg , val , 1 ) ;
}
2007-12-21 08:56:44 -03:00
static inline int mt312_writereg ( struct mt312_state * state ,
2005-04-16 15:20:36 -07:00
const enum mt312_reg_addr reg , const u8 val )
{
2017-11-30 11:55:46 -05:00
u8 tmp = val ; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
return mt312_write ( state , reg , & tmp , 1 ) ;
2005-04-16 15:20:36 -07:00
}
2007-12-21 08:56:44 -03:00
static int mt312_reset ( struct mt312_state * state , const u8 full )
2005-04-16 15:20:36 -07:00
{
return mt312_writereg ( state , RESET , full ? 0x80 : 0x40 ) ;
}
2007-12-21 08:56:44 -03:00
static int mt312_get_inversion ( struct mt312_state * state ,
2015-06-07 14:53:52 -03:00
enum fe_spectral_inversion * i )
2005-04-16 15:20:36 -07:00
{
int ret ;
u8 vit_mode ;
2007-12-24 07:12:55 -03:00
ret = mt312_readreg ( state , VIT_MODE , & vit_mode ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
if ( vit_mode & 0x80 ) /* auto inversion was used */
* i = ( vit_mode & 0x40 ) ? INVERSION_ON : INVERSION_OFF ;
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_get_symbol_rate ( struct mt312_state * state , u32 * sr )
2005-04-16 15:20:36 -07:00
{
int ret ;
u8 sym_rate_h ;
u8 dec_ratio ;
u16 sym_rat_op ;
u16 monitor ;
u8 buf [ 2 ] ;
2007-12-24 07:12:55 -03:00
ret = mt312_readreg ( state , SYM_RATE_H , & sym_rate_h ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-21 08:56:44 -03:00
if ( sym_rate_h & 0x80 ) {
/* symbol rate search was used */
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , MON_CTRL , 0x03 ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_read ( state , MONITOR_H , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
monitor = ( buf [ 0 ] < < 8 ) | buf [ 1 ] ;
2007-12-21 08:58:09 -03:00
dprintk ( " sr(auto) = %u \n " ,
2019-10-09 11:55:22 -03:00
DIV_ROUND_CLOSEST ( monitor * 15625 , 4 ) ) ;
2005-04-16 15:20:36 -07:00
} else {
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , MON_CTRL , 0x05 ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_read ( state , MONITOR_H , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
dec_ratio = ( ( buf [ 0 ] > > 5 ) & 0x07 ) * 32 ;
2007-12-24 07:12:55 -03:00
ret = mt312_read ( state , SYM_RAT_OP_H , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
sym_rat_op = ( buf [ 0 ] < < 8 ) | buf [ 1 ] ;
2007-12-21 08:58:09 -03:00
dprintk ( " sym_rat_op=%d dec_ratio=%d \n " ,
2005-04-16 15:20:36 -07:00
sym_rat_op , dec_ratio ) ;
2007-12-21 08:58:09 -03:00
dprintk ( " *sr(manual) = %lu \n " ,
2008-04-12 15:04:48 -03:00
( ( ( state - > xtal * 8192 ) / ( sym_rat_op + 8192 ) ) *
2005-04-16 15:20:36 -07:00
2 ) - dec_ratio ) ;
}
return 0 ;
}
2015-06-07 14:53:52 -03:00
static int mt312_get_code_rate ( struct mt312_state * state , enum fe_code_rate * cr )
2005-04-16 15:20:36 -07:00
{
2015-06-07 14:53:52 -03:00
const enum fe_code_rate fec_tab [ 8 ] =
2005-04-16 15:20:36 -07:00
{ FEC_1_2 , FEC_2_3 , FEC_3_4 , FEC_5_6 , FEC_6_7 , FEC_7_8 ,
FEC_AUTO , FEC_AUTO } ;
int ret ;
u8 fec_status ;
2007-12-24 07:12:55 -03:00
ret = mt312_readreg ( state , FEC_STATUS , & fec_status ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
* cr = fec_tab [ ( fec_status > > 4 ) & 0x07 ] ;
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_initfe ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 buf [ 2 ] ;
/* wake up */
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , CONFIG ,
2008-04-12 15:04:48 -03:00
( state - > freq_mult = = 6 ? 0x88 : 0x8c ) ) ;
2007-12-24 07:12:55 -03:00
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
/* wait at least 150 usec */
udelay ( 150 ) ;
/* full reset */
2007-12-24 07:12:55 -03:00
ret = mt312_reset ( state , 1 ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-21 08:56:44 -03:00
/* Per datasheet, write correct values. 09/28/03 ACCJr.
* If we don ' t do this , we won ' t get FE_HAS_VITERBI in the VP310 . */
2005-04-16 15:20:36 -07:00
{
2007-12-21 08:56:44 -03:00
u8 buf_def [ 8 ] = { 0x14 , 0x12 , 0x03 , 0x02 ,
0x01 , 0x00 , 0x00 , 0x00 } ;
2005-04-16 15:20:36 -07:00
2007-12-24 07:12:55 -03:00
ret = mt312_write ( state , VIT_SETUP , buf_def , sizeof ( buf_def ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
}
2008-04-12 15:04:49 -03:00
switch ( state - > id ) {
case ID_ZL10313 :
/* enable ADC */
ret = mt312_writereg ( state , GPP_CTRL , 0x80 ) ;
if ( ret < 0 )
return ret ;
/* configure ZL10313 for optimal ADC performance */
buf [ 0 ] = 0x80 ;
buf [ 1 ] = 0xB0 ;
ret = mt312_write ( state , HW_CTRL , buf , 2 ) ;
if ( ret < 0 )
return ret ;
/* enable MPEG output and ADCs */
ret = mt312_writereg ( state , HW_CTRL , 0x00 ) ;
if ( ret < 0 )
return ret ;
ret = mt312_writereg ( state , MPEG_CTRL , 0x00 ) ;
if ( ret < 0 )
return ret ;
break ;
}
2005-04-16 15:20:36 -07:00
/* SYS_CLK */
2019-10-09 11:55:22 -03:00
buf [ 0 ] = DIV_ROUND_CLOSEST ( state - > xtal * state - > freq_mult * 2 , 1000000 ) ;
2005-04-16 15:20:36 -07:00
/* DISEQC_RATIO */
2019-10-09 11:55:22 -03:00
buf [ 1 ] = DIV_ROUND_CLOSEST ( state - > xtal , 22000 * 4 ) ;
2005-04-16 15:20:36 -07:00
2007-12-24 07:12:55 -03:00
ret = mt312_write ( state , SYS_CLK , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , SNR_THS_HIGH , 0x32 ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2008-04-12 15:04:49 -03:00
/* different MOCLK polarity */
switch ( state - > id ) {
case ID_ZL10313 :
buf [ 0 ] = 0x33 ;
break ;
default :
buf [ 0 ] = 0x53 ;
break ;
}
ret = mt312_writereg ( state , OP_CTRL , buf [ 0 ] ) ;
2007-12-24 07:12:55 -03:00
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
/* TS_SW_LIM */
buf [ 0 ] = 0x8c ;
buf [ 1 ] = 0x98 ;
2007-12-24 07:12:55 -03:00
ret = mt312_write ( state , TS_SW_LIM_L , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , CS_SW_LIM , 0x69 ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_send_master_cmd ( struct dvb_frontend * fe ,
2005-04-16 15:20:36 -07:00
struct dvb_diseqc_master_cmd * c )
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 diseqc_mode ;
if ( ( c - > msg_len = = 0 ) | | ( c - > msg_len > sizeof ( c - > msg ) ) )
return - EINVAL ;
2007-12-24 07:12:55 -03:00
ret = mt312_readreg ( state , DISEQC_MODE , & diseqc_mode ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_write ( state , ( 0x80 | DISEQC_INSTR ) , c - > msg , c - > msg_len ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , DISEQC_MODE ,
( diseqc_mode & 0x40 ) | ( ( c - > msg_len - 1 ) < < 3 )
| 0x04 ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2008-04-12 15:04:47 -03:00
/* is there a better way to wait for message to be transmitted */
msleep ( 100 ) ;
2005-04-16 15:20:36 -07:00
/* set DISEQC_MODE[2:0] to zero if a return message is expected */
2007-12-24 07:12:55 -03:00
if ( c - > msg [ 0 ] & 0x02 ) {
ret = mt312_writereg ( state , DISEQC_MODE , ( diseqc_mode & 0x40 ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
}
2005-04-16 15:20:36 -07:00
return 0 ;
}
2015-06-07 14:53:52 -03:00
static int mt312_send_burst ( struct dvb_frontend * fe ,
const enum fe_sec_mini_cmd c )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
const u8 mini_tab [ 2 ] = { 0x02 , 0x03 } ;
int ret ;
u8 diseqc_mode ;
if ( c > SEC_MINI_B )
return - EINVAL ;
2007-12-24 07:12:55 -03:00
ret = mt312_readreg ( state , DISEQC_MODE , & diseqc_mode ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , DISEQC_MODE ,
( diseqc_mode & 0x40 ) | mini_tab [ c ] ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
return 0 ;
}
2015-06-07 14:53:52 -03:00
static int mt312_set_tone ( struct dvb_frontend * fe ,
const enum fe_sec_tone_mode t )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
const u8 tone_tab [ 2 ] = { 0x01 , 0x00 } ;
int ret ;
u8 diseqc_mode ;
if ( t > SEC_TONE_OFF )
return - EINVAL ;
2007-12-24 07:12:55 -03:00
ret = mt312_readreg ( state , DISEQC_MODE , & diseqc_mode ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , DISEQC_MODE ,
( diseqc_mode & 0x40 ) | tone_tab [ t ] ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
return 0 ;
}
2015-06-07 14:53:52 -03:00
static int mt312_set_voltage ( struct dvb_frontend * fe ,
const enum fe_sec_voltage v )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
const u8 volt_tab [ 3 ] = { 0x00 , 0x40 , 0x00 } ;
2008-04-12 15:04:50 -03:00
u8 val ;
2005-04-16 15:20:36 -07:00
if ( v > SEC_VOLTAGE_OFF )
return - EINVAL ;
2008-04-12 15:04:50 -03:00
val = volt_tab [ v ] ;
if ( state - > config - > voltage_inverted )
val ^ = 0x40 ;
return mt312_writereg ( state , DISEQC_MODE , val ) ;
2005-04-16 15:20:36 -07:00
}
2015-06-07 14:53:52 -03:00
static int mt312_read_status ( struct dvb_frontend * fe , enum fe_status * s )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 status [ 3 ] ;
* s = 0 ;
2007-12-24 07:12:55 -03:00
ret = mt312_read ( state , QPSK_STAT_H , status , sizeof ( status ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
[media] dvb-frontends: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:22 -02:00
dprintk ( " QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x \n " ,
status [ 0 ] , status [ 1 ] , status [ 2 ] ) ;
2005-04-16 15:20:36 -07:00
if ( status [ 0 ] & 0xc0 )
* s | = FE_HAS_SIGNAL ; /* signal noise ratio */
if ( status [ 0 ] & 0x04 )
* s | = FE_HAS_CARRIER ; /* qpsk carrier lock */
if ( status [ 2 ] & 0x02 )
* s | = FE_HAS_VITERBI ; /* viterbi lock */
if ( status [ 2 ] & 0x04 )
* s | = FE_HAS_SYNC ; /* byte align lock */
if ( status [ 0 ] & 0x01 )
* s | = FE_HAS_LOCK ; /* qpsk lock */
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_read_ber ( struct dvb_frontend * fe , u32 * ber )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 buf [ 3 ] ;
2007-12-24 07:12:55 -03:00
ret = mt312_read ( state , RS_BERCNT_H , buf , 3 ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
* ber = ( ( buf [ 0 ] < < 16 ) | ( buf [ 1 ] < < 8 ) | buf [ 2 ] ) * 64 ;
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_read_signal_strength ( struct dvb_frontend * fe ,
u16 * signal_strength )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 buf [ 3 ] ;
u16 agc ;
s16 err_db ;
2007-12-24 07:12:55 -03:00
ret = mt312_read ( state , AGC_H , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
agc = ( buf [ 0 ] < < 6 ) | ( buf [ 1 ] > > 2 ) ;
err_db = ( s16 ) ( ( ( buf [ 1 ] & 0x03 ) < < 14 ) | buf [ 2 ] < < 6 ) > > 6 ;
* signal_strength = agc ;
2007-12-21 08:58:09 -03:00
dprintk ( " agc=%08x err_db=%hd \n " , agc , err_db ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_read_snr ( struct dvb_frontend * fe , u16 * snr )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 buf [ 2 ] ;
2008-04-12 15:04:46 -03:00
ret = mt312_read ( state , M_SNR_H , buf , sizeof ( buf ) ) ;
2007-12-24 07:12:55 -03:00
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
* snr = 0xFFFF - ( ( ( ( buf [ 0 ] & 0x7f ) < < 8 ) | buf [ 1 ] ) < < 1 ) ;
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_read_ucblocks ( struct dvb_frontend * fe , u32 * ubc )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 buf [ 2 ] ;
2008-04-12 15:04:46 -03:00
ret = mt312_read ( state , RS_UBC_H , buf , sizeof ( buf ) ) ;
2007-12-24 07:12:55 -03:00
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
* ubc = ( buf [ 0 ] < < 8 ) | buf [ 1 ] ;
return 0 ;
}
2011-12-26 13:50:05 -03:00
static int mt312_set_frontend ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2011-12-26 13:50:05 -03:00
struct dtv_frontend_properties * p = & fe - > dtv_property_cache ;
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 buf [ 5 ] , config_val ;
u16 sr ;
const u8 fec_tab [ 10 ] =
{ 0x00 , 0x01 , 0x02 , 0x04 , 0x3f , 0x08 , 0x10 , 0x20 , 0x3f , 0x3f } ;
const u8 inv_tab [ 3 ] = { 0x00 , 0x40 , 0x80 } ;
2008-04-08 23:20:00 -03:00
dprintk ( " %s: Freq %d \n " , __func__ , p - > frequency ) ;
2005-04-16 15:20:36 -07:00
2018-07-05 18:59:36 -04:00
if ( ( p - > frequency < fe - > ops . info . frequency_min_hz / kHz )
| | ( p - > frequency > fe - > ops . info . frequency_max_hz / kHz ) )
2005-04-16 15:20:36 -07:00
return - EINVAL ;
2012-10-27 16:14:01 -03:00
if ( ( ( int ) p - > inversion < INVERSION_OFF )
2005-04-16 15:20:36 -07:00
| | ( p - > inversion > INVERSION_ON ) )
return - EINVAL ;
2011-12-26 13:50:05 -03:00
if ( ( p - > symbol_rate < fe - > ops . info . symbol_rate_min )
| | ( p - > symbol_rate > fe - > ops . info . symbol_rate_max ) )
2005-04-16 15:20:36 -07:00
return - EINVAL ;
2012-10-27 16:14:01 -03:00
if ( ( ( int ) p - > fec_inner < FEC_NONE )
2011-12-26 13:50:05 -03:00
| | ( p - > fec_inner > FEC_AUTO ) )
2005-04-16 15:20:36 -07:00
return - EINVAL ;
2011-12-26 13:50:05 -03:00
if ( ( p - > fec_inner = = FEC_4_5 )
| | ( p - > fec_inner = = FEC_8_9 ) )
2005-04-16 15:20:36 -07:00
return - EINVAL ;
switch ( state - > id ) {
case ID_VP310 :
2007-12-21 08:56:44 -03:00
/* For now we will do this only for the VP310.
* It should be better for the mt312 as well ,
* but tuning will be slower . ACCJr 09 / 29 / 03
*/
2006-01-10 00:09:16 +03:00
ret = mt312_readreg ( state , CONFIG , & config_val ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2011-12-26 13:50:05 -03:00
if ( p - > symbol_rate > = 30000000 ) {
2007-12-21 08:56:44 -03:00
/* Note that 30MS/s should use 90MHz */
2008-04-12 15:04:48 -03:00
if ( state - > freq_mult = = 6 ) {
2007-12-21 08:56:44 -03:00
/* We are running 60MHz */
2008-04-12 15:04:48 -03:00
state - > freq_mult = 9 ;
2007-12-24 07:12:55 -03:00
ret = mt312_initfe ( fe ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
}
2007-12-21 08:56:44 -03:00
} else {
2008-04-12 15:04:48 -03:00
if ( state - > freq_mult = = 9 ) {
2007-12-21 08:56:44 -03:00
/* We are running 90MHz */
2008-04-12 15:04:48 -03:00
state - > freq_mult = 6 ;
2007-12-24 07:12:55 -03:00
ret = mt312_initfe ( fe ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
}
}
break ;
case ID_MT312 :
2008-04-12 15:04:49 -03:00
case ID_ZL10313 :
2005-04-16 15:20:36 -07:00
break ;
default :
return - EINVAL ;
}
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 ) ;
2007-12-21 08:56:44 -03:00
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
2006-04-18 17:47:09 -03:00
}
2005-04-16 15:20:36 -07:00
/* sr = (u16)(sr * 256.0 / 1000000.0) */
2019-10-09 11:55:22 -03:00
sr = DIV_ROUND_CLOSEST ( p - > symbol_rate * 4 , 15625 ) ;
2005-04-16 15:20:36 -07:00
/* SYM_RATE */
buf [ 0 ] = ( sr > > 8 ) & 0x3f ;
buf [ 1 ] = ( sr > > 0 ) & 0xff ;
/* VIT_MODE */
2011-12-26 13:50:05 -03:00
buf [ 2 ] = inv_tab [ p - > inversion ] | fec_tab [ p - > fec_inner ] ;
2005-04-16 15:20:36 -07:00
/* QPSK_CTRL */
buf [ 3 ] = 0x40 ; /* swap I and Q before QPSK demodulation */
2011-12-26 13:50:05 -03:00
if ( p - > symbol_rate < 10000000 )
2005-04-16 15:20:36 -07:00
buf [ 3 ] | = 0x04 ; /* use afc mode */
/* GO */
buf [ 4 ] = 0x01 ;
2007-12-24 07:12:55 -03:00
ret = mt312_write ( state , SYM_RATE_H , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2018-12-21 02:07:20 -05:00
ret = mt312_reset ( state , 0 ) ;
if ( ret < 0 )
return ret ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2016-02-04 12:58:30 -02:00
static int mt312_get_frontend ( struct dvb_frontend * fe ,
struct dtv_frontend_properties * p )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
2007-12-24 07:12:55 -03:00
ret = mt312_get_inversion ( state , & p - > inversion ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2011-12-26 13:50:05 -03:00
ret = mt312_get_symbol_rate ( state , & p - > symbol_rate ) ;
2007-12-24 07:12:55 -03:00
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2011-12-26 13:50:05 -03:00
ret = mt312_get_code_rate ( state , & p - > fec_inner ) ;
2007-12-24 07:12:55 -03:00
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_i2c_gate_ctrl ( struct dvb_frontend * fe , int enable )
2006-04-18 17:47:09 -03:00
{
2007-12-21 08:56:44 -03:00
struct mt312_state * state = fe - > demodulator_priv ;
2006-04-18 17:47:09 -03:00
2008-04-12 15:04:49 -03:00
u8 val = 0x00 ;
int ret ;
switch ( state - > id ) {
case ID_ZL10313 :
ret = mt312_readreg ( state , GPP_CTRL , & val ) ;
if ( ret < 0 )
goto error ;
2011-03-30 22:57:33 -03:00
/* preserve this bit to not accidentally shutdown ADC */
2008-04-12 15:04:49 -03:00
val & = 0x80 ;
break ;
2006-04-18 17:47:09 -03:00
}
2008-04-12 15:04:49 -03:00
if ( enable )
val | = 0x40 ;
else
val & = ~ 0x40 ;
ret = mt312_writereg ( state , GPP_CTRL , val ) ;
error :
return ret ;
2006-04-18 17:47:09 -03:00
}
2007-12-21 08:56:44 -03:00
static int mt312_sleep ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2005-05-16 21:54:31 -07:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
int ret ;
u8 config ;
/* reset all registers to defaults */
2007-12-24 07:12:55 -03:00
ret = mt312_reset ( state , 1 ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
2008-04-12 15:04:49 -03:00
if ( state - > id = = ID_ZL10313 ) {
/* reset ADC */
ret = mt312_writereg ( state , GPP_CTRL , 0x00 ) ;
if ( ret < 0 )
return ret ;
/* full shutdown of ADCs, mpeg bus tristated */
ret = mt312_writereg ( state , HW_CTRL , 0x0d ) ;
if ( ret < 0 )
return ret ;
}
2007-12-24 07:12:55 -03:00
ret = mt312_readreg ( state , CONFIG , & config ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
/* enter standby */
2007-12-24 07:12:55 -03:00
ret = mt312_writereg ( state , CONFIG , config & 0x7f ) ;
if ( ret < 0 )
2005-04-16 15:20:36 -07:00
return ret ;
return 0 ;
}
2007-12-21 08:56:44 -03:00
static int mt312_get_tune_settings ( struct dvb_frontend * fe ,
struct dvb_frontend_tune_settings * fesettings )
2005-04-16 15:20:36 -07:00
{
fesettings - > min_delay_ms = 50 ;
fesettings - > step_size = 0 ;
fesettings - > max_drift = 0 ;
return 0 ;
}
2007-12-21 08:56:44 -03:00
static void mt312_release ( struct dvb_frontend * fe )
2005-04-16 15:20:36 -07:00
{
2007-12-21 08:56:44 -03:00
struct mt312_state * state = fe - > demodulator_priv ;
2005-04-16 15:20:36 -07:00
kfree ( state ) ;
}
2008-04-12 15:04:48 -03:00
# define MT312_SYS_CLK 90000000UL /* 90 MHz */
2016-08-09 18:32:21 -03:00
static const struct dvb_frontend_ops mt312_ops = {
2011-12-26 13:50:05 -03:00
. delsys = { SYS_DVBS } ,
2005-04-16 15:20:36 -07:00
. info = {
. name = " Zarlink ???? DVB-S " ,
2018-07-05 18:59:36 -04:00
. frequency_min_hz = 950 * MHz ,
. frequency_max_hz = 2150 * MHz ,
2009-07-02 16:17:28 -03:00
/* FIXME: adjust freq to real used xtal */
2018-07-05 18:59:36 -04:00
. frequency_stepsize_hz = MT312_PLL_CLK / 128 ,
2008-04-12 15:04:48 -03:00
. symbol_rate_min = MT312_SYS_CLK / 128 , /* FIXME as above */
2005-04-16 15:20:36 -07:00
. symbol_rate_max = MT312_SYS_CLK / 2 ,
. 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_MUTE_TS |
2005-12-12 00:37:24 -08:00
FE_CAN_RECOVER
2005-04-16 15:20:36 -07:00
} ,
. release = mt312_release ,
. init = mt312_initfe ,
. sleep = mt312_sleep ,
2006-04-18 17:47:09 -03:00
. i2c_gate_ctrl = mt312_i2c_gate_ctrl ,
2005-04-16 15:20:36 -07:00
2011-12-26 13:50:05 -03:00
. set_frontend = mt312_set_frontend ,
. get_frontend = mt312_get_frontend ,
2005-04-16 15:20:36 -07:00
. get_tune_settings = mt312_get_tune_settings ,
. read_status = mt312_read_status ,
. read_ber = mt312_read_ber ,
. read_signal_strength = mt312_read_signal_strength ,
. read_snr = mt312_read_snr ,
. read_ucblocks = mt312_read_ucblocks ,
. diseqc_send_master_cmd = mt312_send_master_cmd ,
. diseqc_send_burst = mt312_send_burst ,
. set_tone = mt312_set_tone ,
. set_voltage = mt312_set_voltage ,
} ;
2008-04-30 12:21:04 -03:00
struct dvb_frontend * mt312_attach ( const struct mt312_config * config ,
2007-12-21 08:56:44 -03:00
struct i2c_adapter * i2c )
2006-02-27 00:07:49 -03:00
{
2007-12-21 08:56:44 -03:00
struct mt312_state * state = NULL ;
2006-02-27 00:07:49 -03:00
/* allocate memory for the internal state */
2009-08-10 22:51:01 -03:00
state = kzalloc ( sizeof ( struct mt312_state ) , GFP_KERNEL ) ;
2006-02-27 00:07:49 -03:00
if ( state = = NULL )
goto error ;
/* setup the state */
state - > config = config ;
state - > i2c = i2c ;
/* check if the demod is there */
if ( mt312_readreg ( state , ID , & state - > id ) < 0 )
goto error ;
2006-05-14 05:01:31 -03:00
/* create dvb_frontend */
2008-04-30 12:21:04 -03:00
memcpy ( & state - > frontend . ops , & mt312_ops ,
2007-12-21 08:56:44 -03:00
sizeof ( struct dvb_frontend_ops ) ) ;
2006-05-14 05:01:31 -03:00
state - > frontend . demodulator_priv = state ;
2006-02-27 00:07:49 -03:00
switch ( state - > id ) {
case ID_VP310 :
2018-09-10 16:20:42 -04:00
strscpy ( state - > frontend . ops . info . name , " Zarlink VP310 DVB-S " ,
sizeof ( state - > frontend . ops . info . name ) ) ;
2008-04-12 15:04:48 -03:00
state - > xtal = MT312_PLL_CLK ;
state - > freq_mult = 9 ;
2006-02-27 00:07:49 -03:00
break ;
case ID_MT312 :
2018-09-10 16:20:42 -04:00
strscpy ( state - > frontend . ops . info . name , " Zarlink MT312 DVB-S " ,
sizeof ( state - > frontend . ops . info . name ) ) ;
2008-04-12 15:04:48 -03:00
state - > xtal = MT312_PLL_CLK ;
state - > freq_mult = 6 ;
2006-02-27 00:07:49 -03:00
break ;
2008-04-12 15:04:49 -03:00
case ID_ZL10313 :
2018-09-10 16:20:42 -04:00
strscpy ( state - > frontend . ops . info . name , " Zarlink ZL10313 DVB-S " ,
sizeof ( state - > frontend . ops . info . name ) ) ;
2008-04-12 15:04:49 -03:00
state - > xtal = MT312_PLL_CLK_10_111 ;
state - > freq_mult = 9 ;
break ;
2006-02-27 00:07:49 -03:00
default :
[media] dvb-frontends: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:22 -02:00
printk ( KERN_WARNING " Only Zarlink VP310/MT312/ZL10313 are supported chips. \n " ) ;
2006-02-27 00:07:49 -03:00
goto error ;
}
return & state - > frontend ;
error :
kfree ( state ) ;
return NULL ;
}
2008-04-30 12:21:04 -03:00
EXPORT_SYMBOL ( mt312_attach ) ;
2006-02-27 00:07:49 -03:00
2005-04-16 15:20:36 -07:00
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " Turn on/off frontend debugging (default:off). " ) ;
2008-04-12 15:04:49 -03:00
MODULE_DESCRIPTION ( " Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver " ) ;
2005-04-16 15:20:36 -07:00
MODULE_AUTHOR ( " Andreas Oberritter <obi@linuxtv.org> " ) ;
2008-04-30 12:21:04 -03:00
MODULE_AUTHOR ( " Matthias Schwarzott <zzam@gentoo.org> " ) ;
2005-04-16 15:20:36 -07:00
MODULE_LICENSE ( " GPL " ) ;