Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] Re: Universal STV0299/TSA5059 frontend driver



Hi Peter,

Peter Schildmann wrote:
> Hi,
> 
> here is the last version of my modified ALPS BSRU6 frontend driver
> with support for Philips SU1278/SH. The driver has an additional
> module parameter 'ftype':
> 
>    ftype=0      .....     Philips SU1278/SH
>    ftype=1      .....     ALPS_BSRU6 / LG TDQB-S00x  (not tested)

unfortunally this is a pretty bad solution if you have multiple cards 
with different stv0299 based tuner modules - you can't load the same 
module multiple times with different module parameters.

We have to implement some autoprobing as you can see it in ves1820.c.

Holger


> 
> I renamed the driver to uni_stv0299.
> 
> Peter
> 
> ------------------------------------------------------------------
> 
> /*
>     Universal driver for STV0299/TDA5059 based
>     DVB QPSK frontends
> 
>     Alps BSRU6, LG TDQB-S00x
> 
>     Copyright (C) 2001-2002 Convergence Integrated Media GmbH
> 	<ralph@convergence.de>, <holger@convergence.de>,
> 	<js@convergence.de>
>     
>     Philips SU1278/SH
> 
>     Copyright (C) 2002 by Peter Schildmann
>         <peter.schildmann@web.de>
> 
>     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/init.h>
> #include <linux/module.h>
> 
> #include "compat.h"
> #include "dvb_frontend.h"
> 
> static int debug = 0;
> #define dprintk	if (debug) printk
> 
> /* frontend types */
> #define PHILIPS_SU1278SH   0
> #define ALPS_BSRU6         1
> static int ftype = 0;
> 
> /* Master Clock = 88 MHz */
> #define M_CLK (88000000UL) 
> 
> static
> struct dvb_frontend_info uni0299_info = {
> 	name: "STV0299/TSA5059 based",
> 	type: FE_QPSK,
> 	frequency_min: 950000,
> 	frequency_max: 2150000,
> 	frequency_stepsize: 125,   /* kHz for QPSK frontends */
> 	frequency_tolerance: M_CLK/2000,
> 	symbol_rate_min: 1000000,
> 	symbol_rate_max: 45000000,
> 	symbol_rate_tolerance: 500,  /* ppm */
> 	notifier_delay: 0,
> 	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_QPSK |
> 	      FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO |
> 	      FE_CAN_CLEAN_SETUP
> };
> 
> 
> static
> u8 init_tab [] = {
>         /* clock registers */
>         0x01, 0x15,   /* K = 0, DIRCLK = 0, M = 0x15                  */
> 	0x02, 0x30,   /* STDBY = 0, VCO = 0 (ON), SERCLK = 0, P = 0   */
>                       /* f_VCO = 4MHz * 4 * (M+1) / (K+1) = 352 MHz   */
> 	0x03, 0x00,   /* auxiliary clock not used                     */
> 	0x04, 0x7d,   /* F22FR = 0x7d                                 */
> 		      /* F22 = f_VCO / 128 / 0x7d = 22 kHz            */
> 
>         /* I2C bus repeater */
> 	0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1                 */
> 
>  	/* general purpose DAC registers */
> 	0x06, 0x40,   /* DAC not used, set to high impendance mode    */
> 	0x07, 0x00,   /* DAC LSB                                      */
> 
> 	/* DiSEqC registers */
> 	0x08, 0x40,   /* DiSEqC off                                   */
> 	0x09, 0x00,   /* FIFO                                         */
> 
>         /* Input/Output configuration register */
> 	0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
> 	              /* OP0 ctl = Normal, OP0 val = 1 (18 V)         */
>                       /* Nyquist filter = 00, QPSK reverse = 0        */
>                    
>         /* AGC1 control register */
> 	0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2   */
> 
>         /* Timing loop register */
> 	0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3                  */
> 
> 	0x10, 0x3f,   // AGC2  0x3d
> 	0x11, 0x84,
> 	0x12, 0xb5,   // Lock detect: -64  Carrier freq detect:on
> 	0x13, 0xb6,   // alpha_car b:4 a:0  noise est:256ks  derot:on
> 	0x14, 0x93,   // beat carc:0 d:0 e:0xf  phase detect algo: 1
> 	0x15, 0xc9,   // lock detector threshold
> 
> 	0x16, 0x1d,   /* AGC1 integrator value                        */
> 	0x17, 0x00,
> 	0x18, 0x14,
> 	0x19, 0xf2,
> 
> 	0x1a, 0x11,
> 
> 	0x1b, 0x9c,
> 	0x1c, 0x00,
> 	0x1d, 0x00,
> 	0x1e, 0x0b,
> 	0x1f, 0x50,
> 
> 	0x20, 0x00,
> 	0x21, 0x00,
> 	0x22, 0x00,
> 	0x23, 0x00,
> 	0x24, 0xff,
> 	0x25, 0xff,
> 	0x26, 0xff,
> 
> 	0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
> 	0x29, 0x1e,  // 1/2 threshold
> 	0x2a, 0x14,  // 2/3 threshold
> 	0x2b, 0x0f,  // 3/4 threshold
> 	0x2c, 0x09,  // 5/6 threshold
> 	0x2d, 0x05,  // 7/8 threshold
> 	0x2e, 0x01,
> 
> 	0x31, 0x1f,  // test all FECs
> 
> 	0x32, 0x19,  // viterbi and synchro search
> 	0x33, 0xfc,  // rs control
> 	0x34, 0x93,  // error control
> 
> 	0x0b, 0x00,
> 	0x27, 0x00,
> 	0x2f, 0x00,
> 	0x30, 0x00,
> 	0x35, 0x00,
> 	0x36, 0x00,
> 	0x37, 0x00,
> 	0x38, 0x00,
> 	0x39, 0x00,
> 	0x3a, 0x00,
> 	0x3b, 0x00,
> 	0x3c, 0x00,
> 	0x3d, 0x00,
> 	0x3e, 0x00,
> 	0x3f, 0x00,
> 	0x40, 0x00,
> 	0x41, 0x00,
> 	0x42, 0x00,
> 	0x43, 0x00,
> 	0x44, 0x00,
> 	0x45, 0x00,
> 	0x46, 0x00,
> 	0x47, 0x00,
> 	0x48, 0x00,
> 	0x49, 0x00,
> 	0x4a, 0x00,
> 	0x4b, 0x00,
> 	0x4c, 0x00,
> 	0x4d, 0x00,
> 	0x4e, 0x00,
> 	0x4f, 0x00
> };
> 
> static
> int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
> {
> 	int ret;
> 	u8 buf [] = { reg, data };
> 	struct i2c_msg msg = { addr: 0x68, flags: 0, buf: buf, len: 2 };
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	ret = i2c->xfer (i2c, &msg, 1);
> 
> 	if (ret != 1) 
> 		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
> 			__FUNCTION__, reg, data, ret);
> 
> 	return (ret != 1) ? -1 : 0;
> }
> 
> 
> static
> u8 stv0299_readreg (struct dvb_i2c_bus *i2c, u8 reg)
> {
> 	int ret;
> 	u8 b0 [] = { reg };
> 	u8 b1 [] = { 0 };
> 	struct i2c_msg msg [] = { { addr: 0x68, flags: 0, buf: b0, len: 1 },
> 			   { addr: 0x68, flags: I2C_M_RD, buf: b1, len: 1 } };
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	ret = i2c->xfer (i2c, msg, 2);
>         
> 	if (ret != 2) 
> 		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
> 
> 	return b1[0];
> }
> 
> 
> static
> int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len)
> {
>         int ret;
>         struct i2c_msg msg [] = { { addr: 0x68, flags: 0, buf: &reg1, len: 1 },
>                            { addr: 0x68, flags: I2C_M_RD, buf: b, len: len } };
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
>         ret = i2c->xfer (i2c, msg, 2);
> 
>         if (ret != 2)
>                 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
> 
>         return ret == 2 ? 0 : -1;
> }
> 
> 
> static
> int tsa5059_write (struct dvb_i2c_bus *i2c, u8 data [4])
> {
> 	int ret;
> 	u8 rpt1 [] = { 0x05, 0xb5 };  /*  enable i2c repeater on stv0299  */
> 	u8 i2c_addr = ftype == PHILIPS_SU1278SH ? 0x60 : 0x61;   /* TSA5059 i2c-bus address */
> 	struct i2c_msg msg [] = {{ addr: 0x68,     flags: 0, buf: rpt1, len: 2 },
> 				 { addr: i2c_addr, flags: 0, buf: data, len: 4 }};
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	ret = i2c->xfer (i2c, msg, 2);
> 
> 	if (ret != 2)
> 		dprintk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret);
> 
> 	return (ret != 2) ? -1 : 0;
> }
> 
> 
> /**
>  *   set up the downconverter frequency divisor for a 
>  *   reference clock comparision frequency of 125 kHz.
>  */
> static
> int tsa5059_set_tv_freq	(struct dvb_i2c_bus *i2c, u32 freq)
> {
>         u32 div = freq / 125;
> 
> 	u8 buf[4] = { (div >> 8) & 0x7f, div & 0xff, 0x84 };
> 
> 	if (ftype == PHILIPS_SU1278SH)
> 	  /* activate f_xtal/f_comp signal output */
> 	  /* charge pump current C0/C1 = 00 */
> 	  buf[3] = 0x20;
> 	else
> 	  buf[3] = freq > 1530000 ? 0xc0 : 0xc4;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	return tsa5059_write (i2c, buf);
> }
> 
> 
> /* static */
> /* int tsa5059_read_status	(struct dvb_i2c_bus *i2c) */
> /* { */
> /* 	int ret; */
> /*         u8 rpt1 [] = { 0x05, 0xb5 }; */
> /* 	u8 stat [] = { 0 }; */
> 
> /* 	struct i2c_msg msg [] = {{ addr: 0x68, flags: 0,        buf: rpt1, len: 2 }, */
> /*                                  { addr: 0x60, flags: I2C_M_RD, buf: stat, len: 1 }}; */
> 
> /*         dprintk ("%s\n", __FUNCTION__); */
> 
> /* 	ret = i2c->xfer (i2c, msg, 2); */
> 
> /* 	if (ret != 2)  */
> /* 		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); */
> 
> /* 	return stat[0]; */
> /* } */
> 
> 
> static
> int stv0299_init (struct dvb_i2c_bus *i2c)
> {
> 	int i;
> 
> 	dprintk("stv0299: init chip\n");
> 
> 	for (i=0; i<sizeof(init_tab); i+=2)
> 		stv0299_writereg (i2c, init_tab[i], init_tab[i+1]);
> 
>         /* AGC1 reference register setup */
> 	if (ftype == PHILIPS_SU1278SH)
> 	  stv0299_writereg (i2c, 0x0f, 0xd2);  /* Iagc = Inverse, m1 = 18 */
> 	else
> 	  stv0299_writereg (i2c, 0x0f, 0x52);  /* Iagc = Normal,  m1 = 18 */
> 
> 	return 0;
> }
> 
> 
> static
> int stv0299_check_inversion (struct dvb_i2c_bus *i2c)
> {
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	if ((stv0299_readreg (i2c, 0x1b) & 0x98) != 0x98) {
> 		u8 val = stv0299_readreg (i2c, 0x0c);
> 		return stv0299_writereg (i2c, 0x0c, val ^ 0x01);
> 	}
> 
> 	return 0;
> }
> 
> 
> static
> int stv0299_set_FEC (struct dvb_i2c_bus *i2c, fe_code_rate_t fec)
> {
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	switch (fec) {
> 	case FEC_AUTO:
> 		return stv0299_writereg (i2c, 0x31, 0x1f);
> 	case FEC_1_2:
> 		return stv0299_writereg (i2c, 0x31, 0x01);
> 	case FEC_2_3:
> 		return stv0299_writereg (i2c, 0x31, 0x02);
> 	case FEC_3_4:
> 		return stv0299_writereg (i2c, 0x31, 0x04);
> 	case FEC_5_6:
> 		return stv0299_writereg (i2c, 0x31, 0x08);
> 	case FEC_7_8:
> 		return stv0299_writereg (i2c, 0x31, 0x10);
> 	default:
> 		return -EINVAL;
> 	}
> }
> 
> 
> static
> fe_code_rate_t stv0299_get_fec (struct dvb_i2c_bus *i2c)
> {
> 	static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6,
> 					     FEC_7_8, FEC_1_2 };
> 	u8 index;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	index = stv0299_readreg (i2c, 0x1b);
> 	index &= 0x7;
> 
> 	if (index > 4)
> 		return FEC_AUTO;
> 
> 	return fec_tab [index];
> }
> 
> 
> static
> int stv0299_wait_diseqc_fifo (struct dvb_i2c_bus *i2c, int timeout)
> {
> 	unsigned long start = jiffies;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	while (stv0299_readreg(i2c, 0x0a) & 1) {
> 		if (jiffies - start > timeout) {
> 			dprintk ("%s: timeout!!\n", __FUNCTION__);
> 			return -ETIMEDOUT;
> 		}
> 		current->state = TASK_INTERRUPTIBLE;
> 		schedule_timeout (1);
> 	};
> 
> 	return 0;
> }
> 
> 
> static
> int stv0299_wait_diseqc_idle (struct dvb_i2c_bus *i2c, int timeout)
> {
> 	unsigned long start = jiffies;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	while ((stv0299_readreg(i2c, 0x0a) & 3) != 2 ) {
> 		if (jiffies - start > timeout) {
> 			dprintk ("%s: timeout!!\n", __FUNCTION__);
> 			return -ETIMEDOUT;
> 		}
> 		current->state = TASK_INTERRUPTIBLE;
> 		schedule_timeout (1);
> 	};
> 
> 	return 0;
> }
> 
> 
> static
> int stv0299_send_diseqc_msg (struct dvb_i2c_bus *i2c,
> 			     struct dvb_diseqc_master_cmd *m)
> {
> 	u8 val;
> 	int i;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
> 		return -ETIMEDOUT;
> 
> 	val = stv0299_readreg (i2c, 0x08);
> 
> 	if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x6))  /* DiSEqC mode */
> 		return -EREMOTEIO;
> 
> 	for (i=0; i<m->msg_len; i++) {
> 		if (stv0299_wait_diseqc_fifo (i2c, 100) < 0)
> 			return -ETIMEDOUT;
> 
> 		if (stv0299_writereg (i2c, 0x09, m->msg[i]))
> 			return -EREMOTEIO;
> 	}
> 
> 	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
> 		return -ETIMEDOUT;
> 
> 	return 0;
> }
> 
> 
> static
> int stv0299_send_diseqc_burst (struct dvb_i2c_bus *i2c, fe_sec_mini_cmd_t burst)
> {
> 	u8 val;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
> 		return -ETIMEDOUT;
> 
> 	val = stv0299_readreg (i2c, 0x08);
> 
> 	if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x2))   /* burst mode */
> 		return -EREMOTEIO;
> 
> 	if (stv0299_writereg (i2c, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff))
> 		return -EREMOTEIO;
> 
> 	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
> 		return -ETIMEDOUT;
> 
> 	if (stv0299_writereg (i2c, 0x08, val))
> 		return -EREMOTEIO;
> 
> 	return 0;
> }
> 
> 
> static
> int stv0299_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone)
> {
> 	u8 val;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
> 		return -ETIMEDOUT;
> 
> 	val = stv0299_readreg (i2c, 0x08);
> 
> 	switch (tone) {
> 	case SEC_TONE_ON:
> 		return stv0299_writereg (i2c, 0x08, val | 0x3);
> 	case SEC_TONE_OFF:
> 		return stv0299_writereg (i2c, 0x08, (val & ~0x3) | 0x02);
> 	default:
> 		return -EINVAL;
> 	};
> }
> 
> 
> static
> int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage)
> {
> 	u8 val;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	val = stv0299_readreg (i2c, 0x0c);
> 	val &= 0x0f;
> 	val |= 0x40;   /* LNB power on */
> 
> 	switch (voltage) {
> 	case SEC_VOLTAGE_13:
> 		return stv0299_writereg (i2c, 0x0c, val);
> 	case SEC_VOLTAGE_18:
> 		return stv0299_writereg (i2c, 0x0c, val | 0x10);
> 	default:
> 		return -EINVAL;
> 	};
> }
> 
> 
> static
> int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate)
> {
> 	u32 ratio;
> 	u32 tmp;
> 	u8 aclk = 0xb4, bclk = 0x51;
> 
> 	if (srate > M_CLK)
> 		srate = M_CLK;
>         if (srate < 500000)
> 		srate = 500000;
> 
> 	if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
> 	if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
> 	if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
> 	if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
> 	if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
> 
> #define FIN (M_CLK >> 4)
> 
> 	tmp = srate << 4;
> 	ratio = tmp / FIN;
>         
> 	tmp = (tmp % FIN) << 8;
> 	ratio = (ratio << 8) + tmp / FIN;
>         
> 	tmp = (tmp % FIN) << 8;
> 	ratio = (ratio << 8) + tmp / FIN;
>   
> 	stv0299_writereg (i2c, 0x13, aclk);
> 	stv0299_writereg (i2c, 0x14, bclk);
> 	stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff);
> 	stv0299_writereg (i2c, 0x20, (ratio >>  8) & 0xff);
> 	stv0299_writereg (i2c, 0x21, (ratio      ) & 0xf0);
> 
> 	return 0;
> }
> 
> 
> static
> int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c)
> {
> 	u32 Mclk = M_CLK / 4096L;
> 	u32 srate;
> 	s32 offset;
> 	u8 sfr[3];
> 	s8 rtf;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	stv0299_readregs (i2c, 0x1f, sfr, 3);
> 	stv0299_readregs (i2c, 0x1a, &rtf, 1);
> 
> 	srate = (sfr[0] << 8) | sfr[1];
> 	srate *= Mclk;
> 	srate /= 16;
> 	srate += (sfr[2] >> 4) * Mclk / 256;
> 
> 	offset = (s32) rtf * (srate / 4096L);
> 	offset /= 128;
> 
> 	srate += offset;
> 
> 	srate += 1000;
> 	srate /= 2000;
> 	srate *= 2000;
> 
> 	return srate;
> }
> 
> 
> static
> int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
> {
> 	struct dvb_i2c_bus *i2c = fe->i2c;
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	switch (cmd) {
> 	case FE_GET_INFO:
> 		memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info));
> 		break;
> 
> 	case FE_READ_STATUS:
> 	{
> 		fe_status_t *status = (fe_status_t *) arg;
> 		u8 signal = 0xff - stv0299_readreg (i2c, 0x18);
> 		u8 sync = stv0299_readreg (i2c, 0x1b);
> 
> 		dprintk ("VSTATUS: 0x%02x\n", sync);
> 
> 		*status = 0;
> 
> 		if (signal > 10)
> 			*status |= FE_HAS_SIGNAL;
> 
> 		if (sync & 0x80)
> 			*status |= FE_HAS_CARRIER;
> 
> 		if (sync & 0x10)
> 			*status |= FE_HAS_VITERBI;
> 
> 		if (sync & 0x08)
> 			*status |= FE_HAS_SYNC;
> 
> 		if ((sync & 0x98) == 0x98)
> 			*status |= FE_HAS_LOCK;
> 
> 		break;
> 	}
> 
>         case FE_READ_BER:
> 		*((u32*) arg) = (stv0299_readreg (i2c, 0x1d) << 8)
> 			       | stv0299_readreg (i2c, 0x1e);
> 		break;
> 
> 	case FE_READ_SIGNAL_STRENGTH:
> 	{
> 		s32 signal =  0xffff - ((stv0299_readreg (i2c, 0x18) << 8)
> 			               | stv0299_readreg (i2c, 0x19));
> 
> 		dprintk ("AGC2I: 0x%02x%02x, signal=0x%04x\n", stv0299_readreg (i2c, 0x18),
> 			 stv0299_readreg (i2c, 0x19), signal);
> 
> 		signal = signal * 5 / 4;
> 		*((u16*) arg) = (signal > 0xffff) ? 0xffff :
> 				(signal < 0) ? 0 : signal;
> 		break;
> 	}
>         case FE_READ_SNR:
> 	{
> 		s32 snr = 0xffff - ((stv0299_readreg (i2c, 0x24) << 8)
> 			           | stv0299_readreg (i2c, 0x25));
> 		snr = 3 * (snr - 0xa100);
> 		*((u16*) arg) = (snr > 0xffff) ? 0xffff :
> 				(snr < 0) ? 0 : snr;
> 		break;
> 	}
> 	case FE_READ_UNCORRECTED_BLOCKS: 
> 		*((u32*) arg) = 0;    /* the stv0299 can't measure BER and */
> 		return -EOPNOTSUPP;   /* errors at the same time.... */
> 
>         case FE_SET_FRONTEND:
>         {
> 		struct dvb_frontend_parameters *p = arg;
> 
> 		tsa5059_set_tv_freq (i2c, p->frequency);
>                 stv0299_set_FEC (i2c, p->u.qpsk.fec_inner);
>                 stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate);
> 		stv0299_check_inversion (i2c);
> 		/* tsa5059_set_tv_freq (i2c, p->frequency); */
> 		stv0299_writereg (i2c, 0x22, 0x00);
> 		stv0299_writereg (i2c, 0x23, 0x00);
> 		stv0299_readreg (i2c, 0x23);
> 		stv0299_writereg (i2c, 0x12, 0xb9);
> 
> 		/* printk ("%s: tsa5059 status: %x\n", __FUNCTION__, tsa5059_read_status(i2c)); */
>                 break;
>         }
> 
>         case FE_GET_FRONTEND:
>         {
> 		struct dvb_frontend_parameters *p = arg;
> 		s32 derot_freq;
> 
> 		derot_freq = (s32)(s16) ((stv0299_readreg (i2c, 0x22) << 8)
> 					| stv0299_readreg (i2c, 0x23));
> 
> 		derot_freq *= (M_CLK >> 16);
> 		derot_freq += 500;
> 		derot_freq /= 1000;
> 
> 		p->frequency += derot_freq;
> 		p->inversion = (stv0299_readreg (i2c, 0x0c) & 1) ?
> 						INVERSION_OFF : INVERSION_ON;
> 		p->u.qpsk.fec_inner = stv0299_get_fec (i2c);
> 		p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c);
>                 break;
>         }
> 
>         case FE_SLEEP:
> 		stv0299_writereg (i2c, 0x0c, 0x00);  /*  LNB power off! */
> 		stv0299_writereg (i2c, 0x02, 0x80);
> 		break;
> 
>         case FE_INIT:
> 		return stv0299_init (i2c);
> 
>         case FE_RESET:
> 		stv0299_writereg (i2c, 0x22, 0x00);
> 		stv0299_writereg (i2c, 0x23, 0x00);
> 		stv0299_readreg (i2c, 0x23);
> 		stv0299_writereg (i2c, 0x12, 0xb9);
>                 break;
> 
> 	case FE_DISEQC_SEND_MASTER_CMD:
> 		return stv0299_send_diseqc_msg (i2c, arg);
> 
> 	case FE_DISEQC_SEND_BURST:
> 		return stv0299_send_diseqc_burst (i2c, (fe_sec_mini_cmd_t) arg);
> 
> 	case FE_SET_TONE:
> 		return stv0299_set_tone (i2c, (fe_sec_tone_mode_t) arg);
> 
> 	case FE_SET_VOLTAGE:
> 		return stv0299_set_voltage (i2c, (fe_sec_voltage_t) arg);
> 
> 	default:
> 		return -EOPNOTSUPP;
> 	};
> 
> 	return 0;
> }
> 
> 
> 
> static
> int uni0299_attach (struct dvb_i2c_bus *i2c)
> {
> 	u8 id = stv0299_readreg (i2c, 0x00);
> 
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	/* register 0x00 contains 0xa1 for STV0299 and STV0299B */
> 	if (id != 0xa1)
> 	  return -ENODEV;
> 
> 	dvb_register_frontend (uni0299_ioctl, i2c, NULL, &uni0299_info);
> 
> 	return 0;
> }
> 
> 
> static
> void uni0299_detach (struct dvb_i2c_bus *i2c)
> {
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	dvb_unregister_frontend (uni0299_ioctl, i2c);
> }
> 
> 
> static
> int __init init_uni0299 (void)
> {
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	return dvb_register_i2c_device (THIS_MODULE, uni0299_attach, uni0299_detach);
> }
> 
> 
> static 
> void __exit exit_uni0299 (void)
> {
> 	dprintk ("%s\n", __FUNCTION__);
> 
> 	dvb_unregister_i2c_device (uni0299_attach);
> }
> 
> module_init (init_uni0299);
> module_exit (exit_uni0299);
> 
> MODULE_PARM(debug,"i");
> MODULE_PARM_DESC(debug, "enable verbose debug messages");
> 
> MODULE_PARM(ftype,"i");
> MODULE_PARM_DESC(type, "frontend type");
> 
> MODULE_DESCRIPTION("Universal STV0299/TSA5059 DVB Frontend driver");
> MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann");
> MODULE_LICENSE("GPL");
> 
> 
> 



-- 
Info:
To unsubscribe send a mail to listar@linuxtv.org with "unsubscribe linux-dvb" as subject.



Home | Main Index | Thread Index