* [PATCH 0/7] LinuxTV.org DVB driver update @ 2003-10-09 10:47 Michael Hunold 2003-10-09 10:47 ` [PATCH 1/7] New DVB frontend driver ves1x93 (obsoletes alps_bsrv2) Michael Hunold 0 siblings, 1 reply; 8+ messages in thread From: Michael Hunold @ 2003-10-09 10:47 UTC (permalink / raw) To: torvalds, linux-kernel 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. ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/7] New DVB frontend driver ves1x93 (obsoletes alps_bsrv2) 2003-10-09 10:47 [PATCH 0/7] LinuxTV.org DVB driver update Michael Hunold @ 2003-10-09 10:47 ` Michael Hunold 2003-10-09 10:47 ` [PATCH 2/7] Fix vbi handling in saa7146 core driver Michael Hunold 0 siblings, 1 reply; 8+ messages in thread From: Michael Hunold @ 2003-10-09 10:47 UTC (permalink / raw) To: torvalds, linux-kernel - [DVB] - replace alps_bsrv2 driver by generic ves1893 & ves1993 driver (Andreas Oberritter) diff -uNrwB --new-file xx-linux-2.6.0-test7/drivers/media/dvb/frontends/alps_bsrv2.c linux-2.6.0-test7-ar/drivers/media/dvb/frontends/alps_bsrv2.c --- xx-linux-2.6.0-test7/drivers/media/dvb/frontends/alps_bsrv2.c 2003-09-10 11:28:41.000000000 +0200 +++ linux-2.6.0-test7-ar/drivers/media/dvb/frontends/alps_bsrv2.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,469 +0,0 @@ -/* - Driver for Alps BSRV2 QPSK Frontend - - Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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/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"); - diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/ves1x93.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/ves1x93.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/ves1x93.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/ves1x93.c 2003-10-09 10:44:10.000000000 +0200 @@ -0,0 +1,619 @@ +/* + Driver for VES1893 and VES1993 QPSK Frontends + + Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de> + Copyright (C) 2001 Ronny Strutz <3des@tuxbox.org> + Copyright (C) 2002 Dennis Noermann <dennis.noermann@noernet.de> + Copyright (C) 2002-2003 Andreas Oberritter <obi@tuxbox.org> + + 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 int board_type = 0; +#define BOARD_SIEMENS_PCI 0 +#define BOARD_NOKIA_DBOX2 1 +#define BOARD_SAGEM_DBOX2 2 + +static int demod_type = 0; +#define DEMOD_VES1893 0 +#define DEMOD_VES1993 1 + +static struct dvb_frontend_info ves1x93_info = { + .name = "VES1x93", + .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 +}; + + +/** + * nokia dbox2 (ves1893) and sagem dbox2 (ves1993) + * need bit AGCR[PWMS] set to 1 + */ + +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_1993_tab [] = { + 0x00, 0x9c, 0x35, 0x80, 0x6a, 0x09, 0x72, 0x8c, + 0x09, 0x6b, 0x00, 0x00, 0x4c, 0x08, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x40, 0x21, 0xb0, 0x00, 0x00, 0x00, 0x10, + 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x0e, 0x80, 0x00 +}; + + +static u8 * init_1x93_tab; + + +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 u8 init_1993_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,1,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,1,1, 1,1,1,1,1 +}; + + +static int ves1x93_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 ves1x93_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 tuner_write (struct dvb_i2c_bus *i2c, u8 *data, u8 len) +{ + int ret; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = len }; + + ves1x93_writereg(i2c, 0x00, 0x11); + ret = i2c->xfer (i2c, &msg, 1); + ves1x93_writereg(i2c, 0x00, 0x01); + + 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 tuner_write (i2c, buf, sizeof(buf)); +} + + +static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +{ + int ret; + u8 buf [2]; + + freq /= 1000; + + buf[0] = (freq >> 8) & 0x7F; + buf[1] = freq & 0xFF; + + ret = tuner_write(i2c, buf, sizeof(buf)); + + return ret; +} + + +static int tuner_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +{ + if ((demod_type == DEMOD_VES1893) && (board_type == BOARD_SIEMENS_PCI)) + return sp5659_set_tv_freq (i2c, freq, pwr); + else if (demod_type == DEMOD_VES1993) + return tsa5059_set_tv_freq (i2c, freq); + + return -EINVAL; +} + + +static int ves1x93_init (struct dvb_i2c_bus *i2c) +{ + int i; + int size; + u8 *init_1x93_wtab; + + dprintk("%s: init chip\n", __FUNCTION__); + + switch (demod_type) { + case DEMOD_VES1893: + init_1x93_tab = init_1893_tab; + init_1x93_wtab = init_1893_wtab; + size = sizeof(init_1893_tab); + if (board_type == BOARD_NOKIA_DBOX2) + init_1x93_tab[0x05] |= 0x20; /* invert PWM */ + break; + + case DEMOD_VES1993: + init_1x93_tab = init_1993_tab; + init_1x93_wtab = init_1993_wtab; + size = sizeof(init_1993_tab); + if (board_type == BOARD_SAGEM_DBOX2) + init_1x93_tab[0x05] |= 0x20; /* invert PWM */ + break; + + default: + return -EINVAL; + } + + for (i = 0; i < size; i++) + if (init_1x93_wtab[i]) + ves1x93_writereg (i2c, i, init_1x93_tab[i]); + + if (demod_type == DEMOD_VES1993) { + if (board_type == BOARD_NOKIA_DBOX2) + tuner_write(i2c, "\x06\x5c\x83\x60", 4); + else if (board_type == BOARD_SAGEM_DBOX2) + tuner_write(i2c, "\x25\x70\x92\x40", 4); + } + + return 0; +} + + +static int ves1x93_clr_bit (struct dvb_i2c_bus *i2c) +{ + ves1x93_writereg (i2c, 0, init_1x93_tab[0] & 0xfe); + ves1x93_writereg (i2c, 0, init_1x93_tab[0]); + ves1x93_writereg (i2c, 3, 0x00); + return ves1x93_writereg (i2c, 3, init_1x93_tab[3]); +} + + +static int ves1x93_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_1x93_tab[0x0c] = (init_1x93_tab[0x0c] & 0x3f) | val; + + return ves1x93_writereg (i2c, 0x0c, init_1x93_tab[0x0c]); +} + + +static int ves1x93_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) +{ + if (fec == FEC_AUTO) + return ves1x93_writereg (i2c, 0x0d, 0x08); + else if (fec < FEC_1_2 || fec > FEC_8_9) + return -EINVAL; + else + return ves1x93_writereg (i2c, 0x0d, fec - FEC_1_2); +} + + +static fe_code_rate_t ves1x93_get_fec (struct dvb_i2c_bus *i2c) +{ + return FEC_1_2 + ((ves1x93_readreg (i2c, 0x0d) >> 4) & 0x7); +} + + +static int ves1x93_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +{ + u32 BDR; + u32 ratio; + u8 ADCONF, FCONF, FNR; + u32 BDRI; + u32 tmp; + u32 XIN, FIN; + + dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate); + + switch (board_type) { + case BOARD_SIEMENS_PCI: + XIN = 90100000UL; + break; + case BOARD_NOKIA_DBOX2: + if (demod_type == DEMOD_VES1893) + XIN = 91000000UL; + else if (demod_type == DEMOD_VES1993) + XIN = 96000000UL; + else + return -EINVAL; + break; + case BOARD_SAGEM_DBOX2: + XIN = 92160000UL; + break; + default: + return -EINVAL; + } + + if (srate > XIN/2) + srate = XIN/2; + + if (srate < 500000) + srate = 500000; + +#define MUL (1UL<<26) + + FIN = (XIN + 6000) >> 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); + /*FCONF = 0x80 | ((FNR & 0x01) << 5) | (((FNR > 1) & 0x03) << 3) | ((FNR >> 1) & 0x07);*/ + } + + 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; + + ves1x93_writereg (i2c, 0x06, 0xff & BDR); + ves1x93_writereg (i2c, 0x07, 0xff & (BDR >> 8)); + ves1x93_writereg (i2c, 0x08, 0x0f & (BDR >> 16)); + + ves1x93_writereg (i2c, 0x09, BDRI); + ves1x93_writereg (i2c, 0x20, ADCONF); + ves1x93_writereg (i2c, 0x21, FCONF); + + if (srate < 6000000) + ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] | 0x80); + else + ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] & 0x7f); + + ves1x93_writereg (i2c, 0x00, 0x00); + ves1x93_writereg (i2c, 0x00, 0x01); + + /* ves1993 hates this, will lose lock */ + if (demod_type != DEMOD_VES1993) + ves1x93_clr_bit (i2c); + + return 0; +} + + +static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +{ + switch (voltage) { + case SEC_VOLTAGE_13: + return ves1x93_writereg (i2c, 0x1f, 0x20); + case SEC_VOLTAGE_18: + return ves1x93_writereg (i2c, 0x1f, 0x30); + case SEC_VOLTAGE_OFF: + return ves1x93_writereg (i2c, 0x1f, 0x00); + default: + return -EINVAL; + } +} + + +static int ves1x93_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, &ves1x93_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: + { + fe_status_t *status = arg; + u8 sync = ves1x93_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 = ves1x93_readreg (i2c, 0x15); + *ber |= (ves1x93_readreg (i2c, 0x16) << 8); + *ber |= ((ves1x93_readreg (i2c, 0x17) & 0x0F) << 16); + *ber *= 10; + break; + } + + case FE_READ_SIGNAL_STRENGTH: + { + u8 signal = ~ves1x93_readreg (i2c, 0x0b); + *((u16*) arg) = (signal << 8) | signal; + break; + } + + case FE_READ_SNR: + { + u8 snr = ~ves1x93_readreg (i2c, 0x1c); + *(u16*) arg = (snr << 8) | snr; + break; + } + + case FE_READ_UNCORRECTED_BLOCKS: + { + *(u32*) arg = ves1x93_readreg (i2c, 0x18) & 0x7f; + + if (*(u32*) arg == 0x7f) + *(u32*) arg = 0xffffffff; /* counter overflow... */ + + ves1x93_writereg (i2c, 0x18, 0x00); /* reset the counter */ + ves1x93_writereg (i2c, 0x18, 0x80); /* dto. */ + break; + } + + case FE_SET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + + tuner_set_tv_freq (i2c, p->frequency, 0); + ves1x93_set_inversion (i2c, p->inversion); + ves1x93_set_fec (i2c, p->u.qpsk.fec_inner); + ves1x93_set_symbolrate (i2c, p->u.qpsk.symbol_rate); + break; + } + + case FE_GET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + int afc; + + afc = ((int)((char)(ves1x93_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_1x93_tab[0x0c] & 0x80)) + p->inversion = (ves1x93_readreg (i2c, 0x0f) & 2) ? + INVERSION_OFF : INVERSION_ON; + p->u.qpsk.fec_inner = ves1x93_get_fec (i2c); + /* XXX FIXME: timing offset !! */ + break; + } + + case FE_SLEEP: + if (board_type == BOARD_SIEMENS_PCI) + ves1x93_writereg (i2c, 0x1f, 0x00); /* LNB power off */ + return ves1x93_writereg (i2c, 0x00, 0x08); + + case FE_INIT: + return ves1x93_init (i2c); + + case FE_RESET: + return ves1x93_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 ves1x93_set_voltage (i2c, (fe_sec_voltage_t) arg); + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + + +static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data) +{ + u8 identity = ves1x93_readreg(i2c, 0x1e); + + switch (identity) { + case 0xdc: /* VES1893A rev1 */ + case 0xdd: /* VES1893A rev2 */ + demod_type = DEMOD_VES1893; + ves1x93_info.name[4] = '8'; + break; + case 0xde: /* VES1993 */ + demod_type = DEMOD_VES1993; + ves1x93_info.name[4] = '9'; + break; + default: + dprintk("VES1x93 not found (identity %02x)\n", identity); + return -ENODEV; + } + + return dvb_register_frontend (ves1x93_ioctl, i2c, NULL, &ves1x93_info); +} + + +static void ves1x93_detach (struct dvb_i2c_bus *i2c, void *data) +{ + dvb_unregister_frontend (ves1x93_ioctl, i2c); +} + + +static int __init init_ves1x93 (void) +{ + switch (board_type) { + case BOARD_NOKIA_DBOX2: + dprintk("%s: NOKIA_DBOX2\n", __FILE__); + break; + case BOARD_SAGEM_DBOX2: + dprintk("%s: SAGEM_DBOX2\n", __FILE__); + break; + case BOARD_SIEMENS_PCI: + dprintk("%s: SIEMENS_PCI\n", __FILE__); + break; + default: + return -EIO; + } + + return dvb_register_i2c_device (THIS_MODULE, ves1x93_attach, ves1x93_detach); +} + + +static void __exit exit_ves1x93 (void) +{ + dvb_unregister_i2c_device (ves1x93_attach); +} + + +module_init(init_ves1x93); +module_exit(exit_ves1x93); + + +MODULE_DESCRIPTION("VES1x93 DVB-S Frontend"); +MODULE_AUTHOR("Ralph Metzler"); +MODULE_LICENSE("GPL"); +MODULE_PARM(debug,"i"); +MODULE_PARM(board_type,"i"); + diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/Kconfig linux-2.6.0-test7-patch/drivers/media/dvb/frontends/Kconfig --- linux-2.6.0-test7/drivers/media/dvb/frontends/Kconfig 2003-10-09 10:40:18.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/Kconfig 2003-10-08 10:51:15.000000000 +0200 @@ -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 diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/Makefile linux-2.6.0-test7-patch/drivers/media/dvb/frontends/Makefile --- linux-2.6.0-test7/drivers/media/dvb/frontends/Makefile 2003-10-09 10:40:18.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/Makefile 2003-10-08 10:51:15.000000000 +0200 @@ -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 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/7] Fix vbi handling in saa7146 core driver 2003-10-09 10:47 ` [PATCH 1/7] New DVB frontend driver ves1x93 (obsoletes alps_bsrv2) Michael Hunold @ 2003-10-09 10:47 ` Michael Hunold 2003-10-09 10:47 ` [PATCH 3/7] Add private data pointer to DVB frontends Michael Hunold 0 siblings, 1 reply; 8+ messages in thread From: Michael Hunold @ 2003-10-09 10:47 UTC (permalink / raw) To: torvalds, linux-kernel - [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 diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/common/saa7146_fops.c linux-2.6.0-test7-patch/drivers/media/common/saa7146_fops.c --- linux-2.6.0-test7/drivers/media/common/saa7146_fops.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/common/saa7146_fops.c 2003-10-06 18:36:47.000000000 +0200 @@ -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; } diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/common/saa7146_vbi.c linux-2.6.0-test7-patch/drivers/media/common/saa7146_vbi.c --- linux-2.6.0-test7/drivers/media/common/saa7146_vbi.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/common/saa7146_vbi.c 2003-10-06 18:45:08.000000000 +0200 @@ -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) diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/common/saa7146_video.c linux-2.6.0-test7-patch/drivers/media/common/saa7146_video.c --- linux-2.6.0-test7/drivers/media/common/saa7146_video.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/common/saa7146_video.c 2003-09-30 19:15:11.000000000 +0200 @@ -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); diff -uNrwB --new-file linux-2.6.0-test7/include/media/saa7146_vv.h linux-2.6.0-test7-patch/include/media/saa7146_vv.h --- linux-2.6.0-test7/include/media/saa7146_vv.h 2003-10-09 10:40:54.000000000 +0200 +++ linux-2.6.0-test7-patch/include/media/saa7146_vv.h 2003-10-06 16:54:55.000000000 +0200 @@ -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 { ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/7] Add private data pointer to DVB frontends 2003-10-09 10:47 ` [PATCH 2/7] Fix vbi handling in saa7146 core driver Michael Hunold @ 2003-10-09 10:47 ` Michael Hunold 2003-10-09 10:47 ` [PATCH 4/7] Fix DVB network device handling Michael Hunold 0 siblings, 1 reply; 8+ messages in thread From: Michael Hunold @ 2003-10-09 10:47 UTC (permalink / raw) To: torvalds, linux-kernel - [DVB] allow private data to be associated with dvb frontend devices (Andreas Oberritter) - [DVB] fixed fe_count countint in nxt6000 frontend driver (Andreas Oberritter) diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/ttusb-dec/dec2000_frontend.c linux-2.6.0-test7-patch/drivers/media/dvb/ttusb-dec/dec2000_frontend.c --- linux-2.6.0-test7/drivers/media/dvb/ttusb-dec/dec2000_frontend.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/ttusb-dec/dec2000_frontend.c 2003-10-09 10:44:10.000000000 +0200 @@ -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__); diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/dvb-core/dvb_i2c.c linux-2.6.0-test7-patch/drivers/media/dvb/dvb-core/dvb_i2c.c --- linux-2.6.0-test7/drivers/media/dvb/dvb-core/dvb_i2c.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/dvb-core/dvb_i2c.c 2003-10-09 10:44:10.000000000 +0200 @@ -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; diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/dvb-core/dvb_i2c.h linux-2.6.0-test7-patch/drivers/media/dvb/dvb-core/dvb_i2c.h --- linux-2.6.0-test7/drivers/media/dvb/dvb-core/dvb_i2c.h 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/dvb-core/dvb_i2c.h 2003-10-09 10:44:10.000000000 +0200 @@ -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 diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/alps_tdmb7.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/alps_tdmb7.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/alps_tdmb7.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/alps_tdmb7.c 2003-10-09 10:44:10.000000000 +0200 @@ -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__); diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/cx24110.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/cx24110.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/cx24110.c 2003-10-09 10:40:18.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/cx24110.c 2003-10-09 10:44:10.000000000 +0200 @@ -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); } diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/dvb_dummy_fe.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/dvb_dummy_fe.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/dvb_dummy_fe.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/dvb_dummy_fe.c 2003-10-09 10:44:10.000000000 +0200 @@ -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; } diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/grundig_29504-401.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/grundig_29504-401.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/grundig_29504-401.c 2003-10-09 10:40:18.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/grundig_29504-401.c 2003-10-09 10:44:10.000000000 +0200 @@ -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); } diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/grundig_29504-491.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/grundig_29504-491.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/grundig_29504-491.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/grundig_29504-491.c 2003-10-09 10:44:10.000000000 +0200 @@ -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); } diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/mt312.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/mt312.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/mt312.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/mt312.c 2003-10-09 10:44:10.000000000 +0200 @@ -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); diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/nxt6000.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/nxt6000.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/nxt6000.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/nxt6000.c 2003-10-09 10:44:10.000000000 +0200 @@ -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"); diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/sp887x.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/sp887x.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/sp887x.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/sp887x.c 2003-10-09 10:44:10.000000000 +0200 @@ -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); diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/stv0299.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/stv0299.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/stv0299.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/stv0299.c 2003-10-09 10:44:10.000000000 +0200 @@ -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); } diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/tda1004x.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/tda1004x.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/tda1004x.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/tda1004x.c 2003-10-09 10:44:10.000000000 +0200 @@ -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__); diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/ves1820.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/ves1820.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/ves1820.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/ves1820.c 2003-10-09 10:44:10.000000000 +0200 @@ -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); } ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/7] Fix DVB network device handling 2003-10-09 10:47 ` [PATCH 3/7] Add private data pointer to DVB frontends Michael Hunold @ 2003-10-09 10:47 ` Michael Hunold 2003-10-09 10:47 ` [PATCH 5/7] Misc. fixes for ALPS TDLB7 DVB frontend driver Michael Hunold 0 siblings, 1 reply; 8+ messages in thread From: Michael Hunold @ 2003-10-09 10:47 UTC (permalink / raw) To: torvalds, linux-kernel - [DVB] simplify and sanitize add/del handling for dvb net devices diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/dvb-core/dvb_net.c linux-2.6.0-test7-patch/drivers/media/dvb/dvb-core/dvb_net.c --- linux-2.6.0-test7/drivers/media/dvb/dvb-core/dvb_net.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/dvb-core/dvb_net.c 2003-09-10 12:38:22.000000000 +0200 @@ -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; } diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/dvb-core/dvb_net.h linux-2.6.0-test7-patch/drivers/media/dvb/dvb-core/dvb_net.h --- linux-2.6.0-test7/drivers/media/dvb/dvb-core/dvb_net.h 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/dvb-core/dvb_net.h 2003-08-25 12:16:12.000000000 +0200 @@ -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; }; ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 5/7] Misc. fixes for ALPS TDLB7 DVB frontend driver 2003-10-09 10:47 ` [PATCH 4/7] Fix DVB network device handling Michael Hunold @ 2003-10-09 10:47 ` Michael Hunold 2003-10-09 10:47 ` [PATCH 6/7] Misc. fixes for AT76C651 " Michael Hunold 0 siblings, 1 reply; 8+ messages in thread From: Michael Hunold @ 2003-10-09 10:47 UTC (permalink / raw) To: torvalds, linux-kernel - [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. diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/alps_tdlb7.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/alps_tdlb7.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/alps_tdlb7.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/alps_tdlb7.c 2003-10-09 10:44:10.000000000 +0200 @@ -1,7 +1,7 @@ /* Driver for Alps TDLB7 Frontend - Copyright (C) 1999 Juergen Peitz <peitz@snafu.de> + 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 0x0A static 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"); ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 6/7] Misc. fixes for AT76C651 DVB frontend driver 2003-10-09 10:47 ` [PATCH 5/7] Misc. fixes for ALPS TDLB7 DVB frontend driver Michael Hunold @ 2003-10-09 10:47 ` Michael Hunold 2003-10-09 10:47 ` [PATCH 7/7] Update the AV7110 DVB driver Michael Hunold 0 siblings, 1 reply; 8+ messages in thread From: Michael Hunold @ 2003-10-09 10:47 UTC (permalink / raw) To: torvalds, linux-kernel - [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) diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/frontends/at76c651.c linux-2.6.0-test7-patch/drivers/media/dvb/frontends/at76c651.c --- linux-2.6.0-test7/drivers/media/dvb/frontends/at76c651.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/frontends/at76c651.c 2003-10-09 10:44:10.000000000 +0200 @@ -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 <andreas@oberritter.de>"); -#ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); -#endif MODULE_PARM(debug, "i"); -#endif ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 7/7] Update the AV7110 DVB driver 2003-10-09 10:47 ` [PATCH 6/7] Misc. fixes for AT76C651 " Michael Hunold @ 2003-10-09 10:47 ` Michael Hunold 0 siblings, 0 replies; 8+ messages in thread From: Michael Hunold @ 2003-10-09 10:47 UTC (permalink / raw) To: torvalds, linux-kernel - [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) diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/ttpci/av7110.c linux-2.6.0-test7-patch/drivers/media/dvb/ttpci/av7110.c --- linux-2.6.0-test7/drivers/media/dvb/ttpci/av7110.c 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/ttpci/av7110.c 2003-10-09 10:30:43.000000000 +0200 @@ -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), diff -uNrwB --new-file linux-2.6.0-test7/drivers/media/dvb/ttpci/av7110.h linux-2.6.0-test7-patch/drivers/media/dvb/ttpci/av7110.h --- linux-2.6.0-test7/drivers/media/dvb/ttpci/av7110.h 2003-10-09 10:40:19.000000000 +0200 +++ linux-2.6.0-test7-patch/drivers/media/dvb/ttpci/av7110.h 2003-10-06 15:31:36.000000000 +0200 @@ -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; ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2003-10-09 10:55 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2003-10-09 10:47 [PATCH 0/7] LinuxTV.org DVB driver update Michael Hunold 2003-10-09 10:47 ` [PATCH 1/7] New DVB frontend driver ves1x93 (obsoletes alps_bsrv2) Michael Hunold 2003-10-09 10:47 ` [PATCH 2/7] Fix vbi handling in saa7146 core driver Michael Hunold 2003-10-09 10:47 ` [PATCH 3/7] Add private data pointer to DVB frontends Michael Hunold 2003-10-09 10:47 ` [PATCH 4/7] Fix DVB network device handling Michael Hunold 2003-10-09 10:47 ` [PATCH 5/7] Misc. fixes for ALPS TDLB7 DVB frontend driver Michael Hunold 2003-10-09 10:47 ` [PATCH 6/7] Misc. fixes for AT76C651 " Michael Hunold 2003-10-09 10:47 ` [PATCH 7/7] Update the AV7110 DVB driver Michael Hunold
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox