mt312: Add support for zl10313 demod
cover mt312: Add support for zl10313 demod
mt312: Cleanup driver and add support for zl10313.
These patches add support for the Zarlink zl10313 demod to mt312 driver. This chip is used at least on Avermedia A700 DVB-S and Compro VideoMate S300/S350 DVB-S cards.
Regards
Matthias
Signature · 4 lines
_______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
PATCH 1/5 mt312: Cleanup buffer variables of read/write functions
Change type of buffer variables from void* to u8* to save some casts.
linux/drivers/media/dvb/frontends/mt312.c +6 -6
@@ -58,7 +58,7 @@ static int debug;#define MT312_PLL_CLK 10000000UL/* 10 MHz */ static int mt312_read (struct mt312_state *state,const enum mt312_reg_addr reg, -void *buf,const size_t count) +u8 *buf,const size_t count) {int ret;struct i2c_msg msg[2 ];
@@ -84,7 +84,7 @@ static int mt312_read(struct mt312_stateint i;dprintk ("R(%d):" , reg &0x7f );for (i =0 ; i < count; i++) -printk (" %02x" , ((const u8 *) buf)[i]); +printk (" %02x" , buf[i]);printk ("\n" ); }
@@ -92,7 +92,7 @@ static int mt312_read(struct mt312_state }static int mt312_write (struct mt312_state *state,const enum mt312_reg_addr reg, -const void *src,const size_t count) +const u8 *src,const size_t count) {int ret;u8 buf[count +1 ];
@@ -102,7 +102,7 @@ static int mt312_write(struct mt312_statint i;dprintk ("W(%d):" , reg &0x7f );for (i =0 ; i < count; i++) -printk (" %02x" , ((const u8 *) src)[i]); +printk (" %02x" , src[i]);printk ("\n" ); }
@@ -463,7 +463,7 @@ static int mt312_read_snr(struct dvb_froint ret;u8 buf[2 ]; - ret =mt312_read (state,M_SNR_H , &buf,sizeof (buf)); + ret =mt312_read (state,M_SNR_H , buf,sizeof (buf));if (ret <0 )return ret;
@@ -478,7 +478,7 @@ static int mt312_read_ucblocks(struct dvint ret;u8 buf[2 ]; - ret =mt312_read (state,RS_UBC_H , &buf,sizeof (buf)); + ret =mt312_read (state,RS_UBC_H , buf,sizeof (buf));if (ret <0 )return ret;
Signature · 4 lines
_______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
PATCH 2/5 mt312: Fix diseqc
In reply to Matthias SchwarzottCorrect the frequency of the emitted diseqc signal to 22kHz. Adds sleep(100) to wait for message to be transmitted.
For now the only user of mt312 is b2c2-flexcop, and it does overwrite all diseqc related functions with own code.
linux/drivers/media/dvb/frontends/mt312.c +4 -1
@@ -270,7 +270,7 @@ static int mt312_initfe(struct dvb_front MT312_SYS_CLK) * 2, 1000000);/* DISEQC_RATIO */ - buf[1 ] =mt312_div (MT312_PLL_CLK ,15000 *4 ); + buf[1 ] =mt312_div (MT312_PLL_CLK ,22000 *4 ); ret =mt312_write (state,SYS_CLK , buf,sizeof (buf));if (ret <0 )
@@ -323,6 +323,9 @@ static int mt312_send_master_cmd(structif (ret <0 )return ret; +/* is there a better way to wait for message to be transmitted */ +msleep (100 ); +/* set DISEQC_MODE[2:0] to zero if a return message is expected */ if (c->msg[0 ] &0x02 ) { ret =mt312_writereg (state,DISEQC_MODE , (diseqc_mode &0x40 ));
Signature · 4 lines
_______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
PATCH 3/5 mt312: Supports different xtal frequencies
In reply to Matthias SchwarzottDo not hardcode xtal frequency but allow different values for future zl10313 support.
linux/drivers/media/dvb/frontends/mt312.c +17 -16
@@ -43,7 +43,8 @@ struct mt312_state {struct dvb_frontend frontend;u8 id; -u8 frequency; +unsigned long xtal; +u8 freq_mult; };static int debug;
@@ -53,8 +54,6 @@ static int debug;printk (KERN_DEBUG "mt312: " args); \ } while (0) -#define MT312_SYS_CLK 90000000UL/* 90 MHz */ -#define MT312_LPOWER_SYS_CLK 60000000UL/* 60 MHz */ #define MT312_PLL_CLK 10000000UL/* 10 MHz */ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
@@ -209,7 +208,7 @@ static int mt312_get_symbol_rate(structdprintk ("sym_rat_op=%d dec_ratio=%d\n" , sym_rat_op, dec_ratio);dprintk ("*sr(manual) = %lu\n" , - (((MT312_PLL_CLK *8192 ) / (sym_rat_op +8192 )) * + (((state->xtal *8192 ) / (sym_rat_op +8192 )) *2 ) - dec_ratio); }
@@ -242,7 +241,7 @@ static int mt312_initfe(struct dvb_front/* wake up */ ret =mt312_writereg (state,CONFIG , - (state->frequency ==60 ?0x88 :0x8c )); + (state->freq_mult ==6 ?0x88 :0x8c ));if (ret <0 )return ret;
@@ -266,11 +265,10 @@ static int mt312_initfe(struct dvb_front }/* SYS_CLK */ - buf[0 ] =mt312_div ((state->frequency ==60 ?MT312_LPOWER_SYS_CLK : -MT312_SYS_CLK ) *2 ,1000000 ); + buf[0 ] =mt312_div (state->xtal * state->freq_mult *2 ,1000000 );/* DISEQC_RATIO */ - buf[1 ] =mt312_div (MT312_PLL_CLK ,22000 *4 ); + buf[1 ] =mt312_div (state->xtal,22000 *4 ); ret =mt312_write (state,SYS_CLK , buf,sizeof (buf));if (ret <0 )
@@ -535,17 +533,17 @@ static int mt312_set_frontend(struct dvbreturn ret;if (p->u.qpsk.symbol_rate >=30000000 ) {/* Note that 30MS/s should use 90MHz */ -if ((config_val &0x0c ) ==0x08 ) { +if (state->freq_mult ==6 ) {/* We are running 60MHz */ - state->frequency =90 ; + state->freq_mult =9 ; ret =mt312_initfe (fe);if (ret <0 )return ret; } }else { -if ((config_val &0x0c ) ==0x0C ) { +if (state->freq_mult ==9 ) {/* We are running 90MHz */ - state->frequency =60 ; + state->freq_mult =6 ; ret =mt312_initfe (fe);if (ret <0 )return ret;
@@ -664,6 +662,7 @@ static void mt312_release(struct dvb_frokfree (state); } +#define MT312_SYS_CLK 90000000UL/* 90 MHz */ static struct dvb_frontend_ops vp310_mt312_ops = { .info = {
@@ -671,8 +670,8 @@ static struct dvb_frontend_ops vp310_mt3 .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, - .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, - .symbol_rate_min = MT312_SYS_CLK / 128, + .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */ + .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */ .symbol_rate_max = MT312_SYS_CLK / 2, .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
@@ -729,11 +728,13 @@ struct dvb_frontend *vp310_mt312_attach(switch (state->id) {case ID_VP310 :strcpy (state->frontend.ops.info.name,"Zarlink VP310 DVB-S" ); - state->frequency =90 ; + state->xtal =MT312_PLL_CLK ; + state->freq_mult =9 ;break ;case ID_MT312 :strcpy (state->frontend.ops.info.name,"Zarlink MT312 DVB-S" ); - state->frequency =60 ; + state->xtal =MT312_PLL_CLK ; + state->freq_mult =6 ;break ;default : printk(KERN_WARNING "Only Zarlink VP310/MT312"
Signature · 4 lines
_______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
PATCH 4/5 mt312: Add support for zl10313 demod
In reply to Matthias SchwarzottAdd zl10313 support to mt312 driver.
zl10313 uses 10.111MHz xtal.
linux/drivers/media/dvb/frontends/mt312.c +82 -8
@@ -1,7 +1,8 @@/* -Driver for Zarlink VP310/MT312 Satellite Channel Decoder +Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder Copyright (C) 2003 Andreas Oberritter <[email protected]> +Copyright (C) 2008 Matthias Schwarzott <[email protected]> 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
@@ -55,6 +56,7 @@ static int debug; } while (0)#define MT312_PLL_CLK 10000000UL/* 10 MHz */ +#define MT312_PLL_CLK_10_111 10111000UL/* 10.111 MHz */ static int mt312_read (struct mt312_state *state,const enum mt312_reg_addr reg,u8 *buf,const size_t count)
@@ -264,6 +266,32 @@ static int mt312_initfe(struct dvb_frontreturn ret; } +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 ; + } +/* SYS_CLK */ buf[0 ] =mt312_div (state->xtal * state->freq_mult *2 ,1000000 );
@@ -278,7 +306,17 @@ static int mt312_initfe(struct dvb_frontif (ret <0 )return ret; - ret =mt312_writereg (state,OP_CTRL ,0x53 ); +/* 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 ]);if (ret <0 )return ret;
@@ -552,6 +590,7 @@ static int mt312_set_frontend(struct dvbbreak ;case ID_MT312 : +case ID_ZL10313 :break ;default :
@@ -617,11 +656,29 @@ static int mt312_i2c_gate_ctrl(struct dv {struct mt312_state *state = fe->demodulator_priv; -if (enable) { -return mt312_writereg (state,GPP_CTRL ,0x40 ); - }else { -return mt312_writereg (state,GPP_CTRL ,0x00 ); +u8 val =0x00 ; +int ret; + +switch (state->id) { +case ID_ZL10313 : + ret =mt312_readreg (state,GPP_CTRL , &val); +if (ret <0 ) + goto error; + +/* preserve this bit to not accidently shutdown ADC */ + val &=0x80 ; +break ; } + +if (enable) + val |=0x40 ; +else + val &= ~0x40 ; + + ret =mt312_writereg (state,GPP_CTRL , val); + +error: +return ret; }static int mt312_sleep (struct dvb_frontend *fe)
@@ -635,6 +692,18 @@ static int mt312_sleep(struct dvb_fronteif (ret <0 )return ret; +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; + } + ret =mt312_readreg (state,CONFIG , &config);if (ret <0 )return ret;
@@ -736,8 +805,13 @@ struct dvb_frontend *vp310_mt312_attach( state->xtal =MT312_PLL_CLK ; state->freq_mult =6 ;break ; +case ID_ZL10313 : +strcpy (state->frontend.ops.info.name,"Zarlink ZL10313 DVB-S" ); + state->xtal =MT312_PLL_CLK_10_111 ; + state->freq_mult =9 ; +break ;default : -printk (KERN_WARNING "Only Zarlink VP310/MT312" +printk (KERN_WARNING "Only Zarlink VP310/MT312/ZL10313" " are supported chips.\n" ); goto error; }
@@ -753,7 +827,7 @@ EXPORT_SYMBOL(vp310_mt312_attach);module_param (debug, int,0644 );MODULE_PARM_DESC (debug,"Turn on/off frontend debugging (default:off)." ); -MODULE_DESCRIPTION ("Zarlink VP310/MT312 DVB-S Demodulator driver" ); +MODULE_DESCRIPTION ("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver" );MODULE_AUTHOR ("Andreas Oberritter <[email protected]>" );MODULE_LICENSE ("GPL" );
linux/drivers/media/dvb/frontends/mt312_priv.h +4 -1
@@ -110,6 +110,8 @@ enum mt312_reg_addr {VIT_ERRPER_H =83 ,VIT_ERRPER_M =84 ,VIT_ERRPER_L =85 , +HW_CTRL =84 ,/* ZL10313 only */ +MPEG_CTRL =85 ,/* ZL10313 only */ VIT_SETUP =86 ,VIT_REF0 =87 , VIT_REF1 = 88,
@@ -156,7 +158,8 @@ enum mt312_reg_addr {enum mt312_model_id {ID_VP310 =1 , -ID_MT312 =3 +ID_MT312 =3 , +ID_ZL10313 =5 , };#endif /* DVB_FRONTENDS_MT312_PRIV */
Signature · 4 lines
_______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
PATCH 5/5 mt312: add attach-time setting to invert lnb-voltage
In reply to Matthias SchwarzottAdd a setting to config struct for inversion of lnb-voltage. Needed for support of Avermedia A700 cards.
linux/drivers/media/dvb/frontends/mt312.c +6 -1
@@ -422,11 +422,16 @@ static int mt312_set_voltage(struct dvb_ {struct mt312_state *state = fe->demodulator_priv;const u8 volt_tab[3 ] = {0x00 ,0x40 ,0x00 }; +u8 val;if (v >SEC_VOLTAGE_OFF )return -EINVAL ; -return mt312_writereg (state,DISEQC_MODE , volt_tab[v]); + val = volt_tab[v]; +if (state->config->voltage_inverted) + val ^=0x40 ; + +return mt312_writereg (state,DISEQC_MODE , val); }static int mt312_read_status (struct dvb_frontend *fe,fe_status_t *s)
linux/drivers/media/dvb/frontends/mt312.h +3 -0
@@ -31,6 +31,9 @@struct mt312_config {/* the demodulator's i2c address */ u8 demod_address; + +/* inverted voltage setting */ +int voltage_inverted:1 ; };#if defined(CONFIG_DVB_MT312 ) || (defined(CONFIG_DVB_MT312_MODULE ) && defined(MODULE ))
Signature · 4 lines
_______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
Quoted 6 lines · Matthias Schwarzott
mt312: Cleanup driver and add support for zl10313.
These patches add support for the Zarlink zl10313 demod to mt312 driver. This chip is used at least on Avermedia A700 DVB-S and Compro VideoMate S300/S350 DVB-S cards.
Hi Jan!
Could you please try to use this driver with your Compro card.
Regards
Matthias
Signature · 6 lines
Matthias Schwarzott (zzam) _______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
Hi Matthias,
It still works. I combined your zl10313 modulator patch with my earlier zl10039 frontend patch. The additional modifications necesary are in (see previous patch):
~/schwarzottv4l/v4l-dvb $ hg status
M linux/drivers/media/dvb/frontends/Kconfig M linux/drivers/media/dvb/frontends/Makefile M linux/drivers/media/video/saa7134/Kconfig M linux/drivers/media/video/saa7134/saa7134-cards.c M linux/drivers/media/video/saa7134/saa7134-dvb.c M linux/drivers/media/video/saa7134/saa7134.h A linux/drivers/media/dvb/frontends/zl10039.c A linux/drivers/media/dvb/frontends/zl10039.h A linux/drivers/media/dvb/frontends/zl10039_priv.h
To keep it simple I omitted the previous remote control code.
Regards
JD
----- Original Message -----
From: "Matthias Schwarzott" <[email protected]>
To: "Jan D. Louw" <[email protected]>
Cc: <[email protected]>
Sent: Saturday, April 12, 2008 5:37 PM
Subject: Re: [linux-dvb] [patch 0/5] mt312: Add support for zl10313 demod
Quoted 7 lines · Matthias Schwarzott
Quoted 6 lines
mt312: Cleanup driver and add support for zl10313.
These patches add support for the Zarlink zl10313 demod to mt312 driver. This chip is used at least on Avermedia A700 DVB-S and Compro VideoMate S300/S350 DVB-S cards.
Quoted 9 lines
Hi Jan!
Could you please try to use this driver with your Compro card.
Regards
MatthiasSignature · 1 line
Matthias Schwarzott (zzam)
_______________________________________________
linux-dvb mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
A message that is not in the archive (sent off-list or not yet received): 000a01c8a7b7$5cc2c060$0500000a@Core2Duo
Quoted 17 lines · Jan Louw
Hi Matthias,
It still works. I combined your zl10313 modulator patch with my earlier zl10039 frontend patch. The additional modifications necesary are in (see previous patch):
~/schwarzottv4l/v4l-dvb $ hg status
M linux/drivers/media/dvb/frontends/Kconfig M linux/drivers/media/dvb/frontends/Makefile M linux/drivers/media/video/saa7134/Kconfig Mlinux/drivers/media/video/saa7134/saa7134-cards.cMlinux/drivers/media/video/saa7134/saa7134-dvb.cMlinux/drivers/media/video/saa7134/saa7134.hAlinux/drivers/media/dvb/frontends/zl10039.cAlinux/drivers/media/dvb/frontends/zl10039.hAlinux/drivers/media/dvb/frontends/zl10039_priv.h
Quoted 2 lines
To keep it simple I omitted the previous remote control code.
As you see here my zl10036 driver seems to work to some point:
http://thread.gmane.org/gmane.linux.drivers.dvb/41015/focus=41303
Could you please mail your current driver for zl10039. Maybe it is worth merging both.
Regards
Matthias
_______________________________________________
linux-dvb mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
Quoted 20 lines · On Sunday 27 April 2008 05:51:30 Matthias Schwarzott wrote:
Quoted 17 lines · Jan Louw
Hi Matthias,
It still works. I combined your zl10313 modulator patch with my earlier zl10039 frontend patch. The additional modifications necesary are in (see previous patch):
~/schwarzottv4l/v4l-dvb $ hg status
M linux/drivers/media/dvb/frontends/Kconfig M linux/drivers/media/dvb/frontends/Makefile M linux/drivers/media/video/saa7134/Kconfig Mlinux/drivers/media/video/saa7134/saa7134-cards.cMlinux/drivers/media/video/saa7134/saa7134-dvb.cMlinux/drivers/media/video/saa7134/saa7134.hAlinux/drivers/media/dvb/frontends/zl10039.cAlinux/drivers/media/dvb/frontends/zl10039.hAlinux/drivers/media/dvb/frontends/zl10039_priv.hQuoted 1 line
To keep it simple I omitted the previous remote control code.
Quoted 8 lines
As you see here my zl10036 driver seems to work to some point:
http://thread.gmane.org/gmane.linux.drivers.dvb/41015/focus=41303Could you please mail your current driver for zl10039. Maybe it is worth merging both.
Regards
Matthias
Hi Matthias,
Here's the zl10039 driver. With the zl10039 I did not bother with offsets or gains - even the weak channels lock stable :-)
I used a constant bandwidth resolution of 200KHz (reference divider of 10) and a PLL frequency divider of 80.
Regards
JD
/*
* Driver for Zarlink ZL10039 DVB-S tuner
*
* Copyright 2007 Jan Dani�l Louw <[email protected]> *
* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
#include "zl10039.h"
#include "zl10039_priv.h"
static int zl10039_read(const struct zl10039_state *state,
const enum zl10039_reg_addr reg, u8 *buf,
const size_t count)
{
struct i2c_msg msg[2];
u8 regbuf[1] = { reg };
int i;
io_printk("%s\n", __FUNCTION__);
/* Write register address */
msg[0].addr = state->config.tuner_address;
msg[0].flags = 0;
msg[0].buf = regbuf;
msg[0].len = 1;
/* Read count bytes */
msg[1].addr = state->config.tuner_address;
msg[1].flags = I2C_M_RD;
msg[1].buf = buf;
msg[1].len = count;
if (i2c_transfer(state->i2c, msg, 2) != 2) {
eprintk("%s: i2c read error\n", __FUNCTION__);
return -EREMOTEIO;
}
for (i = 0; i < count; i++) {
io_printk("R[%s] = 0x%x\n", zl10039_reg_names[reg + i], buf[i]);
}
return 0; /* Success */
}static int zl10039_write(struct zl10039_state *state,
const enum zl10039_reg_addr reg, const u8 *src, const size_t count)
{
u8 buf[count + 1];
struct i2c_msg msg;
int i;
io_printk("%s\n", __FUNCTION__);
for (i = 0; i < count; i++) {
io_printk("W[%s] = 0x%x\n", zl10039_reg_names[reg + i], src[i]);
}
/* Write register address and data in one go */
buf[0] = reg;
memcpy(&buf[1], src, count);
msg.addr = state->config.tuner_address;
msg.flags = 0;
msg.buf = buf;
msg.len = count + 1;
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
eprintk("%s: i2c write error\n", __FUNCTION__);
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)
{
return zl10039_write(state, reg, &val, 1);
}static int zl10039_init(struct dvb_frontend *fe)
{
struct zl10039_state *state = fe->tuner_priv;
int ret;
trace_printk("%s\n", __FUNCTION__);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
/* Reset logic */
ret = zl10039_writereg(state, GENERAL, 0x40);
if (ret < 0) {
eprintk("Note: i2c write error normal when resetting the "
"tuner\n");
}
/* Wake up */
ret = zl10039_writereg(state, GENERAL, 0x01);
if (ret < 0) {
eprintk("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;
trace_printk("%s\n", __FUNCTION__);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
ret = zl10039_writereg(state, GENERAL, 0x80);
if (ret < 0) {
eprintk("Tuner sleep failed\n");
return ret;
}
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
}static int zl10039_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
struct zl10039_state *state = fe->tuner_priv;
u8 buf[6];
u8 bf;
u32 fbw;
u32 div;
int ret;
trace_printk("%s\n", __FUNCTION__);
params_printk("Set frequency = %d, symbol rate = %d\n",
params->frequency, params->u.qpsk.symbol_rate);
/* Assumed 10.111 MHz crystal oscillator */
/* Cancelled num/den 80 to prevent overflow */
div = (params->frequency * 1000) / 126387;
fbw = (params->u.qpsk.symbol_rate * 27) / 32000;
/* 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;
zl10039_dump_registers(state);
/* Close i2c gate */
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
error:
eprintk("Error setting tuner\n");
return ret;
}static struct dvb_tuner_ops zl10039_ops;
struct dvb_frontend * zl10039_attach(struct dvb_frontend *fe,
const struct zl10039_config *config, struct i2c_adapter *i2c)
{
struct zl10039_state *state = NULL;
trace_printk("%s\n", __FUNCTION__);
state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL);
if (state == NULL) goto error;
state->i2c = i2c;
state->config.tuner_address = config->tuner_address;
/* 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:
strcpy(fe->ops.tuner_ops.info.name,
"Zarlink ZL10039 DVB-S tuner");
break;
default:
eprintk("Chip ID does not match a known type\n");
goto error;
}
memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops));
fe->tuner_priv = state;
iprintk("Tuner attached @ i2c address 0x%02x\n", config->tuner_address);
return fe;
error:
kfree(state);
return NULL;
}static int zl10039_release(struct dvb_frontend *fe)
{
struct zl10039_state *state = fe->tuner_priv;
trace_printk("%s\n", __FUNCTION__);
kfree(state);
fe->tuner_priv = NULL;
return 0;
}static struct dvb_tuner_ops zl10039_ops = {
.release = zl10039_release,
.init = zl10039_init,
.sleep = zl10039_sleep,
.set_params = zl10039_set_params,
};EXPORT_SYMBOL(zl10039_attach);
MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver"); MODULE_AUTHOR("Jan Dani�l Louw <[email protected]>"); MODULE_LICENSE("GPL");
/*
Driver for Zarlink ZL10039 DVB-S tuner
Copyright (C) 2007 Jan Dani�l Louw <[email protected]>
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef ZL10039_H
#define ZL10039_H
struct zl10039_config
{
/* tuner's i2c address */
u8 tuner_address;
};#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \ && defined(MODULE)) struct dvb_frontend * zl10039_attach(struct dvb_frontend *fe, const struct zl10039_config *config, struct i2c_adapter *i2c);
#else
static inline struct dvb_frontend * zl10039_attach(struct dvb_frontend *fe,
const struct zl10039_config *config, struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}#endif /* CONFIG_DVB_ZL10039 */
#endif /* ZL10039_H */
/*
* Driver for Zarlink ZL10039 DVB-S tuner
*
* Copyright 2007 Jan Dani�l Louw <[email protected]> *
* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
*/
#ifndef DVB_FRONTENDS_ZL10039_PRIV
#define DVB_FRONTENDS_ZL10039_PRIV
/* Trace function calls */
#define DEBUG_CALL_TRACE 0
/* Trace read/write function calls - information overload */
#define DEBUG_IO_TRACE 0
/* Print register values at critical points */
#define DEBUG_DUMP_REGISTERS 0
/* Print important params passed to functions */
#define DEBUG_PRINT_PARAMS 0
#if DEBUG_CALL_TRACE #define trace_printk(args...) printk(KERN_DEBUG "tuner: zl10039: " args) #else #define trace_printk(args...)
#endif
#if DEBUG_IO_TRACE #define io_printk(args...) printk(KERN_DEBUG "tuner: zl10039: " args) #else #define io_printk(args...)
#endif
#if DEBUG_PRINT_PARAMS #define params_printk(args...) printk(KERN_DEBUG "tuner: zl10039: " \ args) #else #define params_printk(args...)
#endif
#define eprintk(args...) printk(KERN_ERR "tuner: zl10039: " args) #define iprintk(args...) printk(KERN_INFO "tuner: zl10039: " args)
enum zl10039_model_id {
ID_ZL10039 = 1
};struct zl10039_state {
struct i2c_adapter *i2c;
struct zl10039_config config;
u8 id;
};enum zl10039_reg_addr {
PLL0 = 0,
PLL1,
PLL2,
PLL3,
RFFE,
BASE0,
BASE1,
BASE2,
LO0,
LO1,
LO2,
LO3,
LO4,
LO5,
LO6,
GENERAL
};#if DEBUG_DUMP_REGISTERS || DEBUG_IO_TRACE
static const char *zl10039_reg_names[] = {
"PLL_0", "PLL_1", "PLL_2", "PLL_3",
"RF_FRONT_END", "BASE_BAND_0", "BASE_BAND_1", "BASE_BAND_2",
"LOCAL_OSC_0", "LOCAL_OSC_1", "LOCAL_OSC_2", "LOCAL_OSC_3",
"LOCAL_OSC_4", "LOCAL_OSC_5", "LOCAL_OSC_6", "GENERAL"
};#endif
#if DEBUG_DUMP_REGISTERS
static int zl10039_read(const struct zl10039_state *state,
const enum zl10039_reg_addr reg, u8 *buf, const size_t count);
static void zl10039_dump_registers(const struct zl10039_state *state)
{
u8 buf[16];
int ret;
u8 reg;
trace_printk("%s\n", __FUNCTION__);
ret = zl10039_read(state, PLL0, buf, sizeof(buf));
if (ret < 0) return;
for (reg = PLL0; reg <= GENERAL; reg += 4) {
printk(KERN_DEBUG "%03x: [%02x %13s] [%02x %13s] [%02x %13s] "
"[%02x %13s]\n", reg, buf[reg], zl10039_reg_names[reg],
buf[reg+1], zl10039_reg_names[reg+1], buf[reg+2],
zl10039_reg_names[reg+2], buf[reg+3],
zl10039_reg_names[reg+3]);
}
}#else
static inline void zl10039_dump_registers(const struct zl10039_state *state) {} #endif /* DEBUG_DUMP_REGISTERS */
#endif /* DVB_FRONTENDS_ZL10039_PRIV */
_______________________________________________
linux-dvb mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb