LinuxTV.org DVB driver update
cover LinuxTV.org DVB driver update
Hi Linus,
these 7 patches sync the LinuxTV.org DVB driver CVS completely with your latest 2.6.0-test7.
Major fixes:
- many dvb frontend related fixes:
- unify the alps_bsrv2 frontend driver with the new ves1x93 frontend driver
- add private data pointer to frontend drivers
- misc fixes in other frontend drivers
- update dvb-net handling
- fix vbi capture for DVB-C cards with analog module installed
I also back-feeded the kernel janitor patches from 2.6.0-test7 to our local CVS tree, so I don't wipe them out by accident in the future.
Please apply.
Thanks
Michael.
PATCH 1/7 New DVB frontend driver ves1x93 (obsoletes alps_bsrv2)
- [DVB] - replace alps_bsrv2 driver by generic ves1893 & ves1993 driver (Andreas Oberritter)
drivers/media/dvb/frontends/alps_bsrv2.c +0 -469
@@ -1,469 +0,0 @@ -/* -Driver for Alps BSRV2 QPSK Frontend - -Copyright (C) 1999 Convergence Integrated Media GmbH <[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/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/slab.h> - -#include "dvb_frontend.h" - -static int debug =0 ; -#define dprintk if (debug) printk - - -static struct dvb_frontend_info bsrv2_info = { - .name ="Alps BSRV2" , - .type =FE_QPSK , - .frequency_min =950000 , - .frequency_max =2150000 , - .frequency_stepsize =250 ,/* kHz for QPSK frontends */ - .frequency_tolerance =29500 , - .symbol_rate_min =1000000 , - .symbol_rate_max =45000000 , -/* . symbol_rate_tolerance = ???,*/ - .notifier_delay =50 ,/* 1/20 s */ - .caps =FE_CAN_INVERSION_AUTO | -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 -}; - - - -static u8 init_1893_tab [] = { -0x01 ,0xA4 ,0x35 ,0x81 ,0x2A ,0x0d ,0x55 ,0xC4 , -0x09 ,0x69 ,0x00 ,0x86 ,0x4c ,0x28 ,0x7F ,0x00 , -0x00 ,0x81 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , -0x80 ,0x00 ,0x31 ,0xb0 ,0x14 ,0x00 ,0xDC ,0x00 , -0x81 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , -0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , -0x00 ,0x55 ,0x00 ,0x00 ,0x7f ,0x00 -}; - - -static u8 init_1893_wtab[] = -{ -1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,1 ,1 ,0 ,0 , -0 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 , -1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,0 ,0 ,0 ,0 , -1 ,1 ,1 ,0 ,1 ,1 -}; - - -static int ves1893_writereg (struct dvb_i2c_bus *i2c,u8 reg,u8 data) -{ -u8 buf [] = {0x00 , reg, data }; -struct i2c_msg msg = { .addr =0x08 , .flags =0 , .buf = buf, .len =3 }; -int err; - -if ((err = i2c->xfer (i2c, &msg,1 )) !=1 ) { -dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n" , __FUNCTION__, err, reg, data); -return -EREMOTEIO ; - } - -return 0 ; -} - - -static u8 ves1893_readreg (struct dvb_i2c_bus *i2c,u8 reg) -{ -int ret; -u8 b0 [] = {0x00 , reg }; -u8 b1 [] = {0 }; -struct i2c_msg msg [] = { { .addr =0x08 , .flags =0 , .buf = b0, .len =2 }, - { .addr =0x08 , .flags =I2C_M_RD , .buf = b1, .len =1 } }; - - ret = i2c->xfer (i2c, msg,2 ); - -if (ret !=2 ) -dprintk ("%s: readreg error (ret == %i)\n" , __FUNCTION__, ret); - -return b1[0 ]; -} - - -static int sp5659_write (struct dvb_i2c_bus *i2c,u8 data [4 ]) -{ -int ret; -struct i2c_msg msg = { .addr =0x61 , .flags =0 , .buf = data, .len =4 }; - - ret = i2c->xfer (i2c, &msg,1 ); - -if (ret !=1 ) -printk ("%s: i/o error (ret == %i)\n" , __FUNCTION__, ret); - -return (ret !=1 ) ?-1 :0 ; -} - - - -/** -* set up the downconverter frequency divisor for a -* reference clock comparision frequency of 125 kHz. -*/ -static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c,u32 freq,u8 pwr) -{ -u32 div = (freq +479500 ) /125 ; -u8 buf [4 ] = { (div >>8 ) &0x7f , div &0xff ,0x95 , (pwr <<5 ) |0x30 }; - -return sp5659_write (i2c, buf); -} - - -static int ves1893_init (struct dvb_i2c_bus *i2c) -{ -int i; - -dprintk ("%s: init chip\n" , __FUNCTION__); - -for (i=0 ; i<54 ; i++) -if (init_1893_wtab[i]) -ves1893_writereg (i2c, i, init_1893_tab[i]); - -return 0 ; -} - - -static int ves1893_clr_bit (struct dvb_i2c_bus *i2c) -{ -ves1893_writereg (i2c,0 , init_1893_tab[0 ] &0xfe ); -ves1893_writereg (i2c,0 , init_1893_tab[0 ]); -ves1893_writereg (i2c,3 ,0x00 ); -return ves1893_writereg (i2c,3 , init_1893_tab[3 ]); -} - - -static int ves1893_set_inversion (struct dvb_i2c_bus *i2c,fe_spectral_inversion_t inversion) -{ -u8 val; - -/* -* inversion on/off are interchanged because i and q seem to -* be swapped on the hardware -*/ - -switch (inversion) { -case INVERSION_OFF : - val =0xc0 ; -break ; -case INVERSION_ON : - val =0x80 ; -break ; -case INVERSION_AUTO : - val =0x00 ; -break ; -default : -return -EINVAL ; - } - -/* needs to be saved for FE_GET_FRONTEND */ - init_1893_tab[0x0c ] = (init_1893_tab[0x0c ] &0x3f ) | val; - -return ves1893_writereg (i2c,0x0c , init_1893_tab[0x0c ]); -} - - -static int ves1893_set_fec (struct dvb_i2c_bus *i2c,fe_code_rate_t fec) -{ -if (fec ==FEC_AUTO ) -return ves1893_writereg (i2c,0x0d ,0x08 ); -else if (fec <FEC_1_2 || fec >FEC_8_9 ) -return -EINVAL ; -else -return ves1893_writereg (i2c,0x0d , fec -FEC_1_2 ); -} - - -static fe_code_rate_t ves1893_get_fec (struct dvb_i2c_bus *i2c) -{ -return FEC_1_2 + ((ves1893_readreg (i2c,0x0d ) >>4 ) &0x7 ); -} - - -static int ves1893_set_symbolrate (struct dvb_i2c_bus *i2c,u32 srate) -{ -u32 BDR ; -u32 ratio; -u8 ADCONF ,FCONF ,FNR ; -u32 BDRI ; -u32 tmp; - -dprintk ("%s: srate == %ud\n" , __FUNCTION__, (unsigned int ) srate); - -if (srate >90100000UL /2 ) - srate =90100000UL /2 ; - -if (srate <500000 ) - srate =500000 ; - -#define MUL (1UL<<26) -#define FIN (90106000UL>>4) - - tmp = srate <<6 ; - ratio = tmp /FIN ; - - tmp = (tmp %FIN ) <<8 ; - ratio = (ratio <<8 ) + tmp /FIN ; - - tmp = (tmp %FIN ) <<8 ; - ratio = (ratio <<8 ) + tmp /FIN ; - -FNR =0xff ; - -if (ratio <MUL /3 )FNR =0 ; -if (ratio < (MUL *11 )/50 )FNR =1 ; -if (ratio <MUL /6 )FNR =2 ; -if (ratio <MUL /9 )FNR =3 ; -if (ratio <MUL /12 )FNR =4 ; -if (ratio < (MUL *11 )/200 )FNR =5 ; -if (ratio <MUL /24 )FNR =6 ; -if (ratio < (MUL *27 )/1000 )FNR =7 ; -if (ratio <MUL /48 )FNR =8 ; -if (ratio < (MUL *137 )/10000 )FNR =9 ; - -if (FNR ==0xff ) { -ADCONF =0x89 ; -FCONF =0x80 ; -FNR =0 ; - }else { -ADCONF =0x81 ; -FCONF =0x88 | (FNR >>1 ) | ((FNR &0x01 ) <<5 ); - } - -BDR = (( (ratio << (FNR >>1 )) >>4 ) +1 ) >>1 ; -BDRI = ( ((FIN <<8 ) / ((srate << (FNR >>1 )) >>2 )) +1 ) >>1 ; - -dprintk ("FNR= %d\n" ,FNR ); -dprintk ("ratio= %08x\n" , (unsigned int ) ratio); -dprintk ("BDR= %08x\n" , (unsigned int )BDR ); -dprintk ("BDRI= %02x\n" , (unsigned int )BDRI ); - -if (BDRI >0xff ) -BDRI =0xff ; - -ves1893_writereg (i2c,0x06 ,0xff &BDR ); -ves1893_writereg (i2c,0x07 ,0xff & (BDR >>8 )); -ves1893_writereg (i2c,0x08 ,0x0f & (BDR >>16 )); - -ves1893_writereg (i2c,0x09 ,BDRI ); -ves1893_writereg (i2c,0x20 ,ADCONF ); -ves1893_writereg (i2c,0x21 ,FCONF ); - -if (srate <6000000 ) -ves1893_writereg (i2c,0x05 , init_1893_tab[0x05 ] |0x80 ); -else -ves1893_writereg (i2c,0x05 , init_1893_tab[0x05 ] &0x7f ); - -ves1893_writereg (i2c,0x00 ,0x00 ); -ves1893_writereg (i2c,0x00 ,0x01 ); - -ves1893_clr_bit (i2c); - -return 0 ; -} - - -static int ves1893_set_voltage (struct dvb_i2c_bus *i2c,fe_sec_voltage_t voltage) -{ -switch (voltage) { -case SEC_VOLTAGE_13 : -return ves1893_writereg (i2c,0x1f ,0x20 ); -case SEC_VOLTAGE_18 : -return ves1893_writereg (i2c,0x1f ,0x30 ); -case SEC_VOLTAGE_OFF : -return ves1893_writereg (i2c,0x1f ,0x00 ); -default : -return -EINVAL ; - } -} - - -static int bsrv2_ioctl (struct dvb_frontend *fe,unsigned int cmd,void *arg) -{ -struct dvb_i2c_bus *i2c = fe->i2c; - -switch (cmd) { -case FE_GET_INFO : -memcpy (arg, &bsrv2_info,sizeof (struct dvb_frontend_info )); -break ; - -case FE_READ_STATUS : - { -fe_status_t *status = arg; -u8 sync =ves1893_readreg (i2c,0x0e ); - - *status =0 ; - -if (sync &1 ) - *status |=FE_HAS_SIGNAL ; - -if (sync &2 ) - *status |=FE_HAS_CARRIER ; - -if (sync &4 ) - *status |=FE_HAS_VITERBI ; - -if (sync &8 ) - *status |=FE_HAS_SYNC ; - -if ((sync &0x1f ) ==0x1f ) - *status |=FE_HAS_LOCK ; - -break ; - } - -case FE_READ_BER : - { -u32 *ber = (u32 *) arg; - - *ber =ves1893_readreg (i2c,0x15 ); - *ber |= (ves1893_readreg (i2c,0x16 ) <<8 ); - *ber |= ((ves1893_readreg (i2c,0x17 ) &0x0f ) <<16 ); - *ber *=10 ; -break ; - } - -case FE_READ_SIGNAL_STRENGTH : - { -u8 signal = ~ves1893_readreg (i2c,0x0b ); - *((u16 *) arg) = (signal <<8 ) | signal; -break ; - } - -case FE_READ_SNR : - { -u8 snr = ~ves1893_readreg (i2c,0x1c ); - *(u16 *) arg = (snr <<8 ) | snr; -break ; - } - -case FE_READ_UNCORRECTED_BLOCKS : - { - *(u32 *) arg =ves1893_readreg (i2c,0x18 ) &0x7f ; - -if (*(u32 *) arg ==0x7f ) - *(u32 *) arg =0xffffffff ;/* counter overflow... */ - -ves1893_writereg (i2c,0x18 ,0x00 );/* reset the counter */ -ves1893_writereg (i2c,0x18 ,0x80 );/* dto. */ -break ; - } - -case FE_SET_FRONTEND : - { -struct dvb_frontend_parameters *p = arg; - -sp5659_set_tv_freq (i2c, p->frequency,0 ); -ves1893_set_inversion (i2c, p->inversion); -ves1893_set_fec (i2c, p->u.qpsk.fec_inner); -// sp5659_set_tv_freq (i2c, p->frequency, 0); -ves1893_set_symbolrate (i2c, p->u.qpsk.symbol_rate); -break ; - } - -case FE_GET_FRONTEND : - { -struct dvb_frontend_parameters *p = arg; -int afc; - - afc = ((int )((char )(ves1893_readreg (i2c,0x0a ) <<1 )))/2 ; - afc = (afc * (int )(p->u.qpsk.symbol_rate/1000 /8 ))/16 ; - - p->frequency -= afc; - -/* -* inversion indicator is only valid -* if auto inversion was used -*/ -if (!(init_1893_tab[0x0c ] &0x80 )) - p->inversion = (ves1893_readreg (i2c,0x0f ) &2 ) ? -INVERSION_OFF :INVERSION_ON ; - p->u.qpsk.fec_inner =ves1893_get_fec (i2c); -/* XXX FIXME: timing offset !! */ -break ; - } - -case FE_SLEEP : -ves1893_writereg (i2c,0x1f ,0x00 );/* LNB power off */ -return ves1893_writereg (i2c,0x00 ,0x08 ); - -case FE_INIT : -return ves1893_init (i2c); - -case FE_RESET : -return ves1893_clr_bit (i2c); - -case FE_SET_TONE : -return -EOPNOTSUPP ;/* the ves1893 can generate the 22k */ -/* let's implement this when we have */ -/* a box that uses the 22K_0 pin... */ -case FE_SET_VOLTAGE : -return ves1893_set_voltage (i2c, (fe_sec_voltage_t ) arg); - -default : -return -EOPNOTSUPP ; - }; - -return 0 ; -} - - -static int bsrv2_attach (struct dvb_i2c_bus *i2c) -{ -if ((ves1893_readreg (i2c,0x1e ) &0xf0 ) !=0xd0 ) -return -ENODEV ; - -dvb_register_frontend (bsrv2_ioctl, i2c,NULL , &bsrv2_info); - -return 0 ; -} - - -static void bsrv2_detach (struct dvb_i2c_bus *i2c) -{ -dvb_unregister_frontend (bsrv2_ioctl, i2c); -} - - -static int __init init_bsrv2 (void ) -{ -return dvb_register_i2c_device (THIS_MODULE , bsrv2_attach, bsrv2_detach); -} - - -static void __exit exit_bsrv2 (void) -{ -dvb_unregister_i2c_device (bsrv2_attach); -} - - -module_init (init_bsrv2); -module_exit (exit_bsrv2); - - -MODULE_DESCRIPTION ("BSRV2 DVB-S Frontend" ); -MODULE_AUTHOR ("Ralph Metzler" ); -MODULE_LICENSE ("GPL" ); -MODULE_PARM (debug,"i" ); -
drivers/media/dvb/frontends/ves1x93.c +619 -0
619 lines not on this page · raw message
drivers/media/dvb/frontends/Kconfig +10 -10
@@ -16,16 +16,6 @@ DVB adapter simply enable all supported frontends, the right one will get autodetected. -config DVB_ALPS_BSRV2 - tristate "Alps BSRV2 (QPSK)" - depends on DVB_CORE - help - A DVB-S tuner module. Say Y when you want to support this frontend. - - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. - config DVB_SP887X tristate "Frontends with sp887x demodulators, e.g. Microtune DTF7072" depends on DVB_CORE
@@ -125,6 +114,16 @@ DVB adapter simply enable all supported frontends, the right one will get autodetected. +config DVB_VES1X93 + tristate "Frontends with VES1893 or VES1993 demodulator (QPSK)" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. + config DVB_TDA1004X tristate "Frontends with external TDA1004X demodulators (OFDM)" depends on DVB_CORE && !STANDALONE
drivers/media/dvb/frontends/Makefile +1 -1
@@ -5,7 +5,6 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ obj-$(CONFIG_DVB_STV0299) += stv0299.o -obj-$(CONFIG_DVB_ALPS_BSRV2) += alps_bsrv2.o obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o
@@ -14,5 +13,6 @@ obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o +obj-$(CONFIG_DVB_VES1X93) += ves1x93.o obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o obj-$(CONFIG_DVB_SP887X) += sp887x.o
PATCH 2/7 Fix vbi handling in saa7146 core driver
- [DVB] add some debug and safety checks for video/vbi capture buffer handling
- [DVB] add new flag SAA7146_USE_PORT_B_FOR_VBI, so we can distinguish on which video port to apply the vbi workaround
- [DVB] add del_timer(...) for vbi capture queue and vbi_read timers, prevents oopses on vbi usage
drivers/media/common/saa7146_fops.c +18 -8
@@ -61,8 +61,14 @@ }DEB_EE (("dev:%p, dmaq:%p, state:%d\n" , dev, q, state)); +DEB_EE (("q->curr:%p\n" ,q->curr));/* finish current buffer */ +if (NULL == q->curr) { +DEB_D (("aiii. no current buffer\n" )); +return ; + } + q->curr->vb.state = state;do_gettimeofday (&q->curr->vb.ts);wake_up (&q->curr->vb.done);
@@ -221,9 +227,12 @@ fh->dev = dev; fh->type = type; - saa7146_video_uops.open (dev,fh); -if (0 !=BOARD_CAN_DO_VBI (dev) ) { +if ( fh->type ==V4L2_BUF_TYPE_VBI_CAPTURE ) { +DEB_S (("initializing vbi...\n" )); saa7146_vbi_uops.open (dev,fh); + }else { +DEB_S (("initializing video...\n" )); + saa7146_video_uops.open (dev,fh); } result =0 ;
@@ -245,9 +254,10 @@if (down_interruptible (&saa7146_devices_lock))return -ERESTARTSYS ; - saa7146_video_uops.release (dev,fh,file); -if (0 !=BOARD_CAN_DO_VBI (dev) ) { +if ( fh->type ==V4L2_BUF_TYPE_VBI_CAPTURE ) { saa7146_vbi_uops.release (dev,fh,file); + }else { + saa7146_video_uops.release (dev,fh,file); }module_put (dev->ext->module);
@@ -332,11 +342,11 @@switch (fh->type) {case V4L2_BUF_TYPE_VIDEO_CAPTURE : { -DEB_EE (("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun" , file, data, (unsigned long )count)); +// DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count)); return saa7146_video_uops.read (file,data,count,ppos); }case V4L2_BUF_TYPE_VBI_CAPTURE : { -DEB_EE (("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n" , file, data, (unsigned long )count)); +// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count)); return saa7146_vbi_uops.read (file,data,count,ppos); }break ;
@@ -443,7 +453,7 @@ {struct saa7146_vv *vv = dev->vv_data; -DEB_EE (("dev:%p, name:'%s'\n" ,dev,name)); +DEB_EE (("dev:%p, name:'%s', type:%d\n" ,dev,name,type)); *vid = device_template;strlcpy (vid->name, name,sizeof (vid->name));
@@ -451,7 +461,7 @@// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); if (video_register_device (vid,type,-1 ) <0 ) { -ERR (("cannot register vbi v4l2 device. skipping.\n" )); +ERR (("cannot register v4l2 device. skipping.\n" ));return -1 ; }
drivers/media/common/saa7146_vbi.c +16 -2
@@ -38,8 +38,14 @@WRITE_RPS1 (CMD_WR_REG | (1 <<8 ) | (BRS_CTRL /4 ));/* BXO = 1h, BRS to outbound */ WRITE_RPS1 (0xc000008c ); -/* wait for vbi_a */ +/* wait for vbi_a or vbi_b*/ +if (0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) { +DEB_D (("...using port b\n" )); +WRITE_RPS1 (CMD_PAUSE |MASK_09 ); + }else { +DEB_D (("...using port a\n" ));WRITE_RPS1 (CMD_PAUSE |MASK_10 ); + }/* upload brs */ WRITE_RPS1 (CMD_UPLOAD |MASK_08 );/* load brs-control register */
@@ -106,7 +112,7 @@if (signal_pending (current)) { -DEB_VBI (("aborted.\n" )); +DEB_VBI (("aborted (rps:0x%08x).\n" ,saa7146_read (dev,RPS_ADDR1 )));/* stop rps1 for sure */ saa7146_write (dev,MC1 ,MASK_29 );
@@ -316,6 +322,11 @@saa7146_write (dev,MC1 ,MASK_20 ); vv->vbi_streaming =NULL ; + +del_timer (&vv->vbi_q.timeout); +del_timer (&fh->vbi_read_timeout); + +DEB_VBI (("out\n" ));spin_unlock_irqrestore (&dev->slock, flags); }
@@ -371,7 +382,10 @@ fh->vbi_read_timeout.function = vbi_read_timeout; fh->vbi_read_timeout.data = (unsigned long )fh; +/* fixme: enable this again, if the dvb-c w/ analog module work properly */ +/* vbi_workaround(dev); +*/ }static void vbi_close (struct saa7146_dev *dev,struct saa7146_fh *fh,struct file *file)
drivers/media/common/saa7146_video.c +1 -1
@@ -1319,7 +1318,7 @@saa7146_pgtable_alloc (dev->pci, &buf->pt[0 ]); } - err =videobuf_iolock (dev->pci,&buf->vb,NULL ); + err =videobuf_iolock (dev->pci,&buf->vb, &vv->ov_fb);if (err) goto oops; err =saa7146_pgtable_build (dev,buf);
include/media/saa7146_vv.h +1 -0
@@ -150,6 +150,7 @@/* flags */ #define SAA7146_EXT_SWAP_ODD_EVEN 0x1/* needs odd/even fields swapped */ +#define SAA7146_USE_PORT_B_FOR_VBI 0x2/* use input port b for vbi hardware bug workaround */ struct saa7146_ext_vv {
PATCH 3/7 Add private data pointer to DVB frontends
- [DVB] allow private data to be associated with dvb frontend devices (Andreas Oberritter)
- [DVB] fixed fe_count countint in nxt6000 frontend driver (Andreas Oberritter)
drivers/media/dvb/ttusb-dec/dec2000_frontend.c +3 -5
@@ -140,17 +140,15 @@return 0 ; } -static int dec2000_frontend_attach (struct dvb_i2c_bus *i2c) +static int dec2000_frontend_attach (struct dvb_i2c_bus *i2c,void **data) {dprintk ("%s\n" , __FUNCTION__); -dvb_register_frontend (dec2000_frontend_ioctl, i2c,NULL , +return dvb_register_frontend (dec2000_frontend_ioctl, i2c,NULL , &dec2000_frontend_info); - -return 0 ; } -static void dec2000_frontend_detach (struct dvb_i2c_bus *i2c) +static void dec2000_frontend_detach (struct dvb_i2c_bus *i2c,void *data) {dprintk ("%s\n" , __FUNCTION__);
drivers/media/dvb/dvb-core/dvb_i2c.c +8 -7
@@ -32,8 +32,9 @@struct dvb_i2c_device {struct list_head list_head;struct module *owner; -int (*attach) (struct dvb_i2c_bus *i2c); -void (*detach) (struct dvb_i2c_bus *i2c); +int (*attach) (struct dvb_i2c_bus *i2c,void **data); +void (*detach) (struct dvb_i2c_bus *i2c,void *data); +void *data; };LIST_HEAD (dvb_i2c_buslist);
@@ -66,7 +67,7 @@return ; } -if (dev->attach (i2c) ==0 ) { +if (dev->attach (i2c, &dev->data) ==0 ) {register_i2c_client (i2c, dev); }else {if (dev->owner)
@@ -77,7 +78,7 @@static void detach_device (struct dvb_i2c_bus *i2c,struct dvb_i2c_device *dev) { - dev->detach (i2c); + dev->detach (i2c, dev->data);if (dev->owner)module_put (dev->owner);
@@ -229,8 +230,8 @@int dvb_register_i2c_device (struct module *owner, -int (*attach) (struct dvb_i2c_bus *i2c), -void (*detach) (struct dvb_i2c_bus *i2c)) +int (*attach) (struct dvb_i2c_bus *i2c,void **data), +void (*detach) (struct dvb_i2c_bus *i2c,void *data)) {struct dvb_i2c_device *entry;
@@ -256,7 +257,7 @@ } -int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c)) +int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c,void **data)) {struct list_head *entry, *n;
drivers/media/dvb/dvb-core/dvb_i2c.h +3 -3
@@ -54,10 +54,10 @@extern int dvb_register_i2c_device (struct module *owner, -int (*attach) (struct dvb_i2c_bus *i2c), -void (*detach) (struct dvb_i2c_bus *i2c)); +int (*attach) (struct dvb_i2c_bus *i2c,void **data), +void (*detach) (struct dvb_i2c_bus *i2c,void *data)); -extern int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c)); +extern int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c,void **data));#endif
drivers/media/dvb/frontends/alps_tdmb7.c +3 -5
@@ -402,7 +402,7 @@ -static int tdmb7_attach (struct dvb_i2c_bus *i2c) +static int tdmb7_attach (struct dvb_i2c_bus *i2c,void **data) {struct i2c_msg msg = { .addr =0x43 , .flags =0 , .buf =NULL ,. len =0 };
@@ -411,13 +411,11 @@if (i2c->xfer (i2c, &msg,1 ) !=1 )return -ENODEV ; -dvb_register_frontend (tdmb7_ioctl, i2c,NULL , &tdmb7_info); - -return 0 ; +return dvb_register_frontend (tdmb7_ioctl, i2c,NULL , &tdmb7_info); } -static void tdmb7_detach (struct dvb_i2c_bus *i2c) +static void tdmb7_detach (struct dvb_i2c_bus *i2c,void *data) {dprintk ("%s\n" , __FUNCTION__);
drivers/media/dvb/frontends/cx24110.c +3 -5
@@ -643,7 +643,7 @@ } -static int cx24110_attach (struct dvb_i2c_bus *i2c) +static int cx24110_attach (struct dvb_i2c_bus *i2c,void **data) {u8 sig;
@@ -651,13 +651,11 @@if ( sig !=0x5a && sig !=0x69 )return -ENODEV ; -dvb_register_frontend (cx24110_ioctl, i2c,NULL , &cx24110_info); - -return 0 ; +return dvb_register_frontend (cx24110_ioctl, i2c,NULL , &cx24110_info); } -static void cx24110_detach (struct dvb_i2c_bus *i2c) +static void cx24110_detach (struct dvb_i2c_bus *i2c,void *data) {dvb_unregister_frontend (cx24110_ioctl, i2c); }
drivers/media/dvb/frontends/dvb_dummy_fe.c +3 -6
@@ -173,14 +173,13 @@ } -static int dvbdummyfe_attach (struct dvb_i2c_bus *i2c) +static int dvbdummyfe_attach (struct dvb_i2c_bus *i2c,void **data) { -dvb_register_frontend (dvbdummyfe_ioctl, i2c,NULL ,frontend_info ()); -return 0 ; +return dvb_register_frontend (dvbdummyfe_ioctl, i2c,NULL ,frontend_info ()); } -static void dvbdummyfe_detach (struct dvb_i2c_bus *i2c) +static void dvbdummyfe_detach (struct dvb_i2c_bus *i2c,void *data) {dvb_unregister_frontend (dvbdummyfe_ioctl, i2c); }
@@ -191,14 +190,12 @@return dvb_register_i2c_device (THIS_MODULE , dvbdummyfe_attach, dvbdummyfe_detach); -return 0 ; } static void __exit exit_dvbdummyfe (void) {dvb_unregister_i2c_device (dvbdummyfe_attach); -return ; }
drivers/media/dvb/frontends/grundig_29504-401.c +4 -4
@@ -415,7 +416,7 @@ } -static int l64781_attach (struct dvb_i2c_bus *i2c) +static int l64781_attach (struct dvb_i2c_bus *i2c,void **data) {u8 reg0x3e;u8 b0 [] = {0x1a };
@@ -465,9 +466,8 @@ goto bailout; } -dvb_register_frontend (grundig_29504_401_ioctl, i2c,NULL , +return dvb_register_frontend (grundig_29504_401_ioctl, i2c,NULL , &grundig_29504_401_info); -return 0 ; bailout:l64781_writereg (i2c,0x3e , reg0x3e);/* restore reg 0x3e */
@@ -475,7 +475,8 @@ } -static void l64781_detach (struct dvb_i2c_bus *i2c) + +static void l64781_detach (struct dvb_i2c_bus *i2c,void *data) {dvb_unregister_frontend (grundig_29504_401_ioctl, i2c); }
drivers/media/dvb/frontends/grundig_29504-491.c +3 -5
@@ -433,19 +433,17 @@ } -static int tda8083_attach (struct dvb_i2c_bus *i2c) +static int tda8083_attach (struct dvb_i2c_bus *i2c,void **data) {if ((tda8083_readreg (i2c,0x00 )) !=0x05 )return -ENODEV ; -dvb_register_frontend (grundig_29504_491_ioctl, i2c,NULL , +return dvb_register_frontend (grundig_29504_491_ioctl, i2c,NULL , &grundig_29504_491_info); - -return 0 ; } -static void tda8083_detach (struct dvb_i2c_bus *i2c) +static void tda8083_detach (struct dvb_i2c_bus *i2c,void *data) {dvb_unregister_frontend (grundig_29504_491_ioctl, i2c); }
drivers/media/dvb/frontends/mt312.c +2 -2
@@ -714,7 +714,7 @@return 0 ; } -static int mt312_attach (struct dvb_i2c_bus *i2c) +static int mt312_attach (struct dvb_i2c_bus *i2c,void **data) {int ret;u8 id;
@@ -734,7 +734,7 @@return 0 ; } -static void mt312_detach (struct dvb_i2c_bus *i2c) +static void mt312_detach (struct dvb_i2c_bus *i2c,void *data) {dvb_unregister_frontend (mt312_ioctl, i2c);
drivers/media/dvb/frontends/nxt6000.c +3 -2
@@ -829,7 +829,7 @@static u8 demod_addr_tbl[] = {0x14 ,0x18 ,0x24 ,0x28 }; -static int nxt6000_attach (struct dvb_i2c_bus *i2c) +static int nxt6000_attach (struct dvb_i2c_bus *i2c,void **data) {u8 addr_nr;
@@ -881,13 +881,14 @@dvb_register_frontend (nxt6000_ioctl, i2c, (void *)(*((u32 *)&nxt)), &nxt6000_info); + fe_count++; }return (fe_count >0 ) ?0 : -ENODEV ; } -static void nxt6000_detach (struct dvb_i2c_bus *i2c) +static void nxt6000_detach (struct dvb_i2c_bus *i2c,void *data) {dprintk ("nxt6000: detach\n" );
drivers/media/dvb/frontends/sp887x.c +3 -5
@@ -561,7 +561,7 @@static -int sp887x_attach (struct dvb_i2c_bus *i2c) +int sp887x_attach (struct dvb_i2c_bus *i2c,void **data) {struct i2c_msg msg = { addr:0x70 , flags:0 , buf:NULL , len:0 };
@@ -570,14 +570,12 @@if (i2c->xfer (i2c, &msg,1 ) !=1 )return -ENODEV ; -dvb_register_frontend (sp887x_ioctl, i2c,NULL , &sp887x_info); - -return 0 ; +return dvb_register_frontend (sp887x_ioctl, i2c,NULL , &sp887x_info); }static -void sp887x_detach (struct dvb_i2c_bus *i2c) +void sp887x_detach (struct dvb_i2c_bus *i2c,void *data) {dprintk ("%s\n" , __FUNCTION__);dvb_unregister_frontend (sp887x_ioctl, i2c);
drivers/media/dvb/frontends/stv0299.c +3 -6
@@ -910,7 +910,7 @@ } -static int uni0299_attach (struct dvb_i2c_bus *i2c) +static int uni0299_attach (struct dvb_i2c_bus *i2c,void **data) {long tuner_type;u8 id;
@@ -928,17 +928,14 @@if ((tuner_type =probe_tuner (i2c)) <0 )return -ENODEV ; -dvb_register_frontend (uni0299_ioctl, i2c, (void *) tuner_type, +return dvb_register_frontend (uni0299_ioctl, i2c, (void *) tuner_type, &uni0299_info); - -return 0 ; } -static void uni0299_detach (struct dvb_i2c_bus *i2c) +static void uni0299_detach (struct dvb_i2c_bus *i2c,void *data) {dprintk ("%s\n" , __FUNCTION__); -dvb_unregister_frontend (uni0299_ioctl, i2c); }
drivers/media/dvb/frontends/tda1004x.c +5 -7
@@ -1055,7 +1055,7 @@ } -static int tda1004x_attach (struct dvb_i2c_bus *i2c) +static int tda1004x_attach (struct dvb_i2c_bus *i2c,void **data) {int tda1004x_address =-1 ;int tuner_address =-1 ;
@@ -1113,17 +1113,15 @@// register switch (tda_state.tda1004x_address) {case TDA10045H_ADDRESS : -dvb_register_frontend (tda1004x_ioctl, i2c, (void *)(*((u32 *) &tda_state)), &tda10045h_info); -break ; +return dvb_register_frontend (tda1004x_ioctl, i2c, (void *)(*((u32 *) &tda_state)), &tda10045h_info); +default : +return -ENODEV ; } - -// success -return 0 ; }static -void tda1004x_detach (struct dvb_i2c_bus *i2c) +void tda1004x_detach (struct dvb_i2c_bus *i2c,void *data) {dprintk ("%s\n" , __FUNCTION__);
drivers/media/dvb/frontends/ves1820.c +9 -11
@@ -507,9 +507,9 @@ } -static int ves1820_attach (struct dvb_i2c_bus *i2c) +static int ves1820_attach (struct dvb_i2c_bus *i2c,void **data) { -void *data =NULL ; +void *priv =NULL ;long demod_addr;long tuner_type;
@@ -522,21 +522,19 @@if ((i2c->adapter->num <MAX_UNITS ) && pwm[i2c->adapter->num] !=-1 ) {printk ("DVB: VES1820(%d): pwm=0x%02x (user specified)\n" , i2c->adapter->num, pwm[i2c->adapter->num]); -SET_PWM (data, pwm[i2c->adapter->num]); +SET_PWM (priv, pwm[i2c->adapter->num]); }else -SET_PWM (data,read_pwm (i2c)); -SET_REG0 (data, ves1820_inittab[0 ]); -SET_TUNER (data, tuner_type); -SET_DEMOD_ADDR (data, demod_addr); +SET_PWM (priv,read_pwm (i2c)); +SET_REG0 (priv, ves1820_inittab[0 ]); +SET_TUNER (priv, tuner_type); +SET_DEMOD_ADDR (priv, demod_addr); -dvb_register_frontend (ves1820_ioctl, i2c, data, &ves1820_info); - -return 0 ; +return dvb_register_frontend (ves1820_ioctl, i2c, priv, &ves1820_info); } -static void ves1820_detach (struct dvb_i2c_bus *i2c) +static void ves1820_detach (struct dvb_i2c_bus *i2c,void *data) {dvb_unregister_frontend (ves1820_ioctl, i2c); }
PATCH 4/7 Fix DVB network device handling
- [DVB] simplify and sanitize add/del handling for dvb net devices
drivers/media/dvb/dvb-core/dvb_net.c +21 -15
@@ -456,7 +463,7 @@ } -static void dvb_net_setup (struct net_device *dev) +static int dvb_net_init_dev (struct net_device *dev) {ether_setup (dev);
@@ -472,8 +479,11 @@ dev->hard_header_cache =NULL ; dev->flags |=IFF_NOARP ; + +return 0 ; } +static int get_if (struct dvb_net *dvbnet) {int i;
@@ -493,6 +503,7 @@static int dvb_net_add_if (struct dvb_net *dvbnet,u16 pid) {struct net_device *net; +struct dmx_demux *demux;struct dvb_net_priv *priv;int result;int if_num;
@@ -500,20 +511,25 @@if ((if_num =get_if (dvbnet)) <0 )return -EINVAL ; - net =alloc_netdev (sizeof (struct dvb_net_priv ),"dvb" , - dvb_net_setup); -if (!net) -return -ENOMEM ; + net = &dvbnet->device[if_num]; + demux = dvbnet->demux; -sprintf (net->name,"dvb%d_%d" , dvbnet->dvbdev->adapter->num, if_num); +memset (net,0 ,sizeof (struct net_device )); +memcpy (net->name,"dvb0_0" ,7 ); + net->name[3 ] = dvbnet->dvbdev->adapter->num +'0' ; + net->name[5 ] = if_num +'0' ; net->addr_len =6 ;memcpy (net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac,6 ); + net->next =NULL ; + net->init = dvb_net_init_dev; - dvbnet->device[if_num] = net; +if (!(net->priv =kmalloc (sizeof (struct dvb_net_priv ),GFP_KERNEL ))) +return -ENOMEM ; priv = net->priv; - priv->demux = dvbnet->demux; +memset (priv,0 ,sizeof (struct dvb_net_priv )); + priv->demux = demux; priv->pid = pid; priv->rx_mode =RX_MODE_UNI ;
@@ -523,7 +539,6 @@ net->base_addr = pid;if ((result =register_netdev (net)) <0 ) { -kfree (net);return result; }
@@ -533,20 +548,18 @@static int dvb_net_remove_if (struct dvb_net *dvbnet,int num) { -struct net_device *net = dvbnet->device[num]; -struct dvb_net_priv *priv = net->priv; +struct dvb_net_priv *priv = dvbnet->device[num].priv;if (!dvbnet->state[num])return -EINVAL ;if (priv->in_use)return -EBUSY ; -dvb_net_stop (net); +dvb_net_stop (&dvbnet->device[num]);flush_scheduled_work (); -unregister_netdev (net); +kfree (priv); +unregister_netdev (&dvbnet->device[num]); dvbnet->state[num]=0 ; -free_netdev (net); -return 0 ; }
drivers/media/dvb/dvb-core/dvb_net.h +1 -1
@@ -34,7 +34,7 @@struct dvb_net {struct dvb_device *dvbdev; -struct net_device *device[DVB_NET_DEVICES_MAX ]; +struct net_device device[DVB_NET_DEVICES_MAX ];int state[DVB_NET_DEVICES_MAX ];struct dmx_demux *demux; };
PATCH 5/7 Misc. fixes for ALPS TDLB7 DVB frontend driver
- [DVB] applied latest changes by Juergen Peitz (great work!)
- as a workaround for the lockup problem the data valid signal is checked after every channel switch. If it is not set FEC parameters are set again.
- disabled autoprobing if FEC settings are known (from sp887x).
- added support for FE_READ_UNCORRECTED_BLOCKS (from sp887x).
- added support for FE_SLEEP (from sp887x).
- bit error rate is now not only read from register 0xC07 but also from 0xC08 (from sp887x).
- I2C feedthrough to the tuner is now only enabled when needed (from sp887x).
- Added FE_CAN_QAM_AUTO and FE_CAN_HIERARCHY_AUTO to dvb_frontend_info.
- Removed obsolete setting of default frontend parameters in sp8870_init.
- Removed obsolete module parameter 'loadcode' because changes in the saa7146 driver made firmware loading very fast.
drivers/media/dvb/frontends/alps_tdlb7.c +415 -174
@@ -1,7 +1,7 @@/* Driver for Alps TDLB7 Frontend -Copyright (C) 1999 Juergen Peitz <[email protected]> +Copyright (C) 1999 Juergen Peitz 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
@@ -22,23 +22,9 @@/* -- Wrote this code mainly to get my own card running. It's working for me, but I -hope somebody who knows more about linux programming and the DVB driver can -improve it. -- Reused a lot from the existing driver and tuner code. -Thanks to everybody who worked on it! -- This driver needs a copy of the microcode file 'Sc_main.mc' from the Haupauge -windows driver in the 'usr/lib/DVB/driver/frontends' directory. -You can also pass the complete file name with the module parameter 'mcfile'. -- The code only needs to be loaded once after a power on. Because loading the -microcode to the card takes some time, you can use the 'loadcode=0' module -parameter, if you only want to reload the dvb driver. -- Juergen Peitz +This driver needs a copy of the firmware file 'Sc_main.mc' from the Haupauge +windows driver in the '/usr/lib/DVB/driver/frontends' directory. +You can also pass the complete file name with the module parameter 'firmware_file'. */
@@ -50,49 +35,46 @@#include <linux/vmalloc.h> #include <linux/fs.h> #include <linux/unistd.h> +#include <linux/delay.h> #include "dvb_frontend.h" +#include "dvb_functions.h" -static int debug =0 ; - -static int loadcode =1 ; +#ifndef CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION +#define CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION "/usr/lib/DVB/driver/frontends/Sc_main.mc" +#endif -static char * mcfile ="/usr/lib/DVB/driver/frontends/Sc_main.mc" ; +static char * firmware_file =CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION ; +static int debug =0 ;#define dprintk if (debug) printk -/* microcode size for sp8870 */ -#define SP8870_CODE_SIZE 16382 +/* firmware size for sp8870 */ +#define SP8870_FIRMWARE_SIZE 16382 -/* starting point for microcode in file 'Sc_main.mc' */ -#define SP8870_CODE_OFFSET 0x0A +/* starting point for firmware in file 'Sc_main.mc' */ +#define SP8870_FIRMWARE_OFFSET 0x0Astatic int errno;static struct dvb_frontend_info tdlb7_info = { - .name ="Alps TDLB7" , - .type =FE_OFDM , - .frequency_min =470000000 , - .frequency_max =860000000 , - .frequency_stepsize =166666 , -#if 0 - .frequency_tolerance = ???, - .symbol_rate_min = ???, - .symbol_rate_max = ???, - .symbol_rate_tolerance = ???, - .notifier_delay =0 , -#endif - .caps =FE_CAN_FEC_1_2 |FE_CAN_FEC_2_3 |FE_CAN_FEC_3_4 | + name:"Alps TDLB7" , + type:FE_OFDM , + frequency_min:470000000 , + frequency_max:860000000 , + frequency_stepsize:166666 , + 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_QAM_16 |FE_CAN_QAM_64 +FE_CAN_QPSK |FE_CAN_QAM_16 |FE_CAN_QAM_64 |FE_CAN_QAM_AUTO | +FE_CAN_HIERARCHY_AUTO |FE_CAN_RECOVER };static int sp8870_writereg (struct dvb_i2c_bus *i2c,u16 reg,u16 data) {u8 buf [] = { reg >>8 , reg &0xff , data >>8 , data &0xff }; -struct i2c_msg msg = { .addr =0x71 , .flags =0 , .buf = buf, .len =4 }; +struct i2c_msg msg = { addr:0x71 , flags:0 , buf: buf, len:4 };int err;if ((err = i2c->xfer (i2c, &msg,1 )) !=1 ) {
@@ -109,13 +91,15 @@int ret;u8 b0 [] = { reg >>8 , reg &0xff };u8 b1 [] = {0 ,0 }; -struct i2c_msg msg [] = { { .addr =0x71 , .flags =0 , .buf = b0, .len =2 }, - { .addr =0x71 , .flags =I2C_M_RD , .buf = b1, .len =2 } }; +struct i2c_msg msg [] = { { addr:0x71 , flags:0 , buf: b0, len:2 }, + { addr:0x71 , flags:I2C_M_RD , buf: b1, len:2 } }; ret = i2c->xfer (i2c, msg,2 ); -if (ret !=2 ) +if (ret !=2 ) {dprintk ("%s: readreg error (ret == %i)\n" , __FUNCTION__, ret); +return -1 ; + }return (b1[0 ] <<8 | b1[1 ]); }
@@ -124,7 +108,7 @@static int sp5659_write (struct dvb_i2c_bus *i2c,u8 data [4 ]) {int ret; -struct i2c_msg msg = { .addr =0x60 , .flags =0 , .buf = data, .len =4 }; +struct i2c_msg msg = { addr:0x60 , flags:0 , buf: data, len:4 }; ret = i2c->xfer (i2c, &msg,1 );
@@ -135,7 +119,7 @@ } -static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c,u32 freq) +static void sp5659_set_tv_freq (struct dvb_i2c_bus *i2c,u32 freq) {u32 div = (freq +36200000 ) /166666 ;u8 buf [4 ];
@@ -151,42 +135,50 @@ buf[2 ] =0x85 ; buf[3 ] = pwr <<6 ; -return sp5659_write (i2c, buf); +/* open i2c gate for PLL message transmission... */ +sp8870_writereg (i2c,0x206 ,0x001 ); +sp5659_write (i2c, buf); +sp8870_writereg (i2c,0x206 ,0x000 ); } -static int sp8870_read_code (const char *fn,char **fp) +static int sp8870_read_firmware_file (const char *fn,char **fp) {int fd; -loff_t l; +loff_t filesize;char *dp; fd =open (fn,0 ,0 );if (fd ==-1 ) { -printk (KERN_INFO "%s: Unable to load '%s'.\n" , __FUNCTION__, fn); -return -1 ; +printk ("%s: unable to open '%s'.\n" , __FUNCTION__, fn); +return -EIO ; } - l =lseek (fd,0L ,2 ); -if (l <=0 || l <SP8870_CODE_OFFSET +SP8870_CODE_SIZE ) { -printk (KERN_INFO "%s: code file too small '%s'\n" , __FUNCTION__, fn); + + filesize =lseek (fd,0L ,2 ); +if (filesize <=0 || filesize <SP8870_FIRMWARE_OFFSET +SP8870_FIRMWARE_SIZE ) { +printk ("%s: firmware filesize to small '%s'\n" , __FUNCTION__, fn);sys_close (fd); -return -1 ; +return -EIO ; } -lseek (fd,SP8870_CODE_OFFSET ,0 ); - *fp= dp =vmalloc (SP8870_CODE_SIZE ); + + *fp= dp =vmalloc (SP8870_FIRMWARE_SIZE );if (dp ==NULL ) { -printk (KERN_INFO "%s: Out of memory loading '%s'.\n" , __FUNCTION__, fn); +printk ("%s: out of memory loading '%s'.\n" , __FUNCTION__, fn);sys_close (fd); -return -1 ; +return -EIO ; } -if (read (fd, dp,SP8870_CODE_SIZE ) !=SP8870_CODE_SIZE ) { -printk (KERN_INFO "%s: Failed to read '%s'.\n" ,__FUNCTION__, fn); + +lseek (fd,SP8870_FIRMWARE_OFFSET ,0 ); +if (read (fd, dp,SP8870_FIRMWARE_SIZE ) !=SP8870_FIRMWARE_SIZE ) { +printk ("%s: failed to read '%s'.\n" ,__FUNCTION__, fn);vfree (dp);sys_close (fd); -return -1 ; +return -EIO ; } +sys_close (fd); *fp = dp; +return 0 ; }
@@ -191,62 +183,98 @@ } -static int sp8870_load_code (struct dvb_i2c_bus *i2c) +static int sp8870_firmware_upload (struct dvb_i2c_bus *i2c) { -/* this takes a long time. is there a way to do it faster? */ -char *lcode;struct i2c_msg msg; -unsigned char buf[255 ]; -int err; -int p=0 ; -int c; +char *fw_buf =NULL ; +int fw_pos; +u8 tx_buf[255 ]; +int tx_len; +int err =0 ;mm_segment_t fs =get_fs (); +dprintk ("%s: ...\n" , __FUNCTION__); +// system controller stop sp8870_writereg (i2c,0x0F00 ,0x0000 );// instruction RAM register hiword -sp8870_writereg (i2c,0x8F08 ,((SP8870_CODE_SIZE /2 ) &0xFFFF )); +sp8870_writereg (i2c,0x8F08 , ((SP8870_FIRMWARE_SIZE /2 ) &0xFFFF ));// instruction RAM MWR -sp8870_writereg (i2c,0x8F0A ,((SP8870_CODE_SIZE /2 ) >>16 )); +sp8870_writereg (i2c,0x8F0A , ((SP8870_FIRMWARE_SIZE /2 ) >>16 )); +// reading firmware file to buffer set_fs (get_ds ()); -if (sp8870_read_code (mcfile,(char **) &lcode)<0 )return -1 ; + err =sp8870_read_firmware_file (firmware_file, (char **) &fw_buf);set_fs (fs); -while (p<SP8870_CODE_SIZE ){ - c = (p<=SP8870_CODE_SIZE -252 ) ?252 :SP8870_CODE_SIZE -p; - buf[0 ]=0xCF ; - buf[1 ]=0x0A ; -memcpy (&buf[2 ],lcode+p,c); - c+=2 ; +if (err !=0 ) { +printk ("%s: reading firmware file failed!\n" , __FUNCTION__); +return err; + } + +// do firmware upload + fw_pos =0 ; +while (fw_pos <SP8870_FIRMWARE_SIZE ){ + tx_len = (fw_pos <=SP8870_FIRMWARE_SIZE -252 ) ?252 :SP8870_FIRMWARE_SIZE - fw_pos; +// write register 0xCF0A + tx_buf[0 ] =0xCF ; + tx_buf[1 ] =0x0A ; +memcpy (&tx_buf[2 ], fw_buf + fw_pos, tx_len); msg.addr=0x71 ; msg.flags=0 ; - msg.buf=buf; - msg.len=c; + msg.buf = tx_buf; + msg.len = tx_len +2 ;if ((err = i2c->xfer (i2c, &msg,1 )) !=1 ) { -dprintk ("%s: i2c error (err == %i)\n" , - __FUNCTION__, err); -vfree (lcode); -return -EREMOTEIO ; +printk ("%s: firmware upload failed!\n" , __FUNCTION__); +printk ("%s: i2c error (err == %i)\n" , __FUNCTION__, err); +vfree (fw_buf); +return err; } - - p+=252 ; + fw_pos += tx_len; } -vfree (lcode); + +vfree (fw_buf); + +dprintk ("%s: done!\n" , __FUNCTION__);return 0 ; }; -static int sp8870_init (struct dvb_i2c_bus *i2c) +static void sp8870_microcontroller_stop (struct dvb_i2c_bus *i2c) +{ +sp8870_writereg (i2c,0x0F08 ,0x000 ); +sp8870_writereg (i2c,0x0F09 ,0x000 ); + +// microcontroller STOP +sp8870_writereg (i2c,0x0F00 ,0x000 ); +} + + +static void sp8870_microcontroller_start (struct dvb_i2c_bus *i2c) { +sp8870_writereg (i2c,0x0F08 ,0x000 ); +sp8870_writereg (i2c,0x0F09 ,0x000 ); + +// microcontroller START +sp8870_writereg (i2c,0x0F00 ,0x001 ); +// not documented but if we don't read 0x0D01 out here +// we don't get a correct data valid signal +sp8870_readreg (i2c,0x0D01 ); +} + +static int sp8870_init (struct dvb_i2c_bus *i2c) +{dprintk ("%s\n" , __FUNCTION__); +/* enable TS output and interface pins */ +sp8870_writereg (i2c,0xc18 ,0x00d ); +// system controller stop -sp8870_writereg (i2c,0x0F00 ,0x0000 ); +sp8870_microcontroller_stop (i2c); -// ADC mode: 2 for MT8872, 3 for MT8870/8871 +// ADC mode sp8870_writereg (i2c,0x0301 ,0x0003 );// Reed Solomon parity bytes passed to output
@@ -255,103 +283,214 @@// MPEG clock is suppressed if no valid data sp8870_writereg (i2c,0x0C14 ,0x0001 ); -// sample rate correction bit [23..17] -sp8870_writereg (i2c,0x0319 ,0x000A ); +/* bit 0x010: enable data valid signal */ +sp8870_writereg (i2c,0x0D00 ,0x010 ); +sp8870_writereg (i2c,0x0D01 ,0x000 ); -// sample rate correction bit [16..0] -sp8870_writereg (i2c,0x031A ,0x0AAB ); +return 0 ; +} -// integer carrier offset -sp8870_writereg (i2c,0x0309 ,0x0400 ); -// fractional carrier offset -sp8870_writereg (i2c,0x030A ,0x0000 ); +static int sp8870_read_status (struct dvb_i2c_bus *i2c,fe_status_t * fe_status) +{ +int status; +int signal; -// filter for 8 Mhz channel -sp8870_writereg (i2c,0x0311 ,0x0000 ); + *fe_status =0 ; -// scan order: 2k first = 0x0000, 8k first = 0x0001 -sp8870_writereg (i2c,0x0338 ,0x0000 ); + status =sp8870_readreg (i2c,0x0200 ); +if (status <0 ) +return -EIO ; + + signal =sp8870_readreg (i2c,0x0303 ); +if (signal <0 ) +return -EIO ; + +if (signal >0x0F ) + *fe_status |=FE_HAS_SIGNAL ; +if (status &0x08 ) + *fe_status |=FE_HAS_SYNC ; +if (status &0x04 ) + *fe_status |=FE_HAS_LOCK |FE_HAS_CARRIER |FE_HAS_VITERBI ;return 0 ; } -static int tdlb7_ioctl (struct dvb_frontend *fe,unsigned int cmd,void *arg) +static int sp8870_read_ber (struct dvb_i2c_bus *i2c,u32 * ber) { -struct dvb_i2c_bus *i2c = fe->i2c; +int ret; +u32 tmp; -switch (cmd) { -case FE_GET_INFO : -memcpy (arg, &tdlb7_info,sizeof (struct dvb_frontend_info )); -break ; + *ber =0 ; -case FE_READ_STATUS : - { -fe_status_t *status = arg; -int sync =sp8870_readreg (i2c,0x0200 ); -int signal =0xff -sp8870_readreg (i2c,0x303 ); + ret =sp8870_readreg (i2c,0xC08 ); +if (ret <0 ) +return -EIO ; - *status=0 ; -if (signal>10 )// FIXME: is 10 the right value ? - *status |=FE_HAS_SIGNAL ; + tmp = ret &0x3F ; -if (sync&0x04 )// FIXME: find criteria - *status |=FE_HAS_CARRIER ; + ret =sp8870_readreg (i2c,0xC07 ); +if (ret <0 ) +return -EIO ; -if (sync&0x04 )// FIXME - *status |=FE_HAS_VITERBI ; + tmp = ret <<6 ; -if (sync&0x08 )// FIXME - *status |=FE_HAS_SYNC ; +if (tmp >=0x3FFF0 ) + tmp = ~0 ; -if (sync&0x04 ) - *status |=FE_HAS_LOCK ; -break ; + *ber = tmp; +return 0 ; } -case FE_READ_BER : + +static int sp8870_read_signal_strength (struct dvb_i2c_bus *i2c,u16 * signal) { -u32 *ber=(u32 *) arg; -// bit error rate before Viterbi - *ber=sp8870_readreg (i2c,0x0C07 ); -break ; +int ret; +u16 tmp; - } + *signal =0 ; -case FE_READ_SIGNAL_STRENGTH :// FIXME: correct registers ? - { - *((u16 *) arg) =0xffff -((sp8870_readreg (i2c,0x306 ) <<8 ) |sp8870_readreg (i2c,0x303 )); -break ; + ret =sp8870_readreg (i2c,0x306 ); +if (ret <0 ) +return -EIO ; + + tmp = ret <<8 ; + + ret =sp8870_readreg (i2c,0x303 ); +if (ret <0 ) +return -EIO ; + + tmp |= ret; + +if (tmp) + *signal =0xFFFF - tmp; + +return 0 ; } -case FE_READ_SNR :// not supported by hardware? + +static int sp8870_read_snr (struct dvb_i2c_bus *i2c,u32 * snr) { -s32 *snr=(s32 *) arg; *snr=0 ;return -EOPNOTSUPP ; } -case FE_READ_UNCORRECTED_BLOCKS :// not supported by hardware? + +static int sp8870_read_uncorrected_blocks (struct dvb_i2c_bus *i2c,u32 * ublocks) { -u32 *ublocks=(u32 *) arg; +int ret; + *ublocks=0 ; -return -EOPNOTSUPP ; + + ret =sp8870_readreg (i2c,0xC0C ); +if (ret <0 ) +return -EIO ; + +if (ret ==0xFFFF ) + ret = ~0 ; + + *ublocks = ret; + +return 0 ; } -case FE_SET_FRONTEND : + +static int sp8870_read_data_valid_signal (struct dvb_i2c_bus *i2c) +{ +return (sp8870_readreg (i2c,0x0D02 ) >0 ); +} + + +static +int configure_reg0xc05 (struct dvb_frontend_parameters *p,u16 *reg0xc05) +{ +int known_parameters =1 ; + + *reg0xc05 =0x000 ; + +switch (p->u.ofdm.constellation) { +case QPSK : +break ; +case QAM_16 : + *reg0xc05 |= (1 <<10 ); +break ; +case QAM_64 : + *reg0xc05 |= (2 <<10 ); +break ; +case QAM_AUTO : + known_parameters =0 ; +break ; +default : +return -EINVAL ; + }; + +switch (p->u.ofdm.hierarchy_information) { +case HIERARCHY_NONE : +break ; +case HIERARCHY_1 : + *reg0xc05 |= (1 <<7 ); +break ; +case HIERARCHY_2 : + *reg0xc05 |= (2 <<7 ); +break ; +case HIERARCHY_4 : + *reg0xc05 |= (3 <<7 ); +break ; +case HIERARCHY_AUTO : + known_parameters =0 ; +break ; +default : +return -EINVAL ; + }; + +switch (p->u.ofdm.code_rate_HP) { +case FEC_1_2 : +break ; +case FEC_2_3 : + *reg0xc05 |= (1 <<3 ); +break ; +case FEC_3_4 : + *reg0xc05 |= (2 <<3 ); +break ; +case FEC_5_6 : + *reg0xc05 |= (3 <<3 ); +break ; +case FEC_7_8 : + *reg0xc05 |= (4 <<3 ); +break ; +case FEC_AUTO : + known_parameters =0 ; +break ; +default : +return -EINVAL ; + }; + +if (known_parameters) + *reg0xc05 |= (2 <<1 );/* use specified parameters */ +else + *reg0xc05 |= (1 <<1 );/* enable autoprobing */ + +return 0 ; +} + + +static int sp8870_set_frontend_parameters (struct dvb_i2c_bus *i2c, +struct dvb_frontend_parameters *p) { -struct dvb_frontend_parameters *p = arg; +int err; +u16 reg0xc05; + +if ((err =configure_reg0xc05 (p, ®0xc05))) +return err;// system controller stop -sp8870_writereg (i2c,0x0F00 ,0x0000 ); +sp8870_microcontroller_stop (i2c); +// set tuner parameters sp5659_set_tv_freq (i2c, p->frequency); -// read status reg in order to clear pending irqs -sp8870_readreg (i2c,0x200 ); -// sample rate correction bit [23..17] sp8870_writereg (i2c,0x0319 ,0x000A );
@@ -378,28 +517,141 @@else sp8870_writereg (i2c,0x0338 ,0x0001 ); -// instruction RAM register loword -sp8870_writereg (i2c,0x0F09 ,0x0000 ); +sp8870_writereg (i2c,0xc05 , reg0xc05); -// instruction RAM register hiword -sp8870_writereg (i2c,0x0F08 ,0x0000 ); +// read status reg in order to clear pending irqs +sp8870_readreg (i2c,0x200 );// system controller start -sp8870_writereg (i2c,0x0F00 ,0x0001 ); +sp8870_microcontroller_start (i2c); -break ; +return 0 ; } -case FE_GET_FRONTEND :// FIXME: read known values back from Hardware... + +// number of trials to recover from lockup +#define MAXTRIALS 5 +// maximum checks for data valid signal +#define MAXCHECKS 100 + +// only for debugging: counter for detected lockups +static int lockups =0 ; +// only for debugging: counter for channel switches +static int switches =0 ; + +static int sp8870_set_frontend (struct dvb_i2c_bus *i2c,struct dvb_frontend_parameters *p) { +/* +The firmware of the sp8870 sometimes locks up after setting frontend parameters. +We try to detect this by checking the data valid signal. +If it is not set after MAXCHECKS we try to recover the lockup by setting +the frontend parameters again. +*/ + +int err =0 ; +int valid =0 ; +int trials =0 ; +int check_count =0 ; + +dprintk ("%s: frequency = %i\n" , __FUNCTION__, p->frequency); + +for (trials =1 ; trials <=MAXTRIALS ; trials++) { + +if ((err =sp8870_set_frontend_parameters (i2c, p))) +return err; + +for (check_count =0 ; check_count <MAXCHECKS ; check_count++) { +// valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0); + valid =sp8870_read_data_valid_signal (i2c); +if (valid) { +dprintk ("%s: delay = %i usec\n" , + __FUNCTION__, check_count *10 ); +break ; + } +udelay (10 ); + } +if (valid)break ; } -case FE_SLEEP :// is this supported by hardware? +if (!valid) { +printk ("%s: firmware crash!!!!!!\n" , __FUNCTION__); +return -EIO ; + } + +if (debug) { +if (valid) { +if (trials >1 ) { +printk ("%s: firmware lockup!!!\n" , __FUNCTION__); +printk ("%s: recovered after %i trial(s))\n" , __FUNCTION__, trials -1 ); + lockups++; + } + } + switches++; +printk ("%s: switches = %i lockups = %i\n" , __FUNCTION__, switches, lockups); + } + +return 0 ; +} + + +static int sp8870_sleep (struct dvb_i2c_bus *i2c) +{ +// tristate TS output and disable interface pins +return sp8870_writereg (i2c,0xC18 ,0x000 ); +} + + +static int sp8870_wake_up (struct dvb_i2c_bus *i2c) +{ +// enable TS output and interface pins +return sp8870_writereg (i2c,0xC18 ,0x00D ); +} + + +static int tdlb7_ioctl (struct dvb_frontend *fe,unsigned int cmd,void *arg) +{ +struct dvb_i2c_bus *i2c = fe->i2c; + +switch (cmd) { +case FE_GET_INFO : +memcpy (arg, &tdlb7_info,sizeof (struct dvb_frontend_info )); +break ; + +case FE_READ_STATUS : +return sp8870_read_status (i2c, (fe_status_t *) arg); + +case FE_READ_BER : +return sp8870_read_ber (i2c, (u32 *) arg); + +case FE_READ_SIGNAL_STRENGTH : +return sp8870_read_signal_strength (i2c, (u16 *) arg); + +case FE_READ_SNR :// not supported by hardware? +return sp8870_read_snr (i2c, (u32 *) arg); + +case FE_READ_UNCORRECTED_BLOCKS : +return sp8870_read_uncorrected_blocks (i2c, (u32 *) arg); + +case FE_SET_FRONTEND : +return sp8870_set_frontend (i2c, (struct dvb_frontend_parameters *) arg); + +case FE_RESET : +return -EOPNOTSUPP ; + +case FE_GET_FRONTEND :// FIXME: read known values back from Hardware... return -EOPNOTSUPP ; +case FE_SLEEP : +return sp8870_sleep (i2c); +case FE_INIT : -return sp8870_init (i2c); +sp8870_wake_up (i2c); +if (fe->data ==NULL ) {// first time initialisation... + fe->data = (void *) ~0 ; +sp8870_init (i2c); + } +break ;default :return -EOPNOTSUPP ;
@@ -409,31 +661,22 @@ } -static int tdlb7_attach (struct dvb_i2c_bus *i2c) +static int tdlb7_attach (struct dvb_i2c_bus *i2c,void **data) { - -struct i2c_msg msg = { .addr =0x71 , .flags =0 , .buf =NULL , .len =0 }; +struct i2c_msg msg = { addr:0x71 , flags:0 , buf:NULL , len:0 };dprintk ("%s\n" , __FUNCTION__);if (i2c->xfer (i2c, &msg,1 ) !=1 )return -ENODEV ; -if (loadcode) { -dprintk ("%s: loading mcfile '%s' !\n" , __FUNCTION__, mcfile); -if (sp8870_load_code (i2c)==0 ) -dprintk ("%s: microcode loaded!\n" , __FUNCTION__); - }else { -dprintk ("%s: without loading mcfile!\n" , __FUNCTION__); - } - -dvb_register_frontend (tdlb7_ioctl, i2c,NULL , &tdlb7_info); +sp8870_firmware_upload (i2c); -return 0 ; +return dvb_register_frontend (tdlb7_ioctl, i2c,NULL , &tdlb7_info); } -static void tdlb7_detach (struct dvb_i2c_bus *i2c) +static void tdlb7_detach (struct dvb_i2c_bus *i2c,void *data) {dprintk ("%s\n" , __FUNCTION__);
@@ -464,11 +707,8 @@MODULE_PARM (debug,"i" );MODULE_PARM_DESC (debug,"enable verbose debug messages" ); -MODULE_PARM (loadcode,"i" ); -MODULE_PARM_DESC (loadcode,"load tuner microcode" ); - -MODULE_PARM (mcfile,"s" ); -MODULE_PARM_DESC (mcfile,"where to find the microcode file" ); +MODULE_PARM (firmware_file,"s" ); +MODULE_PARM_DESC (firmware_file,"where to find the firmware file" );MODULE_DESCRIPTION ("TDLB7 DVB-T Frontend" );MODULE_AUTHOR ("Juergen Peitz" );
PATCH 6/7 Misc. fixes for AT76C651 DVB frontend driver
- [DVB] fixed some return values in device attach functions
- [DVB] allow private data to be associated with frontend devices here, too
- [DVB] misc bugfixes and performance improvements (endianess, function split up)
drivers/media/dvb/frontends/at76c651.c +73 -67
@@ -37,6 +37,8 @@#include "dvb_functions.h" static int debug =0 ; +static u8 at76c651_qam; +static u8 at76c651_revision;#define dprintk if (debug) printk
@@ -53,7 +55,7 @@static struct dvb_frontend_info at76c651_info = { - .name ="Atmel AT76c651(B) with DAT7021" , + .name ="Atmel AT76C651(B) with DAT7021" , .type =FE_QAM , .frequency_min =48250000 , .frequency_max =863250000 ,
@@ -126,46 +128,70 @@ } +static int at76c651_reset (struct dvb_i2c_bus *i2c) +{ + +return at76c651_writereg (i2c,0x07 ,0x01 ); + +} + +static int at76c651_disable_interrupts (struct dvb_i2c_bus *i2c) +{ + +return at76c651_writereg (i2c,0x0b ,0x00 ); + +} +static int at76c651_set_auto_config (struct dvb_i2c_bus *i2c) { +/* +* Autoconfig +*/ +at76c651_writereg (i2c,0x06 ,0x01 );/* -* performance optimizations +* Performance optimizations, should be done after autoconfig */ at76c651_writereg (i2c,0x10 ,0x06 ); -at76c651_writereg (i2c,0x11 ,0x10 ); +at76c651_writereg (i2c,0x11 , ((at76c651_qam ==5 ) || (at76c651_qam ==7 )) ?0x12 :0x10 );at76c651_writereg (i2c,0x15 ,0x28 );at76c651_writereg (i2c,0x20 ,0x09 ); -at76c651_writereg (i2c,0x24 ,0x90 ); +at76c651_writereg (i2c,0x24 , ((at76c651_qam ==5 ) || (at76c651_qam ==7 )) ?0xC0 :0x90 ); +at76c651_writereg (i2c,0x30 ,0x90 ); +if (at76c651_qam ==5 ) +at76c651_writereg (i2c,0x35 ,0x2A ); -return 0 ; +/* +* Initialize A/D-converter +*/ +if (at76c651_revision ==0x11 ) { +at76c651_writereg (i2c,0x2E ,0x38 ); +at76c651_writereg (i2c,0x2F ,0x13 ); } -static int at76c651_set_bbfreq (struct dvb_i2c_bus *i2c) -{ +at76c651_disable_interrupts (i2c); -at76c651_writereg (i2c,0x04 ,0x3f ); -at76c651_writereg (i2c,0x05 ,0xee ); +/* +* Restart operation +*/ + +at76c651_reset (i2c);return 0 ; } -static int at76c651_reset (struct dvb_i2c_bus *i2c) +static int at76c651_set_bbfreq (struct dvb_i2c_bus *i2c) { -return at76c651_writereg (i2c,0x07 ,0x01 ); - -} - -static int at76c651_disable_interrupts (struct dvb_i2c_bus *i2c) -{ +at76c651_writereg (i2c,0x04 ,0x3f ); +at76c651_writereg (i2c,0x05 ,0xee ); -return at76c651_writereg (i2c,0x0b ,0x00 ); +return 0 ; }
@@ -186,6 +212,10 @@struct i2c_msg msg = { .addr =0xc2 >>1 , .flags =0 , .buf = (u8 *) & tw, .len =sizeof (tw) }; +#ifdef __LITTLE_ENDIAN + tw =__cpu_to_be32 (tw); +#endif +at76c651_switch_tuner_i2c (i2c,1 ); ret = i2c->xfer (i2c, &msg,1 );
@@ -236,7 +266,7 @@u32 mantissa;if (symbolrate >9360000 ) -return -1 ; +return -EINVAL ;/* * FREF = 57800 kHz
@@ -258,34 +288,31 @@static int at76c651_set_qam (struct dvb_i2c_bus *i2c,fe_modulation_t qam) { -u8 qamsel =0 ; -switch (qam) { -case QPSK : - qamsel =0x02 ; + at76c651_qam =0x02 ;break ;case QAM_16 : - qamsel =0x04 ; + at76c651_qam =0x04 ;break ;case QAM_32 : - qamsel =0x05 ; + at76c651_qam =0x05 ;break ;case QAM_64 : - qamsel =0x06 ; + at76c651_qam =0x06 ;break ;case QAM_128 : - qamsel =0x07 ; + at76c651_qam =0x07 ;break ;case QAM_256 : - qamsel =0x08 ; + at76c651_qam =0x08 ;break ;#if 0 case QAM_512 : - qamsel =0x09 ; + at76c651_qam =0x09 ;break ;case QAM_1024 : - qamsel =0x0A ; + at76c651_qam =0x0A ;break ;#endif default :
@@ -293,7 +320,7 @@ } -return at76c651_writereg (i2c,0x03 , qamsel); +return at76c651_writereg (i2c,0x03 , at76c651_qam); }
@@ -345,7 +371,6 @@at76c651_set_qam (i2c,QAM_64 );at76c651_set_bbfreq (i2c);at76c651_set_auto_config (i2c); -at76c651_disable_interrupts (i2c);return 0 ;
@@ -408,13 +432,12 @@ {u8 gain = ~at76c651_readreg (fe->i2c,0x91 ); - *(s32 *) arg = (gain <<8 ) | gain; - *(s32 *) arg =0x0FFF ; + *(u16 *) arg = (gain <<8 ) | gain;break ; }case FE_READ_SNR : - *(s32 *) arg = + *(u16 *) arg =0xFFFF - ((at76c651_readreg (fe->i2c,0x8F ) <<8 ) |at76c651_readreg (fe->i2c,0x90 ));
@@ -440,42 +463,31 @@return at76c651_reset (fe->i2c);default : -return -ENOSYS ; +return -ENOIOCTLCMD ; }return 0 ; } -static int at76c651_attach (struct dvb_i2c_bus *i2c) +static int at76c651_attach (struct dvb_i2c_bus *i2c,void **data) +{ +if ( (at76c651_readreg (i2c,0x0E ) !=0x65 ) || + ( ( (at76c651_revision =at76c651_readreg (i2c,0x0F )) &0xFE ) !=0x10 ) ) { - -if (at76c651_readreg (i2c,0x0e ) !=0x65 ) { -dprintk ("no AT76C651(B) found\n" ); -return -ENODEV ; - } -if (at76c651_readreg (i2c,0x0F ) !=0x10 ) { - -if (at76c651_readreg (i2c,0x0F ) ==0x11 ) { - -dprintk ("AT76C651B found\n" ); - - }else { - -dprintk ("no AT76C651(B) found\n" ); - -return -ENODEV ; - +if (at76c651_revision ==0x10 ) + { +dprintk ("AT76C651A found\n" ); +strcpy (at76c651_info.name,"Atmel AT76C651A with DAT7021" ); } - - }else { - +else + { +strcpy (at76c651_info.name,"Atmel AT76C651B with DAT7021" );dprintk ("AT76C651B found\n" ); - }at76c651_set_defaults (i2c);
@@ -480,19 +492,15 @@at76c651_set_defaults (i2c); -dvb_register_frontend (at76c651_ioctl, i2c,NULL , &at76c651_info); - -return 0 ; +return dvb_register_frontend (at76c651_ioctl, i2c,NULL , &at76c651_info); } -static void at76c651_detach (struct dvb_i2c_bus *i2c) +static void at76c651_detach (struct dvb_i2c_bus *i2c,void *data) {dvb_unregister_frontend (at76c651_ioctl, i2c); -at76c651_disable_interrupts (i2c); - }static int __init at76c651_init (void )
@@ -513,11 +521,7 @@module_init (at76c651_init);module_exit (at76c651_exit); -#ifdef MODULE MODULE_DESCRIPTION ("at76c651/dat7021 dvb-c frontend driver" );MODULE_AUTHOR ("Andreas Oberritter <[email protected]>" ); -#ifdef MODULE_LICENSE MODULE_LICENSE ("GPL" ); -#endif MODULE_PARM (debug,"i" ); -#endif
PATCH 7/7 Update the AV7110 DVB driver
- [DVB] add vbi device handling for dvb-c cards with analog module
- [DVB] fix error handling upon device initialization
- [DVB] fix DD1_INIT handling of DVB-C w/ analog module installed. (Jon Burgess)
drivers/media/dvb/ttpci/av7110.c +48 -32
@@ -55,8 +55,10 @@#include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/in.h> +#include <linux/slab.h> #include <linux/string.h> #include <linux/pci.h> +#include <linux/init.h> #include <linux/vmalloc.h> #include <linux/netdevice.h> #include <linux/inetdevice.h>
@@ -4520,28 +4526,6 @@DEB_EE (("dev: %p, av7110: %p\n" ,dev,av7110)); -/* special case DVB-C: these cards have an analog tuner -plus need some special handling, so we have separate -saa7146_ext_vv data for these... */ -if (dev->pci->subsystem_vendor ==0x110a ) { - ret =saa7146_vv_init (dev, &av7110_vv_data_c); - }else { - ret =saa7146_vv_init (dev, &av7110_vv_data_st); - } - -if (0 != ret) { -ERR (("cannot init capture device. skipping.\n" )); -kfree (av7110); -return -1 ; - } - -if (saa7146_register_device (&av7110->v4l_dev, dev,"av7110" ,VFL_TYPE_GRABBER )) { -ERR (("cannot register capture device. skipping.\n" )); -saa7146_vv_release (dev); -kfree (av7110); -return -1 ; - } - av7110->dev=(struct saa7146_dev *)dev;dvb_register_adapter (&av7110->dvb_adapter, av7110->card_name);
@@ -4555,8 +4539,6 @@ av7110->dvb_adapter, 0);if (!av7110->i2c_bus) { -saa7146_unregister_device (&av7110->v4l_dev, dev); -saa7146_vv_release (dev);dvb_unregister_adapter (av7110->dvb_adapter);kfree (av7110);return -ENOMEM ;
@@ -4727,7 +4709,7 @@memcpy (standard,dvb_standard,sizeof (struct saa7146_standard )*2 );/* set dd1 stream a & b */ saa7146_write (dev,DD1_STREAM_B ,0x00000000 ); -saa7146_write (dev,DD1_INIT ,0x0200700 ); +saa7146_write (dev,DD1_INIT ,0x02000700 );saa7146_write (dev,MC2 , (MASK_09 |MASK_25 |MASK_10 |MASK_26 )); }else if (dev->pci->subsystem_vendor ==0x110a ) {
@@ -4754,17 +4736,52 @@av7110_setup_irc_config (av7110,0 );av7110_register (av7110); +/* special case DVB-C: these cards have an analog tuner +plus need some special handling, so we have separate +saa7146_ext_vv data for these... */ +if (0 != av7110->has_analog_tuner) { + ret =saa7146_vv_init (dev, &av7110_vv_data_c); + }else { + ret =saa7146_vv_init (dev, &av7110_vv_data_st); + } + +if (0 != ret) { +ERR (("cannot init capture device. skipping.\n" )); + ret = -ENODEV ; + goto err; + } + +if (saa7146_register_device (&av7110->v4l_dev, dev,"av7110" ,VFL_TYPE_GRABBER )) { +ERR (("cannot register capture device. skipping.\n" )); + ret = -ENODEV ; + goto video_err; + } + +if (0 != av7110->has_analog_tuner) { +if (0 !=saa7146_register_device (&av7110->vbi_dev, dev,"av7110" ,VFL_TYPE_VBI )) { +ERR (("cannot register vbi v4l2 device. skipping.\n" )); + } +/* we use this to remember that this dvb-c card cannot do vbi */ + av7110->has_analog_tuner =2 ; + } +printk (KERN_INFO "av7110: found av7110-%d.\n" ,av7110_num); av7110_num++;return 0 ; +video_err: +saa7146_vv_release (dev); + err: -if (av7110 ) +if (NULL != av7110 ) {kfree (av7110); - -/* FIXME: error handling is pretty bogus: memory does not get freed...*/ -saa7146_unregister_device (&av7110->v4l_dev, dev); -saa7146_vv_release (dev); + } +if (NULL != av7110->debi_virt) { +pci_free_consistent (dev->pci,8192 , av7110->debi_virt, av7110->debi_bus); + } +if (NULL != av7110->iobuf) { +vfree (av7110->iobuf); + }dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id);
@@ -4780,6 +4797,9 @@DEB_EE (("av7110: %p\n" ,av7110));saa7146_unregister_device (&av7110->v4l_dev, saa); +if (2 == av7110->has_analog_tuner) { +saa7146_unregister_device (&av7110->vbi_dev, saa); + } av7110->arm_rmmod=1 ;wake_up_interruptible (&av7110->arm_wait);
@@ -4948,8 +4968,8 @@static struct saa7146_ext_vv av7110_vv_data_c = { .inputs =1 , .audios =1 , - .capabilities =V4L2_CAP_TUNER , - .flags =0 , + .capabilities =V4L2_CAP_TUNER |V4L2_CAP_VBI_CAPTURE , + .flags =SAA7146_USE_PORT_B_FOR_VBI , .stds = &standard[0 ], .num_stds =sizeof (standard)/sizeof (struct saa7146_standard ),
drivers/media/dvb/ttpci/av7110.h +3 -1
@@ -399,14 +399,16 @@struct dvb_device dvb_dev;struct dvb_net dvb_net; +struct video_device v4l_dev; +struct video_device vbi_dev;struct saa7146_dev *dev;struct dvb_i2c_bus *i2c_bus;char *card_name; -/* support for analog module of dvb-c */ +/* support for analog module of dvb-c */ int has_analog_tuner;int current_input;u32 current_freq;