2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2009-06-20 16:51:48 +04:00
/*
* Driver for Zarlink ZL10039 DVB - S tuner
*
* Copyright 2007 Jan D . Louw < jd . louw @ mweb . co . za >
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/string.h>
# include <linux/slab.h>
# include <linux/dvb/frontend.h>
2017-12-28 21:03:51 +03:00
# include <media/dvb_frontend.h>
2009-06-20 16:51:48 +04:00
# include "zl10039.h"
static int debug ;
2013-11-02 12:05:18 +04:00
/* Max transfer size done by I2C transfer functions */
# define MAX_XFER_SIZE 64
2009-06-20 16:51:48 +04:00
# define dprintk(args...) \
do { \
if ( debug ) \
printk ( KERN_DEBUG args ) ; \
} while ( 0 )
enum zl10039_model_id {
ID_ZL10039 = 1
} ;
struct zl10039_state {
struct i2c_adapter * i2c ;
u8 i2c_addr ;
u8 id ;
} ;
enum zl10039_reg_addr {
PLL0 = 0 ,
PLL1 ,
PLL2 ,
PLL3 ,
RFFE ,
BASE0 ,
BASE1 ,
BASE2 ,
LO0 ,
LO1 ,
LO2 ,
LO3 ,
LO4 ,
LO5 ,
LO6 ,
GENERAL
} ;
static int zl10039_read ( const struct zl10039_state * state ,
const enum zl10039_reg_addr reg , u8 * buf ,
const size_t count )
{
u8 regbuf [ ] = { reg } ;
struct i2c_msg msg [ ] = {
{ /* Write register address */
. addr = state - > i2c_addr ,
. flags = 0 ,
. buf = regbuf ,
. len = 1 ,
} , { /* Read count bytes */
. addr = state - > i2c_addr ,
. flags = I2C_M_RD ,
. buf = buf ,
. len = count ,
} ,
} ;
dprintk ( " %s \n " , __func__ ) ;
if ( i2c_transfer ( state - > i2c , msg , 2 ) ! = 2 ) {
dprintk ( " %s: i2c read error \n " , __func__ ) ;
return - EREMOTEIO ;
}
return 0 ; /* Success */
}
static int zl10039_write ( struct zl10039_state * state ,
const enum zl10039_reg_addr reg , const u8 * src ,
const size_t count )
{
2013-11-02 12:05:18 +04:00
u8 buf [ MAX_XFER_SIZE ] ;
2009-06-20 16:51:48 +04:00
struct i2c_msg msg = {
. addr = state - > i2c_addr ,
. flags = 0 ,
. buf = buf ,
. len = count + 1 ,
} ;
2013-11-02 12:05:18 +04:00
if ( 1 + count > sizeof ( buf ) ) {
printk ( KERN_WARNING
2014-09-25 03:35:12 +04:00
" %s: i2c wr reg=%04x: len=%zu is too big! \n " ,
2013-11-02 12:05:18 +04:00
KBUILD_MODNAME , reg , count ) ;
return - EINVAL ;
}
2009-06-20 16:51:48 +04:00
dprintk ( " %s \n " , __func__ ) ;
/* Write register address and data in one go */
buf [ 0 ] = reg ;
memcpy ( & buf [ 1 ] , src , count ) ;
if ( i2c_transfer ( state - > i2c , & msg , 1 ) ! = 1 ) {
dprintk ( " %s: i2c write error \n " , __func__ ) ;
return - EREMOTEIO ;
}
return 0 ; /* Success */
}
static inline int zl10039_readreg ( struct zl10039_state * state ,
const enum zl10039_reg_addr reg , u8 * val )
{
return zl10039_read ( state , reg , val , 1 ) ;
}
static inline int zl10039_writereg ( struct zl10039_state * state ,
const enum zl10039_reg_addr reg ,
const u8 val )
{
2017-11-30 19:55:46 +03:00
const u8 tmp = val ; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
return zl10039_write ( state , reg , & tmp , 1 ) ;
2009-06-20 16:51:48 +04:00
}
static int zl10039_init ( struct dvb_frontend * fe )
{
struct zl10039_state * state = fe - > tuner_priv ;
int ret ;
dprintk ( " %s \n " , __func__ ) ;
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
/* Reset logic */
ret = zl10039_writereg ( state , GENERAL , 0x40 ) ;
if ( ret < 0 ) {
[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 22:44:22 +03:00
dprintk ( " Note: i2c write error normal when resetting the tuner \n " ) ;
2009-06-20 16:51:48 +04:00
}
/* Wake up */
ret = zl10039_writereg ( state , GENERAL , 0x01 ) ;
if ( ret < 0 ) {
dprintk ( " Tuner power up failed \n " ) ;
return ret ;
}
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
return 0 ;
}
static int zl10039_sleep ( struct dvb_frontend * fe )
{
struct zl10039_state * state = fe - > tuner_priv ;
int ret ;
dprintk ( " %s \n " , __func__ ) ;
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
ret = zl10039_writereg ( state , GENERAL , 0x80 ) ;
if ( ret < 0 ) {
dprintk ( " Tuner sleep failed \n " ) ;
return ret ;
}
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
return 0 ;
}
2011-12-24 19:24:33 +04:00
static int zl10039_set_params ( struct dvb_frontend * fe )
2009-06-20 16:51:48 +04:00
{
2011-12-23 04:20:31 +04:00
struct dtv_frontend_properties * c = & fe - > dtv_property_cache ;
2009-06-20 16:51:48 +04:00
struct zl10039_state * state = fe - > tuner_priv ;
u8 buf [ 6 ] ;
u8 bf ;
u32 fbw ;
u32 div ;
int ret ;
dprintk ( " %s \n " , __func__ ) ;
dprintk ( " Set frequency = %d, symbol rate = %d \n " ,
2011-12-23 04:20:31 +04:00
c - > frequency , c - > symbol_rate ) ;
2009-06-20 16:51:48 +04:00
/* Assumed 10.111 MHz crystal oscillator */
/* Cancelled num/den 80 to prevent overflow */
2011-12-23 04:20:31 +04:00
div = ( c - > frequency * 1000 ) / 126387 ;
fbw = ( c - > symbol_rate * 27 ) / 32000 ;
2009-06-20 16:51:48 +04:00
/* Cancelled num/den 10 to prevent overflow */
bf = ( ( fbw * 5088 ) / 1011100 ) - 1 ;
/*PLL divider*/
buf [ 0 ] = ( div > > 8 ) & 0x7f ;
buf [ 1 ] = ( div > > 0 ) & 0xff ;
/*Reference divider*/
/* Select reference ratio of 80 */
buf [ 2 ] = 0x1D ;
/*PLL test modes*/
buf [ 3 ] = 0x40 ;
/*RF Control register*/
buf [ 4 ] = 0x6E ; /* Bypass enable */
/*Baseband filter cutoff */
buf [ 5 ] = bf ;
/* Open i2c gate */
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
/* BR = 10, Enable filter adjustment */
ret = zl10039_writereg ( state , BASE1 , 0x0A ) ;
if ( ret < 0 )
goto error ;
/* Write new config values */
ret = zl10039_write ( state , PLL0 , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
goto error ;
/* BR = 10, Disable filter adjustment */
ret = zl10039_writereg ( state , BASE1 , 0x6A ) ;
if ( ret < 0 )
goto error ;
/* Close i2c gate */
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
return 0 ;
error :
dprintk ( " Error setting tuner \n " ) ;
return ret ;
}
2016-08-10 00:32:31 +03:00
static void zl10039_release ( struct dvb_frontend * fe )
2009-06-20 16:51:48 +04:00
{
struct zl10039_state * state = fe - > tuner_priv ;
dprintk ( " %s \n " , __func__ ) ;
kfree ( state ) ;
fe - > tuner_priv = NULL ;
}
2016-09-11 17:44:12 +03:00
static const struct dvb_tuner_ops zl10039_ops = {
2009-06-20 16:51:48 +04:00
. release = zl10039_release ,
. init = zl10039_init ,
. sleep = zl10039_sleep ,
. set_params = zl10039_set_params ,
} ;
struct dvb_frontend * zl10039_attach ( struct dvb_frontend * fe ,
u8 i2c_addr , struct i2c_adapter * i2c )
{
struct zl10039_state * state = NULL ;
dprintk ( " %s \n " , __func__ ) ;
state = kmalloc ( sizeof ( struct zl10039_state ) , GFP_KERNEL ) ;
if ( state = = NULL )
goto error ;
state - > i2c = i2c ;
state - > i2c_addr = i2c_addr ;
/* Open i2c gate */
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 1 ) ;
/* check if this is a valid tuner */
if ( zl10039_readreg ( state , GENERAL , & state - > id ) < 0 ) {
/* Close i2c gate */
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
goto error ;
}
/* Close i2c gate */
if ( fe - > ops . i2c_gate_ctrl )
fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
state - > id = state - > id & 0x0f ;
switch ( state - > id ) {
case ID_ZL10039 :
2018-09-10 23:20:42 +03:00
strscpy ( fe - > ops . tuner_ops . info . name ,
" Zarlink ZL10039 DVB-S tuner " ,
sizeof ( fe - > ops . tuner_ops . info . name ) ) ;
2009-06-20 16:51:48 +04:00
break ;
default :
dprintk ( " Chip ID=%x does not match a known type \n " , state - > id ) ;
goto error ;
}
memcpy ( & fe - > ops . tuner_ops , & zl10039_ops , sizeof ( struct dvb_tuner_ops ) ) ;
fe - > tuner_priv = state ;
dprintk ( " Tuner attached @ i2c address 0x%02x \n " , i2c_addr ) ;
return fe ;
error :
kfree ( state ) ;
return NULL ;
}
EXPORT_SYMBOL ( zl10039_attach ) ;
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " Turn on/off frontend debugging (default:off). " ) ;
MODULE_DESCRIPTION ( " Zarlink ZL10039 DVB-S tuner driver " ) ;
MODULE_AUTHOR ( " Jan D. Louw <jd.louw@mweb.co.za> " ) ;
MODULE_LICENSE ( " GPL " ) ;