All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 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 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, &reg0xc05)))
+		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 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.