public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/12] LinuxTV.org DVB+V4L fixes
@ 2003-12-19 12:28 Michael Hunold
  2003-12-19 12:28 ` [PATCH 1/12] Remove firmware of av7110 driver Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

Hello Andrew, hello Linus,

because of the "stable freeze" 2.6.0 release a bunch of patches
for the DVB subsystem has piled up. 8-)

These 12 patches try to sync the DVB drivers hosted by
http://www.linuxtv.org with 2.6.0.

As usual, detailed descriptions are at the beginning of each patch.

Please note that patch "01-DVB-av7110-firmware-removal.diff" now
finally removes the firmware blob for the dvb-ttpci driver, so the
patch is quite large and has only been sent to you in a separate mail.

We're planning to remove the firmware files from other drivers as well.

The firmware removal depends on the latest patch by Manuel Estrada Sainz
<ranty@debian.org> which is currently only in the -mm
tree.

It fixes firmware_class to use a kernel_thread instead of scheduling
a work queue which will freeze the system if you don't use the firmware
hotplug systems. I hope it's ok if you apply this cross-subsystem patch
this time, I'll write a separate mail to Manuel, too.

Please apply.

Thanks!
Michael.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/12] Remove firmware of av7110 driver
  2003-12-19 12:28 [PATCH 0/12] LinuxTV.org DVB+V4L fixes Michael Hunold
@ 2003-12-19 12:28 ` Michael Hunold
  2003-12-19 12:28   ` [PATCH 2/12] Update saa7146 capture core Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

... sent to Linus and Andrew in private only. 
It removes the firmware for the dvb-ttpci / av7110 driver, you can
do "rm drivers/media/dvb/ttpci/av7110_firm.h" as well.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 2/12] Update saa7146 capture core
  2003-12-19 12:28 ` [PATCH 1/12] Remove firmware of av7110 driver Michael Hunold
@ 2003-12-19 12:28   ` Michael Hunold
  2003-12-19 12:28     ` [PATCH 3/12] Add new DVB driver Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

V4L: - fix a bunch of race conditions and locking bugs in video and vbi capture code on device closure
V4L: - use vmalloc_32() instead of vmalloc() in saa7146_vmalloc_build_pgtable(). this makes sure that the pagetable is in lowmem kernel memory
V4L: - i2c timeout fix by Gerd Knorr 
V4L: - SAA7146_I2C_SHORT_DELAY flag to speed up I2C access by Oliver Endriss
V4L: - move saa7146_set_gpio() from saa7146_vv to saa7146_core, it's needed by DVB budget drivers
V4L: - add "new" saa7146_wait_for_debi_done() function, remove other versions from av7110 and budget.ci
V4L: - make budget-ci use this gpio function and the new wait_...() function,
V4L: - make saa7146_pgtable_build_single() deliver a return code, make sanity checks of the arguments
V4L: - sanitize enabling of video input pins and i2c pins, use some default values, so the hardware is always in a sane state
V4L: - remove SAA7146_EXT_SWAP_ODD_EVEN flag + handling, fix the hardware initialization instead
V4L: - change minimal picture size to 48x32 just like other drivers
V4L: - set up arbitrition control for video dma3 correctly
V4L: - remove unnecessary code for capture to framebuffer memory, it's handled in the generic code
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_core.c linux-2.6.0-p/drivers/media/common/saa7146_core.c
--- linux-2.6.0/drivers/media/common/saa7146_core.c	2003-12-18 03:59:06.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_core.c	2003-12-17 14:00:22.000000000 +0100
@@ -45,10 +45,65 @@
 #endif
 
 /****************************************************************************
+ * gpio and debi helper functions
+ ****************************************************************************/
+
+/* write "data" to the gpio-pin "pin" */
+void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
+{
+	u32 value = 0;
+
+	/* sanity check */
+	if(pin > 3)
+		return;
+
+	/* read old register contents */
+	value = saa7146_read(dev, GPIO_CTRL );
+	
+	value &= ~(0xff << (8*pin));
+	value |= (data << (8*pin));
+
+	saa7146_write(dev, GPIO_CTRL, value);
+}
+
+/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev)
+{
+	int start;
+
+	/* wait for registers to be programmed */
+	start = jiffies;
+	while (1) {
+                if (saa7146_read(dev, MC2) & 2)
+                        break;
+		if (jiffies-start > HZ/20) {
+			DEB_S(("timed out while waiting for registers getting programmed\n"));
+			return -ETIMEDOUT;
+		}
+	}
+
+	/* wait for transfer to complete */
+	start = jiffies;
+	while (1) {
+		if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
+			break;
+		saa7146_read(dev, MC2);
+		if (jiffies-start > HZ/4) {
+			DEB_S(("timed out while waiting for transfer completion\n"));
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+/****************************************************************************
  * general helper functions
  ****************************************************************************/
 
-/* this is videobuf_vmalloc_to_sg() from video-buf.c */
+/* this is videobuf_vmalloc_to_sg() from video-buf.c 
+   make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
+   may be triggered on highmem machines */
 static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
 {
 	struct scatterlist *sglist;
@@ -84,7 +139,7 @@
 {
 	struct scatterlist *slist = NULL;
 	int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
-	char *mem = vmalloc(length);
+	char *mem = vmalloc_32(length);
 	int slen = 0;
 
 	if (NULL == mem) {
@@ -103,7 +158,9 @@
 	}
 	
 	slen = pci_map_sg(pci,slist,pages,PCI_DMA_FROMDEVICE);
-	saa7146_pgtable_build_single(pci, pt, slist, slen);
+	if (0 != saa7146_pgtable_build_single(pci, pt, slist, slen)) {
+		return NULL;
+	}
 
 	/* fixme: here's a memory leak: slist never gets freed by any other
 	   function ...*/
@@ -139,7 +196,7 @@
 	return 0;
 }
 
-void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
+int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
 	struct scatterlist *list, int sglen  )
 {
 	u32   *ptr, fill;
@@ -148,6 +205,11 @@
 
 	BUG_ON( 0 == sglen);
 
+	if (list->offset > PAGE_SIZE) {
+		DEB_D(("offset > PAGE_SIZE. this should not happen."));
+		return -EINVAL;
+	}
+	
 	/* if we have a user buffer, the first page may not be
 	   aligned to a page boundary. */
 	pt->offset = list->offset;
@@ -177,6 +239,7 @@
 		printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
 	}
 */
+	return 0;
 }
 
 /********************************************************************************/
@@ -322,7 +384,7 @@
 	saa7146_write(dev, MC1, MASK_31);
 */
 
-	/* disable alle irqs */
+	/* disable all irqs */
 	saa7146_write(dev, IER, 0);
 
 	/* shut down all dma transfers */
@@ -381,8 +443,8 @@
 	dev->module = THIS_MODULE;
 	init_waitqueue_head(&dev->i2c_wq);
 
-	/* set some default values */
-	saa7146_write(dev, BCS_CTRL, 0x80400040);
+	/* set some sane pci arbitrition values */
+	saa7146_write(dev, PCI_BT_V1, 0x1c00101f); 
 
 	if( 0 != ext->probe) {
 		if( 0 != ext->probe(dev) ) {
@@ -508,6 +570,7 @@
 EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
 EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
 EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
 
 EXPORT_SYMBOL_GPL(saa7146_setgpio);
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_fops.c linux-2.6.0-p/drivers/media/common/saa7146_fops.c
--- linux-2.6.0/drivers/media/common/saa7146_fops.c	2003-12-18 03:58:49.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_fops.c	2003-12-18 12:18:53.000000000 +0100
@@ -86,7 +86,7 @@
 		return;
 	}
 
-	DEB_EE(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
+	DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
 
 #if DEBUG_SPINLOCKS
 	BUG_ON(!spin_is_locked(&dev->slock));
@@ -98,10 +98,10 @@
 		if (!list_empty(&q->queue))
 			next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
 		q->curr = buf;
-		DEB_D(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
+		DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
 		buf->activate(dev,buf,next);
 	} else {
-		DEB_D(("no next buffer. stopping.\n"));
+		DEB_INT(("no next buffer. stopping.\n"));
 		if( 0 != vbi ) {
 			/* turn off video-dma3 */
 			saa7146_write(dev,MC1, MASK_20);
@@ -229,10 +229,10 @@
 
 	if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
 		DEB_S(("initializing vbi...\n"));
-		saa7146_vbi_uops.open(dev,fh);
+		saa7146_vbi_uops.open(dev,file);
 	} else {
 		DEB_S(("initializing video...\n"));
-		saa7146_video_uops.open(dev,fh);
+		saa7146_video_uops.open(dev,file);
 	}
 
 	result = 0;
@@ -255,9 +255,9 @@
 		return -ERESTARTSYS;
 
 	if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		saa7146_vbi_uops.release(dev,fh,file);
+		saa7146_vbi_uops.release(dev,file);
 	} else {
-		saa7146_video_uops.release(dev,fh,file);
+		saa7146_video_uops.release(dev,file);
 	}
 
 	module_put(dev->ext->module);
@@ -372,7 +372,7 @@
 {
 	u32 isr = status;
 	
-	DEB_EE(("dev:%p, isr:0x%08x\n",dev,(u32)status));
+	DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
 
 	if (0 != (isr & (MASK_27))) {
 		DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
@@ -410,6 +410,12 @@
 
 	DEB_EE(("dev:%p\n",dev));
 	
+	/* set default values for video parts of the saa7146 */
+	saa7146_write(dev, BCS_CTRL, 0x80400040);
+
+	/* enable video-port pins */
+	saa7146_write(dev, MC1, (MASK_10 | MASK_26));
+
 	/* save per-device extension data (one extension can
 	   handle different devices that might need different
 	   configuration data) */
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_hlp.c linux-2.6.0-p/drivers/media/common/saa7146_hlp.c
--- linux-2.6.0/drivers/media/common/saa7146_hlp.c	2003-12-18 03:58:58.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_hlp.c	2003-11-20 11:01:06.000000000 +0100
@@ -660,24 +660,6 @@
 	vv->current_hps_sync = sync;
 } 
 
-/* write "data" to the gpio-pin "pin" */
-void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
-{
-	u32 value = 0;
-
-	/* sanity check */
-	if(pin > 3)
-		return;
-
-	/* read old register contents */
-	value = saa7146_read(dev, GPIO_CTRL );
-	
-	value &= ~(0xff << (8*pin));
-	value |= (data << (8*pin));
-
-	saa7146_write(dev, GPIO_CTRL, value);
-}
-
 /* reprogram hps, enable(1) / disable(0) video */
 void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v)
 {
@@ -710,13 +692,15 @@
 	/* calculate starting address */
 	where  = (which-1)*0x18;
 
+/*
 	if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
 		saa7146_write(dev, where, 	vdma->base_even);
 		saa7146_write(dev, where+0x04, 	vdma->base_odd);
 	} else {
+*/
 		saa7146_write(dev, where, 	vdma->base_odd);
 		saa7146_write(dev, where+0x04, 	vdma->base_even);
-	}
+//	}
 	saa7146_write(dev, where+0x08, 	vdma->prot_addr);
 	saa7146_write(dev, where+0x0c, 	vdma->pitch);
 	saa7146_write(dev, where+0x10, 	vdma->base_page);
@@ -971,12 +955,13 @@
 	unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
 	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
 
+/*
 	if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
 		unsigned long tmp = e_wait;
 		e_wait = o_wait;
 		o_wait = tmp;
 	}
-
+*/
 	/* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/
 	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait);
 	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_i2c.c linux-2.6.0-p/drivers/media/common/saa7146_i2c.c
--- linux-2.6.0/drivers/media/common/saa7146_i2c.c	2003-12-18 03:59:44.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_i2c.c	2003-12-10 14:06:57.000000000 +0100
@@ -186,7 +186,7 @@
 {
 	u32 status = 0, mc2 = 0;
 	int trial = 0;
-	int timeout;
+	unsigned long timeout;
 
 	/* write out i2c-command */
 	DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
@@ -218,7 +218,7 @@
 			if( 0 != mc2 ) {
 				break;
 			}
-			if (jiffies > timeout) {
+			if (time_after(jiffies,timeout)) {
 				printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n");
 				return -EIO;
 			}
@@ -233,7 +233,7 @@
 			status = saa7146_i2c_status(dev);
 			if ((status & 0x3) != 1)
 				break;
-			if (jiffies > timeout) {
+			if (time_after(jiffies,timeout)) {
 				/* this is normal when probing the bus
 				 * (no answer from nonexisistant device...)
 				 */
@@ -301,7 +301,8 @@
 		goto out;
 	}
 
-        if (count > 3) short_delay = 1;
+	if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
+		short_delay = 1;
   
 	do {
 		/* reset the i2c-device if necessary */
@@ -403,19 +404,29 @@
 {
 	DEB_EE(("bitrate: 0x%08x\n",bitrate));
 	
+	/* enable i2c-port pins */
+	saa7146_write(dev, MC1, (MASK_08 | MASK_24));
+
 	dev->i2c_bitrate = bitrate;
 	saa7146_i2c_reset(dev);
 
 	if( NULL != i2c_adapter ) {
 		memset(i2c_adapter,0,sizeof(struct i2c_adapter));
 		strcpy(i2c_adapter->name, dev->name);	
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+		i2c_adapter->data = dev;
+#else
 		i2c_set_adapdata(i2c_adapter,dev);
-		i2c_adapter->class	   = I2C_ADAP_CLASS_TV_ANALOG;
+#endif
 		i2c_adapter->algo	   = &saa7146_algo;
 		i2c_adapter->algo_data     = NULL;
 		i2c_adapter->id 	   = I2C_ALGO_SAA7146;
 		i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
 		i2c_adapter->retries = SAA7146_I2C_RETRIES;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#else
+		i2c_adapter->class = I2C_ADAP_CLASS_TV_ANALOG;
+#endif
 	}
 	
 	return 0;
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_vbi.c linux-2.6.0-p/drivers/media/common/saa7146_vbi.c
--- linux-2.6.0/drivers/media/common/saa7146_vbi.c	2003-12-18 03:57:59.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_vbi.c	2003-12-15 21:51:01.000000000 +0100
@@ -41,7 +41,11 @@
 	/* 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 | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
+		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
+/*
 		WRITE_RPS1(CMD_PAUSE | MASK_09);
+*/
 	} else {
 		DEB_D(("...using port a\n"));
 		WRITE_RPS1(CMD_PAUSE | MASK_10);
@@ -137,10 +141,10 @@
 	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
 
 /*
-	vdma3.base_even	= (u32)dev->ov_fb.base+2048*70;
-	vdma3.base_odd	= (u32)dev->ov_fb.base;
-	vdma3.prot_addr	= (u32)dev->ov_fb.base+2048*164;
-	vdma3.pitch	= 2048;
+	vdma3.base_even	= 0xc8000000+2560*70;
+	vdma3.base_odd	= 0xc8000000;
+	vdma3.prot_addr	= 0xc8000000+2560*164;
+	vdma3.pitch	= 2560;
 	vdma3.base_page	= 0;
 	vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above!
 */
@@ -244,7 +249,9 @@
 		err = videobuf_iolock(dev->pci,&buf->vb,NULL);
 		if (err)
 			goto oops;
-		saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
+		err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
+		if (0 != err)
+			return err;
 	}
 	buf->vb.state = STATE_PREPARED;
 	buf->activate = buffer_activate;
@@ -303,7 +310,7 @@
 
 /* ------------------------------------------------------------------ */
 
-static void vbi_stop(struct saa7146_fh *fh)
+static void vbi_stop(struct saa7146_fh *fh, struct file *file)
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
@@ -321,23 +328,29 @@
 	/* shut down dma 3 transfers */
 	saa7146_write(dev, MC1, MASK_20);
 
+	if (vv->vbi_q.curr) {
+		saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
+	}
+
+	videobuf_queue_cancel(file,&fh->vbi_q);
+
 	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);
 }
 
 static void vbi_read_timeout(unsigned long data)
 {
-	struct saa7146_fh *fh = (struct saa7146_fh *)data;
+	struct file *file = (struct file*)data;
+	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_dev *dev = fh->dev;
 	
 	DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
 
-	vbi_stop(fh);
+	vbi_stop(fh, file);
 }
 
 static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
@@ -354,10 +367,21 @@
 	init_waitqueue_head(&vv->vbi_wq);
 }
 
-static void vbi_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
+static void vbi_open(struct saa7146_dev *dev, struct file *file)
 {
+	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+	
+	u32 arbtr_ctrl	= saa7146_read(dev, PCI_BT_V1);
+	int ret = 0;
+	
 	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
 
+	/* adjust arbitrition control for video dma 3 */
+	arbtr_ctrl &= ~0x1f0000;
+	arbtr_ctrl |=  0x1d0000;
+	saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
+	saa7146_write(dev, MC2, (MASK_04|MASK_20));		
+	
 	memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt));
 
 	fh->vbi_fmt.sampling_rate	= 27000000;
@@ -380,21 +404,32 @@
 
 	init_timer(&fh->vbi_read_timeout);
 	fh->vbi_read_timeout.function = vbi_read_timeout;
-	fh->vbi_read_timeout.data = (unsigned long)fh;
+	fh->vbi_read_timeout.data = (unsigned long)file;
 
-	/* fixme: enable this again, if the dvb-c w/ analog module work properly */
-/*
-	vbi_workaround(dev);
-*/
+	/* initialize the brs */
+	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
+		saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19));
+	} else {
+		saa7146_write(dev, BRS_CTRL, 0x00000001);
+
+		if (0 != (ret = vbi_workaround(dev))) {
+			DEB_VBI(("vbi workaround failed!\n"));
+			/* return ret;*/
+		}
+	}
+
+	/* upload brs register */
+	saa7146_write(dev, MC2, (MASK_08|MASK_24));		
 }
 
-static void vbi_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file)
+static void vbi_close(struct saa7146_dev *dev, struct file *file)
 {
+	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
 	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
 
 	if( fh == vv->vbi_streaming ) {
-		vbi_stop(fh);
+		vbi_stop(fh, file);
 	}
 }
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_video.c linux-2.6.0-p/drivers/media/common/saa7146_video.c
--- linux-2.6.0/drivers/media/common/saa7146_video.c	2003-12-18 03:59:05.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_video.c	2003-12-17 14:00:22.000000000 +0100
@@ -116,7 +116,7 @@
 		DEB_D(("no fb fmt set.\n"));
 		return -EINVAL;
 	}
-	if (win->w.width < 64 || win->w.height <  64) {
+	if (win->w.width < 48 || win->w.height <  32) {
 		DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height));
 		return -EINVAL;
 	}
@@ -661,7 +661,7 @@
 */				
 	} else {
 		struct saa7146_pgtable *pt = &buf->pt[0];
-		saa7146_pgtable_build_single(pci, pt, list, length);
+		return saa7146_pgtable_build_single(pci, pt, list, length);
 	}
 
 	return 0;
@@ -704,7 +704,7 @@
 	return 0;
 }
 
-static int video_end(struct saa7146_fh *fh)
+static int video_end(struct saa7146_fh *fh, struct file *file)
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
@@ -735,82 +735,11 @@
 	saa7146_write(dev, MC1, 0x00700000);
 
 	vv->streaming = NULL;
-	spin_unlock_irqrestore(&dev->slock, flags);
-	
-	return 0;
-}
-
-/* capturing to framebuffer */
-
-int overlay_reqbufs(struct saa7146_dev *dev, struct v4l2_requestbuffers *req)
-{
-/*	struct saa7146_fh *fh = file->private_data;
 
-	if (req->count > VIDEO_MAX_FRAME)
-		req->count = VIDEO_MAX_FRAME;
-
-	*size = fh->video_fmt.sizeimage;
-
-*/
-	return 0;
-}
-int overlay_querybuf(struct saa7146_dev *dev, struct v4l2_buffer *buf)
-{
-	return 0;
-}
-int overlay_qbuf(struct saa7146_dev *dev, struct v4l2_buffer *b)
-{
-/*	if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {
-		DEB_D(("index %d out of bounds.\n",b->index));
-		goto -EINVAL;
-	}
-	
-	buf = q->bufs[b->index];
-	if (NULL == buf) {
-		printk("videobuf_qbuf: NULL == buf\n");
-		goto done;
-	}
-	if (0 == buf->baddr) {
-		printk("videobuf_qbuf: 0 == buf->baddr\n");
-		goto done;
-	}
-	if (buf->state == STATE_QUEUED ||
-	    buf->state == STATE_ACTIVE) {
-		printk("videobuf_qbuf: already queued or activated.\n");
-		goto done;
-	}
-
-	field = videobuf_next_field(q);
-	retval = q->ops->buf_prepare(file,buf,field);
-	if (0 != retval) {
-		printk("videobuf_qbuf: buf_prepare() failed.\n");
-		goto done;
-	}
+	videobuf_queue_cancel(file,&fh->video_q);
 	
-	list_add_tail(&buf->stream,&q->stream);
-	if (q->streaming) {
-		spin_lock_irqsave(q->irqlock,flags);
-		q->ops->buf_queue(file,buf);
-		spin_unlock_irqrestore(q->irqlock,flags);
-	}
-	retval = 0;
+	spin_unlock_irqrestore(&dev->slock, flags);
 	
- done:
-	up(&q->lock);
-	return retval;
-*/
-	return 0;
-}
-int overlay_dqbuf(struct saa7146_dev *dev, struct v4l2_buffer *buf)
-{
-	return 0;
-}
-int overlay_streamon(struct saa7146_dev *dev)
-{
-	return 0;
-}
-int overlay_streamoff(struct saa7146_dev *dev)
-{
 	return 0;
 }
 
@@ -818,7 +746,7 @@
 /*
  * This function is _not_ called directly, but from
  * video_generic_ioctl (and maybe others).  userspace
- * copying is done already, arg is a kernel fhinter.
+ * copying is done already, arg is a kernel pointer.
  */
 
 int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
@@ -1141,38 +1069,24 @@
 	case VIDIOC_REQBUFS: {
 		struct v4l2_requestbuffers *req = arg;
 		DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));
-/*
-		if( req->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
-			return overlay_reqbufs(dev,req);
-		} 
-*/
 		return videobuf_reqbufs(file,q,req);
 	}
 	case VIDIOC_QUERYBUF: {
 		struct v4l2_buffer *buf = arg;
 		DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));
-/* 		if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
-			return overlay_querybuf(dev,buf);
-		} 
- */		return videobuf_querybuf(q,buf);
+		return videobuf_querybuf(q,buf);
 	}
 	case VIDIOC_QBUF: {
 		struct v4l2_buffer *buf = arg;
 		int ret = 0;
-/* 		if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
-			return overlay_qbuf(dev,buf);
-		} 
- */		ret = videobuf_qbuf(file,q,buf);
+		ret = videobuf_qbuf(file,q,buf);
 		DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));
 		return ret;
 	}
 	case VIDIOC_DQBUF: {
 		struct v4l2_buffer *buf = arg;
 		int ret = 0;
-/* 		if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
-			return overlay_dqbuf(dev,buf);
-		} 
- */		ret = videobuf_dqbuf(file,q,buf);
+		ret = videobuf_dqbuf(file,q,buf);
 		DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));
 		return ret;
 	}
@@ -1180,29 +1094,18 @@
 		int *type = arg;
 		DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
 
-		if( 0 != ops->capture_begin ) {
-			if( 0 != (err = ops->capture_begin(fh))) {
+		if( 0 != (err = video_begin(fh))) {
 				return err;
 			}
-		}
-/* 		if( *type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
-			err = overlay_streamon(dev);
-		} else { */
 		err = videobuf_streamon(file,q);
-/* 		} */
 		return err;
 	}
 	case VIDIOC_STREAMOFF: {
 		int *type = arg;
 
 		DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
-		if( 0 != ops->capture_end ) {
-			ops->capture_end(fh);
-		}
-/* 		if( *type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
-			return overlay_streamoff(dev);
-		} 
- */		err = videobuf_streamoff(file,q);
+		video_end(fh, file);
+		err = videobuf_streamoff(file,q);
 		return err;
 	}
 	case VIDIOCGMBUF:
@@ -1267,8 +1170,8 @@
 	DEB_CAP(("vbuf:%p\n",vb));
 
 	/* sanity checks */
-	if (fh->video_fmt.width  < 64 ||
-	    fh->video_fmt.height < 64 ||
+	if (fh->video_fmt.width  < 48 ||
+	    fh->video_fmt.height < 32 ||
 	    fh->video_fmt.width  > vv->standard->h_max_out ||
 	    fh->video_fmt.height > vv->standard->v_max_out) {
 		DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
@@ -1407,8 +1310,9 @@
 }
 
 
-static void video_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
+static void video_open(struct saa7146_dev *dev, struct file *file)
 {
+	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
 	struct saa7146_format *sfmt;
 
 	fh->video_fmt.width = 384;
@@ -1429,8 +1333,9 @@
 }
 
 
-static void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file)
+static void video_close(struct saa7146_dev *dev, struct file *file)
 {
+	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
 	unsigned long flags;
 	
@@ -1443,10 +1348,8 @@
 	}
 	
 	if( fh == vv->streaming ) {
-		video_end(fh);		
+		video_end(fh, file);		
 	}
-
-	videobuf_queue_cancel(file,&fh->video_q);
 }
 
 
@@ -1489,7 +1392,7 @@
 		return -EAGAIN;
 	}
 	ret = videobuf_read_one(file,&fh->video_q , data, count, ppos);
-	video_end(fh);
+	video_end(fh, file);
 
 	/* restart overlay if it was active before */
 	if( 0 != restart_overlay ) {
@@ -1505,6 +1408,4 @@
 	.release = video_close,
 	.irq_done = video_irq_done,
 	.read = video_read,
-	.capture_begin = video_begin,
-	.capture_end = video_end,
 };
diff -uNrwB --new-file linux-2.6.0/include/media/saa7146.h linux-2.6.0-p/include/media/saa7146.h
--- linux-2.6.0/include/media/saa7146.h	2003-12-18 03:58:04.000000000 +0100
+++ linux-2.6.0-p/include/media/saa7146.h	2003-12-08 16:19:01.000000000 +0100
@@ -87,6 +87,7 @@
 {
 	char	name[32];		/* name of the device */
 #define SAA7146_USE_I2C_IRQ	0x1
+#define SAA7146_I2C_SHORT_DELAY	0x2
 	int	flags;
 	
 	/* pairs of subvendor and subdevice ids for
@@ -162,9 +163,10 @@
 struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc);
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
 void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
-void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
+int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
 char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt);
 void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data);
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev);
 
 /* some memory sizes */
 #define SAA7146_I2C_MEM		( 1*PAGE_SIZE)
@@ -187,6 +189,9 @@
 #define SAA7146_GPIO_OUTLO 0x40
 #define SAA7146_GPIO_OUTHI 0x50
 
+/* debi defines */
+#define DEBINOSWAP 0x000e0000
+
 /* define for the register programming sequencer (rps) */
 #define CMD_NOP		0x00000000  /* No operation */
 #define CMD_CLR_EVENT	0x00000000  /* Clear event */
diff -uNrwB --new-file linux-2.6.0/include/media/saa7146_vv.h linux-2.6.0-p/include/media/saa7146_vv.h
--- linux-2.6.0/include/media/saa7146_vv.h	2003-12-18 03:58:08.000000000 +0100
+++ linux-2.6.0-p/include/media/saa7146_vv.h	2003-12-17 14:00:22.000000000 +0100
@@ -149,7 +149,7 @@
 };
 
 /* flags */
-#define SAA7146_EXT_SWAP_ODD_EVEN       0x1     /* needs odd/even fields swapped */
+// #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
@@ -171,12 +171,10 @@
 
 struct saa7146_use_ops  {
         void (*init)(struct saa7146_dev *, struct saa7146_vv *);
-        void(*open)(struct saa7146_dev *, struct saa7146_fh *);
-        void (*release)(struct saa7146_dev *, struct saa7146_fh *,struct file *);
+        void(*open)(struct saa7146_dev *, struct file *);
+        void (*release)(struct saa7146_dev *, struct file *);
         void (*irq_done)(struct saa7146_dev *, unsigned long status);
 	ssize_t (*read)(struct file *, char *, size_t, loff_t *);
-        int (*capture_begin)(struct saa7146_fh *);
-        int (*capture_end)(struct saa7146_fh *);
 };
 
 /* from saa7146_fops.c */
diff -ura linux-2.6.0.p/drivers/media/common/saa7146_video.c linux-2.6.0.p2/drivers/media/common/saa7146_video.c
--- linux-2.6.0.p/drivers/media/common/saa7146_video.c	2003-12-19 10:38:46.000000000 +0100
+++ linux-2.6.0.p2/drivers/media/common/saa7146_video.c	2003-12-19 10:40:43.000000000 +0100
@@ -736,8 +736,6 @@
 
 	vv->streaming = NULL;
 
-	videobuf_queue_cancel(file,&fh->video_q);
-	
 	spin_unlock_irqrestore(&dev->slock, flags);
 	
 	return 0;
@@ -1105,8 +1103,8 @@
 		int *type = arg;
 
 		DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
-		video_end(fh, file);
 		err = videobuf_streamoff(file,q);
+		video_end(fh, file);
 		return err;
 	}
 	case VIDIOCGMBUF:


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 3/12] Add new DVB driver
  2003-12-19 12:28   ` [PATCH 2/12] Update saa7146 capture core Michael Hunold
@ 2003-12-19 12:28     ` Michael Hunold
  2003-12-19 12:28       ` [PATCH 4/12] Update Skystar2 " Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - new DVB driver for bt878 based "budget" DVB cards (Nebula, Pinnacle PCTV, Twinhan DST)
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/Kconfig linux-2.6.0-p/drivers/media/dvb/Kconfig
--- linux-2.6.0/drivers/media/dvb/Kconfig	2003-12-18 03:58:39.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/Kconfig	2003-10-13 12:52:18.000000000 +0200
@@ -45,5 +45,9 @@
 	depends on DVB_CORE && PCI
 source "drivers/media/dvb/b2c2/Kconfig"
 
+comment "Supported BT878 Adapters"
+	depends on DVB_CORE && PCI
+source "drivers/media/dvb/bt8xx/Kconfig"
+
 endmenu
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/Makefile linux-2.6.0-p/drivers/media/dvb/Makefile
--- linux-2.6.0/drivers/media/dvb/Makefile	2003-12-18 03:58:57.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/Makefile	2003-10-01 12:18:11.000000000 +0200
@@ -2,5 +2,5 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/
+obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/bt8xx/Kconfig linux-2.6.0-p/drivers/media/dvb/bt8xx/Kconfig
--- linux-2.6.0/drivers/media/dvb/bt8xx/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/bt8xx/Kconfig	2003-10-13 12:52:18.000000000 +0200
@@ -0,0 +1,13 @@
+config DVB_BT8XX
+	tristate "Nebula/Pinnacle PCTV PCI cards"
+	depends on DVB_CORE && PCI && VIDEO_BT848
+	help
+	  Support for PCI cards based on the Bt8xx PCI bridge. Examples are
+	  the Nebula cards, the Pinnacle PCTV cards, and Twinhan DST cards.
+
+          Since these cards have no MPEG decoder onboard, they transmit
+	  only compressed MPEG data over the PCI bus, so you need
+	  an external software decoder to watch TV on your computer.
+
+	  Say Y if you own such a device and want to use it.
+
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/bt8xx/Makefile linux-2.6.0-p/drivers/media/dvb/bt8xx/Makefile
--- linux-2.6.0/drivers/media/dvb/bt8xx/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/bt8xx/Makefile	2003-07-15 11:18:59.000000000 +0200
@@ -0,0 +1,5 @@
+
+obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video
+
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/bt8xx/bt878.c linux-2.6.0-p/drivers/media/dvb/bt8xx/bt878.c
--- linux-2.6.0/drivers/media/dvb/bt8xx/bt878.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/bt8xx/bt878.c	2003-11-20 09:44:03.000000000 +0100
@@ -0,0 +1,618 @@
+/*
+ * bt878.c: part of the driver for the Pinnacle PCTV Sat DVB PCI card
+ *
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ *
+ * large parts based on the bttv driver
+ * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+ *                        & Marcus Metzler (mocm@thp.uni-koeln.de)
+ * (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ * 
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/ioport.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "bt878.h"
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include "dst-bt878.h"
+#else
+#include "../frontends/dst-bt878.h"
+#endif
+
+#include "dvb_functions.h"
+
+/**************************************/
+/* Miscellaneous utility  definitions */
+/**************************************/
+
+unsigned int bt878_verbose = 1;
+unsigned int bt878_debug = 0;
+MODULE_PARM(bt878_verbose, "i");
+MODULE_PARM_DESC(bt878_verbose,
+		 "verbose startup messages, default is 1 (yes)");
+MODULE_PARM(bt878_debug, "i");
+MODULE_PARM_DESC(bt878_debug, "debug messages, default is 0 (no)");
+MODULE_LICENSE("GPL");
+
+int bt878_num;
+struct bt878 bt878[BT878_MAX];
+
+EXPORT_SYMBOL(bt878_debug);
+EXPORT_SYMBOL(bt878_verbose);
+EXPORT_SYMBOL(bt878_num);
+EXPORT_SYMBOL(bt878);
+
+#define btwrite(dat,adr)    bmtwrite((dat), (bt->bt878_mem+(adr)))
+#define btread(adr)         bmtread(bt->bt878_mem+(adr))
+
+#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
+#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
+#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
+
+#if defined(dprintk)
+#undef dprintk
+#endif
+#define dprintk if(bt878_debug) printk
+
+static void bt878_mem_free(struct bt878 *bt)
+{
+	if (bt->buf_cpu) {
+		pci_free_consistent(bt->dev, bt->buf_size, bt->buf_cpu,
+				    bt->buf_dma);
+		bt->buf_cpu = NULL;
+	}
+
+	if (bt->risc_cpu) {
+		pci_free_consistent(bt->dev, bt->risc_size, bt->risc_cpu,
+				    bt->risc_dma);
+		bt->risc_cpu = NULL;
+	}
+}
+
+static int bt878_mem_alloc(struct bt878 *bt)
+{
+	if (!bt->buf_cpu) {
+		bt->buf_size = 128 * 1024;
+
+		bt->buf_cpu =
+		    pci_alloc_consistent(bt->dev, bt->buf_size,
+					 &bt->buf_dma);
+
+		if (!bt->buf_cpu)
+			return -ENOMEM;
+
+		memset(bt->buf_cpu, 0, bt->buf_size);
+	}
+
+	if (!bt->risc_cpu) {
+		bt->risc_size = PAGE_SIZE;
+		bt->risc_cpu =
+		    pci_alloc_consistent(bt->dev, bt->risc_size,
+					 &bt->risc_dma);
+
+		if (!bt->risc_cpu) {
+			bt878_mem_free(bt);
+			return -ENOMEM;
+		}
+
+		memset(bt->risc_cpu, 0, bt->risc_size);
+	}
+
+	return 0;
+}
+
+/* RISC instructions */
+#define RISC_WRITE        	(0x01 << 28)
+#define RISC_JUMP         	(0x07 << 28)
+#define RISC_SYNC         	(0x08 << 28)
+
+/* RISC bits */
+#define RISC_WR_SOL       	(1 << 27)
+#define RISC_WR_EOL       	(1 << 26)
+#define RISC_IRQ          	(1 << 24)
+#define RISC_STATUS(status)	((((~status) & 0x0F) << 20) | ((status & 0x0F) << 16))
+#define RISC_SYNC_RESYNC  	(1 << 15)
+#define RISC_SYNC_FM1     	0x06
+#define RISC_SYNC_VRO     	0x0C
+
+#define RISC_FLUSH()		bt->risc_pos = 0
+#define RISC_INSTR(instr) 	bt->risc_cpu[bt->risc_pos++] = cpu_to_le32(instr)
+
+static int bt878_make_risc(struct bt878 *bt)
+{
+	bt->block_bytes = bt->buf_size >> 4;
+	bt->block_count = 1 << 4;
+	bt->line_bytes = bt->block_bytes;
+	bt->line_count = bt->block_count;
+
+	while (bt->line_bytes > 4095) {
+		bt->line_bytes >>= 1;
+		bt->line_count <<= 1;
+	}
+
+	if (bt->line_count > 255) {
+		printk("bt878: buffer size error!\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+static void bt878_risc_program(struct bt878 *bt, u32 op_sync_orin)
+{
+	u32 buf_pos = 0;
+	u32 line;
+
+	RISC_FLUSH();
+	RISC_INSTR(RISC_SYNC | RISC_SYNC_FM1 | op_sync_orin);
+	RISC_INSTR(0);
+
+	dprintk("bt878: risc len lines %u, bytes per line %u\n", 
+			bt->line_count, bt->line_bytes);
+	for (line = 0; line < bt->line_count; line++) {
+		// At the beginning of every block we issue an IRQ with previous (finished) block number set
+		if (!(buf_pos % bt->block_bytes))
+			RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL |
+				   RISC_IRQ |
+				   RISC_STATUS(((buf_pos /
+						 bt->block_bytes) +
+						(bt->block_count -
+						 1)) %
+					       bt->block_count) | bt->
+				   line_bytes);
+		else
+			RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL |
+				   bt->line_bytes);
+		RISC_INSTR(bt->buf_dma + buf_pos);
+		buf_pos += bt->line_bytes;
+	}
+
+	RISC_INSTR(RISC_SYNC | op_sync_orin | RISC_SYNC_VRO);
+	RISC_INSTR(0);
+
+	RISC_INSTR(RISC_JUMP);
+	RISC_INSTR(bt->risc_dma);
+
+	btwrite((bt->line_count << 16) | bt->line_bytes, BT878_APACK_LEN);
+}
+
+/*****************************/
+/* Start/Stop grabbing funcs */
+/*****************************/
+
+void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
+		u32 irq_err_ignore)
+{
+	u32 int_mask;
+
+	dprintk("bt878 debug: bt878_start (ctl=%8.8x)\n", controlreg);
+	/* complete the writing of the risc dma program now we have
+	 * the card specifics
+	 */
+	bt878_risc_program(bt, op_sync_orin);
+	controlreg &= ~0x1f;
+	controlreg |= 0x1b;
+
+	btwrite(cpu_to_le32(bt->risc_dma), BT878_ARISC_START);
+
+	/* original int mask had :
+	 *    6    2    8    4    0
+	 * 1111 1111 1000 0000 0000
+	 * SCERR|OCERR|PABORT|RIPERR|FDSR|FTRGT|FBUS|RISCI
+	 * Hacked for DST to:
+	 * SCERR | OCERR | FDSR | FTRGT | FBUS | RISCI
+	 */
+	int_mask = BT878_ASCERR | BT878_AOCERR | BT878_APABORT | 
+		BT878_ARIPERR | BT878_APPERR | BT878_AFDSR | BT878_AFTRGT | 
+		BT878_AFBUS | BT878_ARISCI;
+
+
+	/* ignore pesky bits */
+	int_mask &= ~irq_err_ignore;
+	
+	btwrite(int_mask, BT878_AINT_MASK);
+	btwrite(controlreg, BT878_AGPIO_DMA_CTL);
+}
+
+void bt878_stop(struct bt878 *bt)
+{
+	u32 stat;
+	int i = 0;
+
+	dprintk("bt878 debug: bt878_stop\n");
+
+	btwrite(0, BT878_AINT_MASK);
+	btand(~0x13, BT878_AGPIO_DMA_CTL);
+
+	do {
+		stat = btread(BT878_AINT_STAT);
+		if (!(stat & BT878_ARISC_EN))
+			break;
+		i++;
+	} while (i < 500);
+
+	dprintk("bt878(%d) debug: bt878_stop, i=%d, stat=0x%8.8x\n",
+		bt->nr, i, stat);
+}
+
+EXPORT_SYMBOL(bt878_start);
+EXPORT_SYMBOL(bt878_stop);
+
+/*****************************/
+/* Interrupt service routine */
+/*****************************/
+
+static irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 stat, astat, mask;
+	int count;
+	struct bt878 *bt;
+
+	bt = (struct bt878 *) dev_id;
+
+	count = 0;
+	while (1) {
+		stat = btread(BT878_AINT_STAT);
+		mask = btread(BT878_AINT_MASK);
+		if (!(astat = (stat & mask)))
+			return IRQ_NONE;	/* this interrupt is not for me */
+/*		dprintk("bt878(%d) debug: irq count %d, stat 0x%8.8x, mask 0x%8.8x\n",bt->nr,count,stat,mask); */
+		btwrite(astat, BT878_AINT_STAT);	/* try to clear interupt condition */
+
+
+		if (astat & (BT878_ASCERR | BT878_AOCERR)) {
+			if (bt878_verbose) {
+				printk("bt878(%d): irq%s%s risc_pc=%08x\n",
+				       bt->nr,
+				       (astat & BT878_ASCERR) ? " SCERR" :
+				       "",
+				       (astat & BT878_AOCERR) ? " OCERR" :
+				       "", btread(BT878_ARISC_PC));
+			}
+		}
+		if (astat & (BT878_APABORT | BT878_ARIPERR | BT878_APPERR)) {
+			if (bt878_verbose) {
+				printk
+				    ("bt878(%d): irq%s%s%s risc_pc=%08x\n",
+				     bt->nr,
+				     (astat & BT878_APABORT) ? " PABORT" :
+				     "",
+				     (astat & BT878_ARIPERR) ? " RIPERR" :
+				     "",
+				     (astat & BT878_APPERR) ? " PPERR" :
+				     "", btread(BT878_ARISC_PC));
+			}
+		}
+		if (astat & (BT878_AFDSR | BT878_AFTRGT | BT878_AFBUS)) {
+			if (bt878_verbose) {
+				printk
+				    ("bt878(%d): irq%s%s%s risc_pc=%08x\n",
+				     bt->nr,
+				     (astat & BT878_AFDSR) ? " FDSR" : "",
+				     (astat & BT878_AFTRGT) ? " FTRGT" :
+				     "",
+				     (astat & BT878_AFBUS) ? " FBUS" : "",
+				     btread(BT878_ARISC_PC));
+			}
+		}
+		if (astat & BT878_ARISCI) {
+			bt->finished_block = (stat & BT878_ARISCS) >> 28;
+			tasklet_schedule(&bt->tasklet);
+			break;
+		}
+		count++;
+		if (count > 20) {
+			btwrite(0, BT878_AINT_MASK);
+			printk(KERN_ERR
+			       "bt878(%d): IRQ lockup, cleared int mask\n",
+			       bt->nr);
+			break;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+extern int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data);
+extern int bttv_read_gpio(unsigned int card, unsigned long *data);
+extern int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data);
+
+int
+bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp)
+{
+	int retval;
+
+	retval = 0;
+	if (down_interruptible (&bt->gpio_lock))
+		return -ERESTARTSYS;
+	/* special gpio signal */
+	switch (cmd) {
+	    case DST_IG_ENABLE:
+		// dprintk("dvb_bt8xx: dst enable mask 0x%02x enb 0x%02x \n", mp->dstg.enb.mask, mp->dstg.enb.enable);
+		retval = bttv_gpio_enable(bt->bttv_nr,
+				mp->enb.mask,
+				mp->enb.enable);
+		break;
+	    case DST_IG_WRITE:
+		// dprintk("dvb_bt8xx: dst write gpio mask 0x%02x out 0x%02x\n", mp->dstg.outp.mask, mp->dstg.outp.highvals);
+		retval = bttv_write_gpio(bt->bttv_nr,
+				mp->outp.mask,
+				mp->outp.highvals);
+
+		break;
+	    case DST_IG_READ:
+		/* read */
+		retval =  bttv_read_gpio(bt->bttv_nr, &mp->rd.value);
+		// dprintk("dvb_bt8xx: dst read gpio 0x%02x\n", (unsigned)mp->dstg.rd.value);
+		break;
+	    case DST_IG_TS:
+		/* Set packet size */
+		bt->TS_Size = mp->psize;
+		break;
+
+	    default:
+		retval = -EINVAL;
+		break;
+	}
+	up(&bt->gpio_lock);
+	return retval;
+}
+
+EXPORT_SYMBOL(bt878_device_control);
+
+struct bt878 *bt878_find_by_dvb_adap(struct dvb_adapter *adap)
+{
+	unsigned int card_nr;
+	
+	printk("bt878 find by dvb adap: checking \"%s\"\n",adap->name);
+	for (card_nr = 0; card_nr < bt878_num; card_nr++) {
+		if (bt878[card_nr].adap_ptr == adap)
+			return &bt878[card_nr];
+	}
+	printk("bt878 find by dvb adap: NOT found \"%s\"\n",adap->name);
+	return NULL;
+}
+
+EXPORT_SYMBOL(bt878_find_by_dvb_adap);
+
+/***********************/
+/* PCI device handling */
+/***********************/
+
+static int __devinit bt878_probe(struct pci_dev *dev,
+				 const struct pci_device_id *pci_id)
+{
+	int result;
+	unsigned char lat;
+	struct bt878 *bt;
+#if defined(__powerpc__)
+	unsigned int cmd;
+#endif
+
+	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
+	       bt878_num);
+
+	bt = &bt878[bt878_num];
+	bt->dev = dev;
+	bt->nr = bt878_num;
+	bt->shutdown = 0;
+
+	bt->id = dev->device;
+	bt->irq = dev->irq;
+	bt->bt878_adr = pci_resource_start(dev, 0);
+	if (pci_enable_device(dev))
+		return -EIO;
+	if (!request_mem_region(pci_resource_start(dev, 0),
+				pci_resource_len(dev, 0), "bt878")) {
+		return -EBUSY;
+	}
+
+	pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+	printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ",
+	       bt878_num, bt->id, bt->revision, dev->bus->number,
+	       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	printk("irq: %d, latency: %d, memory: 0x%lx\n",
+	       bt->irq, lat, bt->bt878_adr);
+
+
+#if defined(__powerpc__)
+	/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
+	/* response on cards with no firmware is not enabled by OF */
+	pci_read_config_dword(dev, PCI_COMMAND, &cmd);
+	cmd = (cmd | PCI_COMMAND_MEMORY);
+	pci_write_config_dword(dev, PCI_COMMAND, cmd);
+#endif
+
+#ifdef __sparc__
+	bt->bt878_mem = (unsigned char *) bt->bt878_adr;
+#else
+	bt->bt878_mem = ioremap(bt->bt878_adr, 0x1000);
+#endif
+
+	/* clear interrupt mask */
+	btwrite(0, BT848_INT_MASK);
+
+	result = request_irq(bt->irq, bt878_irq,
+			     SA_SHIRQ | SA_INTERRUPT, "bt878",
+			     (void *) bt);
+	if (result == -EINVAL) {
+		printk(KERN_ERR "bt878(%d): Bad irq number or handler\n",
+		       bt878_num);
+		goto fail1;
+	}
+	if (result == -EBUSY) {
+		printk(KERN_ERR
+		       "bt878(%d): IRQ %d busy, change your PnP config in BIOS\n",
+		       bt878_num, bt->irq);
+		goto fail1;
+	}
+	if (result < 0)
+		goto fail1;
+
+	pci_set_master(dev);
+	pci_set_drvdata(dev, bt);
+
+/*        if(init_bt878(btv) < 0) {
+                bt878_remove(dev);
+                return -EIO;
+        }
+*/
+
+	if ((result = bt878_mem_alloc(bt))) {
+		printk("bt878: failed to allocate memory!\n");
+		goto fail2;
+	}
+
+	bt878_make_risc(bt);
+	btwrite(0, BT878_AINT_MASK);
+	bt878_num++;
+
+	return 0;
+
+      fail2:
+	free_irq(bt->irq, bt);
+      fail1:
+	release_mem_region(pci_resource_start(bt->dev, 0),
+			   pci_resource_len(bt->dev, 0));
+	return result;
+}
+
+static void __devexit bt878_remove(struct pci_dev *pci_dev)
+{
+	u8 command;
+	struct bt878 *bt = pci_get_drvdata(pci_dev);
+
+	if (bt878_verbose)
+		printk("bt878(%d): unloading\n", bt->nr);
+
+	/* turn off all capturing, DMA and IRQs */
+	btand(~13, BT878_AGPIO_DMA_CTL);
+
+	/* first disable interrupts before unmapping the memory! */
+	btwrite(0, BT878_AINT_MASK);
+	btwrite(~0x0UL, BT878_AINT_STAT);
+
+	/* disable PCI bus-mastering */
+	pci_read_config_byte(bt->dev, PCI_COMMAND, &command);
+	/* Should this be &=~ ?? */
+	command &= ~PCI_COMMAND_MASTER;
+	pci_write_config_byte(bt->dev, PCI_COMMAND, command);
+
+	free_irq(bt->irq, bt);
+	printk(KERN_DEBUG "bt878_mem: 0x%p.\n", bt->bt878_mem);
+	if (bt->bt878_mem)
+		iounmap(bt->bt878_mem);
+
+	release_mem_region(pci_resource_start(bt->dev, 0),
+			   pci_resource_len(bt->dev, 0));
+	/* wake up any waiting processes
+	   because shutdown flag is set, no new processes (in this queue)
+	   are expected
+	 */
+	bt->shutdown = 1;
+	bt878_mem_free(bt);
+
+	pci_set_drvdata(pci_dev, NULL);
+	return;
+}
+
+static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
+	{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BROOKTREE_878,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
+
+static struct pci_driver bt878_pci_driver = {
+      .name 	= "bt878",
+      .id_table = bt878_pci_tbl,
+      .probe 	= bt878_probe,
+      .remove 	= bt878_remove,
+};
+
+static int bt878_pci_driver_registered = 0;
+
+/* This will be used later by dvb-bt8xx to only use the audio
+ * dma of certain cards */
+int bt878_find_audio_dma(void)
+{
+	// pci_register_driver(&bt878_pci_driver);
+	bt878_pci_driver_registered = 1;
+	return 0;
+}
+
+EXPORT_SYMBOL(bt878_find_audio_dma);
+
+/*******************************/
+/* Module management functions */
+/*******************************/
+
+int bt878_init_module(void)
+{
+	bt878_num = 0;
+	bt878_pci_driver_registered = 0;
+
+	printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n",
+	       (BT878_VERSION_CODE >> 16) & 0xff,
+	       (BT878_VERSION_CODE >> 8) & 0xff,
+	       BT878_VERSION_CODE & 0xff);
+/*
+        bt878_check_chipset();
+*/
+	/* later we register inside of bt878_find_audio_dma
+	 * because we may want to ignore certain cards */
+	bt878_pci_driver_registered = 1;
+	return pci_module_init(&bt878_pci_driver);
+}
+
+void bt878_cleanup_module(void)
+{
+	if (bt878_pci_driver_registered) {
+		bt878_pci_driver_registered = 0;
+		pci_unregister_driver(&bt878_pci_driver);
+	}
+	return;
+}
+
+EXPORT_SYMBOL(bt878_init_module);
+EXPORT_SYMBOL(bt878_cleanup_module);
+module_init(bt878_init_module);
+module_exit(bt878_cleanup_module);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/bt8xx/bt878.h linux-2.6.0-p/drivers/media/dvb/bt8xx/bt878.h
--- linux-2.6.0/drivers/media/dvb/bt8xx/bt878.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/bt8xx/bt878.h	2003-10-28 10:39:42.000000000 +0100
@@ -0,0 +1,145 @@
+/* 
+    bt878.h - Bt878 audio module (register offsets)
+
+    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.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.
+*/
+
+#ifndef _BT878_H_
+#define _BT878_H_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include "bt848.h"
+
+#define BT878_VERSION_CODE 0x000000
+
+#define BT878_AINT_STAT		0x100
+#define BT878_ARISCS		(0xf<<28)
+#define BT878_ARISC_EN		(1<<27)
+#define BT878_ASCERR		(1<<19)
+#define BT878_AOCERR		(1<<18)
+#define BT878_APABORT		(1<<17)
+#define BT878_ARIPERR		(1<<16)
+#define BT878_APPERR		(1<<15)
+#define BT878_AFDSR		(1<<14)
+#define BT878_AFTRGT		(1<<13)
+#define BT878_AFBUS		(1<<12)
+#define BT878_ARISCI		(1<<11)
+#define BT878_AOFLOW		(1<<3)
+
+#define BT878_AINT_MASK		0x104
+
+#define BT878_AGPIO_DMA_CTL	0x10c
+#define BT878_A_GAIN		(0xf<<28)
+#define BT878_A_G2X		(1<<27)
+#define BT878_A_PWRDN		(1<<26)
+#define BT878_A_SEL		(3<<24)
+#define BT878_DA_SCE		(1<<23)
+#define BT878_DA_LRI		(1<<22)
+#define BT878_DA_MLB		(1<<21)
+#define BT878_DA_LRD		(0x1f<<16)
+#define BT878_DA_DPM		(1<<15)
+#define BT878_DA_SBR		(1<<14)
+#define BT878_DA_ES2		(1<<13)
+#define BT878_DA_LMT		(1<<12)
+#define BT878_DA_SDR		(0xf<<8)
+#define BT878_DA_IOM		(3<<6)
+#define BT878_DA_APP		(1<<5)
+#define BT878_ACAP_EN		(1<<4)
+#define BT878_PKTP		(3<<2)
+#define BT878_RISC_EN		(1<<1)
+#define BT878_FIFO_EN		1
+
+#define BT878_APACK_LEN		0x110
+#define BT878_AFP_LEN		(0xff<<16)
+#define BT878_ALP_LEN		0xfff
+
+#define BT878_ARISC_START	0x114
+
+#define BT878_ARISC_PC		0x120
+
+/* BT878 FUNCTION 0 REGISTERS */
+#define BT878_GPIO_DMA_CTL	0x10c
+
+/* Interrupt register */
+#define BT878_INT_STAT		0x100
+#define BT878_INT_MASK		0x104
+#define BT878_I2CRACK		(1<<25)
+#define BT878_I2CDONE		(1<<8)
+
+#define BT878_MAX 4
+
+#define BT878_RISC_SYNC_MASK	(1 << 15)
+
+extern int bt878_num;
+extern struct bt878 bt878[BT878_MAX];
+
+struct bt878 {
+	struct semaphore  gpio_lock;
+	unsigned int nr;
+	unsigned int bttv_nr;
+	struct dvb_adapter *adap_ptr;
+	struct pci_dev *dev;
+	unsigned int id;
+	unsigned int TS_Size;
+	unsigned char revision;
+	unsigned int irq;
+	unsigned long bt878_adr;
+	unsigned char *bt878_mem; /* function 1 */
+
+	volatile u32 finished_block;
+	volatile u32 last_block;
+	u32 block_count;
+	u32 block_bytes;
+	u32 line_bytes;
+	u32 line_count;
+
+	u32 buf_size;
+	u8 *buf_cpu;
+	dma_addr_t buf_dma;
+
+	u32 risc_size;
+	u32 *risc_cpu;
+	dma_addr_t risc_dma;
+	u32 risc_pos;
+
+	struct tasklet_struct tasklet;
+	int shutdown;	
+};
+
+void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
+		u32 irq_err_ignore);
+void bt878_stop(struct bt878 *bt);	     
+
+#if defined(__powerpc__)	/* big-endian */
+extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val)
+{
+	__asm__ __volatile__("stwbrx %1,0,%2":"=m"(*addr):"r"(val),
+			     "r"(addr));
+	__asm__ __volatile__("eieio":::"memory");
+}
+
+#define bmtwrite(dat,adr)  io_st_le32((unsigned *)(adr),(dat))
+#define bmtread(adr)       ld_le32((unsigned *)(adr))
+#else
+#define bmtwrite(dat,adr)  writel((dat), (char *) (adr))
+#define bmtread(adr)       readl(adr)
+#endif
+
+#endif
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/bt8xx/dvb-bt8xx.c linux-2.6.0-p/drivers/media/dvb/bt8xx/dvb-bt8xx.c
--- linux-2.6.0/drivers/media/dvb/bt8xx/dvb-bt8xx.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/bt8xx/dvb-bt8xx.c	2003-11-25 13:10:26.000000000 +0100
@@ -0,0 +1,565 @@
+/*
+ * Bt8xx based DVB adapter driver 
+ *
+ * Copyright (C) 2002,2003 Florian Schirmer <schirmer@taytron.net>
+ *
+ * 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 <asm/bitops.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include "dvb-bt8xx.h"
+
+#include "dvb_functions.h"
+
+#include "bt878.h"
+
+/* ID THAT MUST GO INTO i2c ids */
+#ifndef  I2C_DRIVERID_DVB_BT878A
+# define I2C_DRIVERID_DVB_BT878A I2C_DRIVERID_EXP0+10
+#endif
+
+
+#define dprintk if (debug) printk
+
+extern int bttv_get_cardinfo(unsigned int card, int *type, int *cardid);
+extern struct pci_dev* bttv_get_pcidev(unsigned int card);
+
+static LIST_HEAD(card_list);
+static int debug = 0;
+
+static void dvb_bt8xx_task(unsigned long data)
+{
+	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data;
+
+	//printk("%d ", finished_block);
+
+	while (card->bt->last_block != card->bt->finished_block) {
+		(card->bt->TS_Size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)(&card->demux, &card->bt->buf_cpu[card->bt->last_block * card->bt->block_bytes], card->bt->block_bytes);
+		card->bt->last_block = (card->bt->last_block + 1) % card->bt->block_count;
+	}
+}
+
+static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct dvb_bt8xx_card *card = dvbdmx->priv;
+
+	dprintk("dvb_bt8xx: start_feed\n");
+	
+	if (!dvbdmx->dmx.frontend)
+		return -EINVAL;
+
+	if (card->active)
+		return 0;
+		
+	card->active = 1;
+	
+//	bt878_start(card->bt, card->gpio_mode);
+
+	return 0;
+}
+
+static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct dvb_bt8xx_card *card = dvbdmx->priv;
+
+	dprintk("dvb_bt8xx: stop_feed\n");
+	
+	if (!dvbdmx->dmx.frontend)
+		return -EINVAL;
+		
+	if (!card->active)
+		return 0;
+
+//	bt878_stop(card->bt);
+
+	card->active = 0;
+
+	return 0;
+}
+
+static int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num)
+{
+	struct dvb_bt8xx_card *card = i2c->data;
+	int retval;
+
+	if (down_interruptible (&card->bt->gpio_lock))
+		return -ERESTARTSYS;
+
+	retval = i2c_transfer(card->i2c_adapter,
+			      (struct i2c_msg*) msgs,
+			      num);
+
+	up(&card->bt->gpio_lock);
+
+	return retval;
+}
+
+static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev)
+{
+	if ((adev->subsystem_vendor == bdev->subsystem_vendor) &&
+		(adev->subsystem_device == bdev->subsystem_device) &&
+		(adev->bus->number == bdev->bus->number) &&
+		(PCI_SLOT(adev->devfn) == PCI_SLOT(bdev->devfn)))
+		return 1;
+	return 0;
+}
+
+static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)
+{
+	unsigned int card_nr;
+	
+	/* Hmm, n squared. Hope n is small */
+	for (card_nr = 0; card_nr < bt878_num; card_nr++) {
+		if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))
+			return &bt878[card_nr];
+	}
+	return NULL;
+}
+
+static int __init dvb_bt8xx_card_match(unsigned int bttv_nr, char *card_name, u32 gpio_mode, u32 op_sync_orin, u32 irq_err_ignore)
+{
+	struct dvb_bt8xx_card *card;
+	struct pci_dev* bttv_pci_dev;
+
+	dprintk("dvb_bt8xx: identified card%d as %s\n", bttv_nr, card_name);
+			
+	if (!(card = kmalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))
+		return -ENOMEM;
+
+	memset(card, 0, sizeof(*card));
+	card->bttv_nr = bttv_nr;
+	strncpy(card->card_name, card_name, sizeof(card_name) - 1);
+	
+	if (!(bttv_pci_dev = bttv_get_pcidev(bttv_nr))) {
+		printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr);
+		kfree(card);
+		return -EFAULT;
+	}
+
+	if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
+		printk("dvb_bt8xx: unable to determine DMA core of card %d\n", card->bttv_nr);
+	
+		kfree(card);
+		return -EFAULT;
+		
+	}
+	init_MUTEX(&card->bt->gpio_lock);
+	card->bt->bttv_nr = bttv_nr;
+	card->gpio_mode = gpio_mode;
+	card->op_sync_orin = op_sync_orin;
+	card->irq_err_ignore = irq_err_ignore;
+	list_add_tail(&card->list, &card_list);
+
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+/* with 2.6.x not needed thanks to the driver model + sysfs */
+
+extern struct i2c_adapter *bttv_get_i2c_adap(unsigned int card);
+
+static void __init dvb_bt8xx_get_adaps(void)
+{
+	struct dvb_bt8xx_card *card;
+	struct list_head *entry, *entry_safe;
+
+	list_for_each_safe(entry, entry_safe, &card_list) {
+		card = list_entry(entry, struct dvb_bt8xx_card, list);
+		card->i2c_adapter =  bttv_get_i2c_adap(card->bttv_nr);
+		if (!card->i2c_adapter) {
+			printk("dvb_bt8xx: unable to determine i2c adaptor of card %d, deleting\n", card->bttv_nr);
+
+			list_del(&card->list);
+			kfree(card);
+		}
+	}
+}
+
+static void dvb_bt8xx_i2c_adap_free(struct i2c_adapter *adap)
+{
+}
+
+static void __exit dvb_bt8xx_exit_adaps(void)
+{
+}
+
+#else
+
+/* More complicated. but cleaner better */
+
+static struct dvb_bt8xx_card *dvb_bt8xx_find_by_i2c_adap(struct i2c_adapter *adap)
+{
+	struct dvb_bt8xx_card *card;
+	struct list_head *item;
+	
+	printk("find by i2c adap: checking \"%s\"\n",adap->name);
+	list_for_each(item, &card_list) {
+		card = list_entry(item, struct dvb_bt8xx_card, list);
+		if (card->i2c_adapter == adap)
+			return card;
+	}
+	return NULL;
+}
+
+static struct dvb_bt8xx_card *dvb_bt8xx_find_by_pci(struct i2c_adapter *adap)
+{
+	struct dvb_bt8xx_card *card;
+	struct list_head *item;
+	struct device  *dev;
+	struct pci_dev *pci;
+	
+	printk("find by pci: checking \"%s\"\n",adap->name);
+	dev = adap->dev.parent;
+	if (NULL == dev) {
+		/* shoudn't happen with 2.6.0-test7 + newer */
+		printk("attach: Huh? i2c adapter not in sysfs tree?\n");
+		return 0;
+	}
+	pci = to_pci_dev(dev);
+	list_for_each(item, &card_list) {
+		card = list_entry(item, struct dvb_bt8xx_card, list);
+		if (is_pci_slot_eq(pci, card->bt->dev)) {
+			return card;
+		}
+	}
+	return NULL;
+}
+
+static int dvb_bt8xx_attach(struct i2c_adapter *adap)
+{
+	struct dvb_bt8xx_card *card;
+	
+	printk("attach: checking \"%s\"\n",adap->name);
+
+	/* looking for bt878 cards ... */
+	if (adap->id != (I2C_ALGO_BIT | I2C_HW_B_BT848))
+		return 0;
+	card = dvb_bt8xx_find_by_pci(adap);
+	if (!card)
+		return 0;
+	card->i2c_adapter = adap;
+	printk("attach: \"%s\", to card %d\n",
+	       adap->name, card->bttv_nr);
+	try_module_get(adap->owner);
+
+	return 0;
+}
+
+static void dvb_bt8xx_i2c_adap_free(struct i2c_adapter *adap)
+{
+	module_put(adap->owner);
+}
+
+static int dvb_bt8xx_detach(struct i2c_adapter *adap)
+{
+	struct dvb_bt8xx_card *card;
+
+	card = dvb_bt8xx_find_by_i2c_adap(adap);
+	if (!card)
+		return 0;
+
+	/* This should not happen. We have locked the module! */
+	printk("detach: \"%s\", for card %d removed\n",
+	       adap->name, card->bttv_nr);
+	return 0;
+}
+
+static struct i2c_driver dvb_bt8xx_driver = {
+	.owner           = THIS_MODULE,
+	.name            = "dvb_bt8xx",
+        .id              = I2C_DRIVERID_DVB_BT878A,
+	.flags           = I2C_DF_NOTIFY,
+        .attach_adapter  = dvb_bt8xx_attach,
+        .detach_adapter  = dvb_bt8xx_detach,
+};
+
+static void __init dvb_bt8xx_get_adaps(void)
+{
+	i2c_add_driver(&dvb_bt8xx_driver);
+}
+
+static void __exit dvb_bt8xx_exit_adaps(void)
+{
+	i2c_del_driver(&dvb_bt8xx_driver);
+}
+#endif
+
+static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card)
+{
+	int result;
+
+	if (!card->i2c_adapter) {
+		printk("dvb_bt8xx: unable to determine i2c adaptor of card %d, deleting\n", card->bttv_nr);
+
+		return -EFAULT;
+	
+	}
+
+	if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name)) < 0) {
+	
+		printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
+		
+		dvb_bt8xx_i2c_adap_free(card->i2c_adapter);
+		return result;
+		
+	}
+	card->bt->adap_ptr = card->dvb_adapter;
+
+	if (!(dvb_register_i2c_bus(master_xfer, card, card->dvb_adapter, 0))) {
+		printk("dvb_bt8xx: dvb_register_i2c_bus of card%d failed\n", card->bttv_nr);
+
+		dvb_unregister_adapter(card->dvb_adapter);
+		dvb_bt8xx_i2c_adap_free(card->i2c_adapter);
+
+		return -EFAULT;
+	}
+
+	memset(&card->demux, 0, sizeof(struct dvb_demux));
+
+	card->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING;
+
+	card->demux.priv = card;
+	card->demux.filternum = 256;
+	card->demux.feednum = 256;
+	card->demux.start_feed = dvb_bt8xx_start_feed;
+	card->demux.stop_feed = dvb_bt8xx_stop_feed;
+	card->demux.write_to_decoder = NULL;
+	
+	if ((result = dvb_dmx_init(&card->demux)) < 0) {
+		printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
+
+		dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0);
+		dvb_unregister_adapter(card->dvb_adapter);
+		dvb_bt8xx_i2c_adap_free(card->i2c_adapter);
+		
+		return result;
+	}
+
+	card->dmxdev.filternum = 256;
+	card->dmxdev.demux = &card->demux.dmx;
+	card->dmxdev.capabilities = 0;
+	
+	if ((result = dvb_dmxdev_init(&card->dmxdev, card->dvb_adapter)) < 0) {
+		printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result);
+
+		dvb_dmx_release(&card->demux);
+		dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0);
+		dvb_unregister_adapter(card->dvb_adapter);
+		dvb_bt8xx_i2c_adap_free(card->i2c_adapter);
+		
+		return result;
+	}
+
+	card->fe_hw.source = DMX_FRONTEND_0;
+
+	if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {
+		printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
+
+		dvb_dmxdev_release(&card->dmxdev);
+		dvb_dmx_release(&card->demux);
+		dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0);
+		dvb_unregister_adapter(card->dvb_adapter);
+		dvb_bt8xx_i2c_adap_free(card->i2c_adapter);
+		
+		return result;
+	}
+	
+	card->fe_mem.source = DMX_MEMORY_FE;
+
+	if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem)) < 0) {
+		printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
+
+		card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
+		dvb_dmxdev_release(&card->dmxdev);
+		dvb_dmx_release(&card->demux);
+		dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0);
+		dvb_unregister_adapter(card->dvb_adapter);
+		dvb_bt8xx_i2c_adap_free(card->i2c_adapter);
+		
+		return result;
+	}
+
+	if ((result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {
+		printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
+
+		card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
+		card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
+		dvb_dmxdev_release(&card->dmxdev);
+		dvb_dmx_release(&card->demux);
+		dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0);
+		dvb_unregister_adapter(card->dvb_adapter);
+		dvb_bt8xx_i2c_adap_free(card->i2c_adapter);
+		
+		return result;
+	}
+
+	dvb_net_init(card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
+
+	tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
+	
+	bt878_start(card->bt, card->gpio_mode, card->op_sync_orin, card->irq_err_ignore);
+
+	return 0;
+}
+
+static int __init dvb_bt8xx_load_all(void)
+{
+	struct dvb_bt8xx_card *card;
+	struct list_head *entry, *entry_safe;
+
+	list_for_each_safe(entry, entry_safe, &card_list) {
+		card = list_entry(entry, struct dvb_bt8xx_card, list);
+		if (dvb_bt8xx_load_card(card) < 0) {
+			list_del(&card->list);
+			kfree(card);
+			continue;
+		}
+	}
+	return 0;
+
+}
+
+#define BT878_NEBULA	0x68
+#define BT878_TWINHAN_DST 0x71
+
+static int __init dvb_bt8xx_init(void)
+{
+	unsigned int card_nr = 0;
+	int card_id;
+	int card_type;
+
+	dprintk("dvb_bt8xx: enumerating available bttv cards...\n");
+	
+	while (bttv_get_cardinfo(card_nr, &card_type, &card_id) == 0) {
+		switch(card_id) {
+			case 0x001C11BD:
+				dvb_bt8xx_card_match(card_nr, "Pinnacle PCTV DVB-S",
+					       0x0400C060, 0, 0);
+				/* 26, 15, 14, 6, 5 
+				 * A_G2X  DA_DPM DA_SBR DA_IOM_DA 
+				 * DA_APP(parallel) */
+				break;
+			case 0x01010071:
+nebula:
+				dvb_bt8xx_card_match(card_nr, "Nebula DigiTV DVB-T",
+					     (1 << 26) | (1 << 14) | (1 << 5),
+					     0, 0);
+				/* A_PWRDN DA_SBR DA_APP (high speed serial) */
+				break;
+			case 0x07611461:
+				dvb_bt8xx_card_match(card_nr, "Avermedia DVB-T",
+					     (1 << 26) | (1 << 14) | (1 << 5),
+					     0, 0);
+				/* A_PWRDN DA_SBR DA_APP (high speed serial) */
+				break;
+			case 0x0:
+				if (card_type == BT878_NEBULA ||
+					card_type == BT878_TWINHAN_DST)
+					goto dst;
+				goto unknown_card;
+			case 0x2611BD:
+			case 0x11822:
+dst:
+				dvb_bt8xx_card_match(card_nr, "DST DVB-S", 0x2204f2c,
+						BT878_RISC_SYNC_MASK,
+						BT878_APABORT | BT878_ARIPERR | BT878_APPERR | BT878_AFBUS);
+				/* 25,21,14,11,10,9,8,3,2 then
+				 * 0x33 = 5,4,1,0
+				 * A_SEL=SML, DA_MLB, DA_SBR, 
+				 * DA_SDR=f, fifo trigger = 32 DWORDS
+				 * IOM = 0 == audio A/D
+				 * DPM = 0 == digital audio mode
+				 * == async data parallel port
+				 * then 0x33 (13 is set by start_capture)
+				 * DA_APP = async data parallel port, 
+				 * ACAP_EN = 1,
+				 * RISC+FIFO ENABLE */
+				break;
+			default:
+unknown_card:
+				printk("%s: unknown card_id found %0X\n",
+					__FUNCTION__, card_id);
+				if (card_type == BT878_NEBULA) {
+					printk("%s: bttv type set to nebula\n",
+						__FUNCTION__);
+					goto nebula;
+				}
+				if (card_type == BT878_TWINHAN_DST) {
+					printk("%s: bttv type set to Twinhan DST\n",
+						__FUNCTION__);
+					goto dst;
+				}
+				printk("%s: unknown card_type found %0X, NOT LOADED\n",
+					__FUNCTION__, card_type);
+				printk("%s: unknown card_nr found %0X\n",
+					__FUNCTION__, card_nr);
+		}
+		card_nr++;
+	}
+	dvb_bt8xx_get_adaps();
+	dvb_bt8xx_load_all();
+
+	return 0;
+
+}
+
+static void __exit dvb_bt8xx_exit(void)
+{
+	struct dvb_bt8xx_card *card;
+	struct list_head *entry, *entry_safe;
+
+	dvb_bt8xx_exit_adaps();
+	list_for_each_safe(entry, entry_safe, &card_list) {
+		card = list_entry(entry, struct dvb_bt8xx_card, list);
+		
+		dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
+
+		bt878_stop(card->bt);
+		tasklet_kill(&card->bt->tasklet);
+		dvb_net_release(&card->dvbnet);
+		card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
+		card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
+		dvb_dmxdev_release(&card->dmxdev);
+		dvb_dmx_release(&card->demux);
+		dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0);
+		dvb_bt8xx_i2c_adap_free(card->i2c_adapter);
+		dvb_unregister_adapter(card->dvb_adapter);
+		
+		list_del(&card->list);
+		kfree(card);
+	}
+
+}
+
+module_init(dvb_bt8xx_init);
+module_exit(dvb_bt8xx_exit);
+MODULE_DESCRIPTION("Bt8xx based DVB adapter driver");
+MODULE_AUTHOR("Florian Schirmer <schirmer@taytron.net>");
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/bt8xx/dvb-bt8xx.h linux-2.6.0-p/drivers/media/dvb/bt8xx/dvb-bt8xx.h
--- linux-2.6.0/drivers/media/dvb/bt8xx/dvb-bt8xx.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/bt8xx/dvb-bt8xx.h	2003-11-25 13:10:26.000000000 +0100
@@ -0,0 +1,47 @@
+/*
+ * Bt8xx based DVB adapter driver 
+ *
+ * Copyright (C) 2002,2003 Florian Schirmer <schirmer@taytron.net>
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ * Copyright (C) 1999-2001 Ralph  Metzler & Marcus Metzler for convergence integrated media GmbH
+ * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.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/i2c.h>
+#include "dvbdev.h"
+#include "dvb_net.h"
+
+struct dvb_bt8xx_card {
+
+	struct list_head list;
+	u8 active;
+	char card_name[32];
+	struct dvb_adapter *dvb_adapter;
+	struct bt878 *bt;
+	unsigned int bttv_nr;
+	struct dvb_demux demux;
+	struct dmxdev dmxdev;
+	struct dmx_frontend fe_hw;
+	struct dmx_frontend fe_mem;
+	u32 gpio_mode;
+	u32 op_sync_orin;
+	u32 irq_err_ignore;
+	struct i2c_adapter *i2c_adapter;
+	struct dvb_net dvbnet;
+				
+};
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/Kconfig linux-2.6.0-p/drivers/media/dvb/frontends/Kconfig
--- linux-2.6.0/drivers/media/dvb/frontends/Kconfig	2003-12-18 03:58:16.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/Kconfig	2003-11-20 09:44:03.000000000 +0100
@@ -1,6 +1,17 @@
 comment "Supported Frontend Modules"
 	depends on DVB
 
+config DVB_TWINHAN_DST
+	tristate "TWINHAN DST based DVB-S frontend (QPSK)"
+	depends on DVB_CORE
+	help
+	  Used in such cards as the VP-1020/1030, Twinhan DST,
+	  VVmer TV@SAT. Say Y when you want to support frontends 
+	  using this asic.
+
+	  This module requires the dvb-bt8xx driver and dvb bt878
+	  module.
+
 config DVB_STV0299
 	tristate "STV0299 based DVB-S frontend (QPSK)"
 	depends on DVB_CORE
@@ -145,3 +155,19 @@
             wget http://www.technotrend.de/new/215/TTweb_215a_budget_20_05_2003.zip
             unzip -j TTweb_215a_budget_20_05_2003.zip Software/Oem/PCI/App/ttlcdacc.dll
             mv ttlcdacc.dll /etc/dvb/tda1004x.bin
+
+config DVB_SP887X_FIRMWARE_FILE
+        string "Full pathname of sp887x firmware file"
+        depends on DVB_SP887X
+        default "/etc/dvb/sc_main.mc"
+        help
+          This driver needs a copy of the Avermedia firmware. The version tested
+	  is part of the Avermedia DVB-T 1.3.26.3 Application. This can be downloaded
+	  from the Avermedia web site.
+	  If the software is installed in Windows the file will be in the
+	  /Program Files/AVerTV DVB-T/ directory and is called sc_main.mc.
+	  Alternatively it can "extracted" from the install cab files but this will have
+	  to be done in windows as I don't know of a linux version of extract.exe.
+	  Copy this file to /etc/dvb/sc_main.mc. With this version of the file the first
+	  10 bytes are discarded and the next 0x4000 loaded. This may change in future
+	  versions.
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/Makefile linux-2.6.0-p/drivers/media/dvb/frontends/Makefile
--- linux-2.6.0/drivers/media/dvb/frontends/Makefile	2003-12-18 03:58:03.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/Makefile	2003-10-13 12:52:18.000000000 +0200
@@ -4,6 +4,7 @@
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
 
+obj-$(CONFIG_DVB_TWINHAN_DST) += dst.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
 obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o
 obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/dst-bt878.h linux-2.6.0-p/drivers/media/dvb/frontends/dst-bt878.h
--- linux-2.6.0/drivers/media/dvb/frontends/dst-bt878.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/dst-bt878.h	2003-10-28 03:33:54.000000000 +0100
@@ -0,0 +1,33 @@
+
+struct dst_gpio_enable {
+	u32	mask;
+	u32	enable;
+};
+
+struct dst_gpio_output {
+	u32	mask;
+	u32	highvals;
+};
+
+struct dst_gpio_read {
+	unsigned long value;
+};
+
+union dst_gpio_packet {
+	struct dst_gpio_enable enb;
+	struct dst_gpio_output outp;
+	struct dst_gpio_read rd;
+	int    psize;
+};
+
+#define DST_IG_ENABLE	0
+#define DST_IG_WRITE	1
+#define DST_IG_READ	2
+#define DST_IG_TS       3
+
+struct bt878 ;
+
+int
+bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
+
+struct bt878 *bt878_find_by_dvb_adap(struct dvb_adapter *adap);
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/dst.c linux-2.6.0-p/drivers/media/dvb/frontends/dst.c
--- linux-2.6.0/drivers/media/dvb/frontends/dst.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/dst.c	2003-11-05 16:42:47.000000000 +0100
@@ -0,0 +1,1189 @@
+/* 
+    Frontend-driver for TwinHan DST Frontend
+
+    Copyright (C) 2003 Jamie Honan
+
+
+
+    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 <linux/vmalloc.h>
+#include <asm/div64.h>
+#include <asm/delay.h>
+
+#include "dvb_frontend.h"
+#include "dvb_functions.h"
+#include "dst-bt878.h"
+
+unsigned int dst_debug = 0;
+unsigned int dst_verbose = 0;
+
+MODULE_PARM(dst_verbose, "i");
+MODULE_PARM_DESC(dst_verbose,
+		 "verbose startup messages, default is 1 (yes)");
+MODULE_PARM(dst_debug, "i");
+MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)");
+
+unsigned int dst_type = (-1U);
+unsigned int dst_type_flags = (-1U);
+MODULE_PARM(dst_type, "i");
+MODULE_PARM_DESC(dst_type,
+		"Type of DST card, 0 Satellite, 1 terrestial TV, 2 Cable, default driver determined");
+MODULE_PARM(dst_type_flags, "i");
+MODULE_PARM_DESC(dst_type_flags,
+		"Type flags of DST card, bitfield 1=10 byte tuner, 2=TS is 204, 4=symdiv");
+
+#define dprintk	if (dst_debug) printk
+
+#define DST_TYPE_IS_SAT		0
+#define DST_TYPE_IS_TERR	1
+#define DST_TYPE_IS_CABLE	2
+
+#define DST_TYPE_HAS_NEWTUNE	1
+#define DST_TYPE_HAS_TS204	2
+#define DST_TYPE_HAS_SYMDIV	4
+
+#define HAS_LOCK	1
+#define ATTEMPT_TUNE	2
+#define HAS_POWER	4
+
+struct dst_data {
+	u8	tx_tuna[10];
+	u8	rx_tuna[10];
+	u8	rxbuffer[10];
+	u8	diseq_flags;
+	u8	dst_type;
+	u32	type_flags;
+	u32 frequency;     /* intermediate frequency in kHz for QPSK */
+        fe_spectral_inversion_t inversion;
+        u32   symbol_rate;  /* symbol rate in Symbols per second */
+	fe_code_rate_t  fec;
+	fe_sec_voltage_t voltage;
+	fe_sec_tone_mode_t tone;
+	u32 decode_freq;
+	u8  decode_lock;
+	u16 decode_strength;
+	u16 decode_snr;
+	unsigned long cur_jiff;
+	u8  k22;
+	fe_bandwidth_t bandwidth;
+	struct bt878 *bt;
+	struct dvb_i2c_bus *i2c;
+} ;
+
+static struct dvb_frontend_info dst_info_sat = {
+	.name 			= "DST SAT",
+	.type 			= FE_QPSK,
+	.frequency_min 		= 950000,
+	.frequency_max 		= 2150000,
+	.frequency_stepsize 	= 1000,           /* 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_AUTO |
+		FE_CAN_QPSK
+};
+
+static struct dvb_frontend_info dst_info_cable = {
+	.name 			= "DST CABLE",
+	.type 			= FE_QAM,
+        .frequency_stepsize 	= 62500,
+	.frequency_min 		= 51000000,
+	.frequency_max 		= 858000000,
+	.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_AUTO |
+		FE_CAN_QAM_AUTO
+};
+
+static struct dvb_frontend_info dst_info_tv = {
+	.name 			= "DST TERR",
+	.type 			= FE_OFDM,
+	.frequency_min 		= 137000000,
+	.frequency_max 		= 858000000,
+	.frequency_stepsize 	= 166667,
+	.caps = FE_CAN_INVERSION_AUTO |
+	    FE_CAN_FEC_AUTO |
+	    FE_CAN_QAM_AUTO |
+	    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
+};
+
+static void dst_packsize(struct dst_data *dst, int psize)
+{
+	union dst_gpio_packet bits;
+
+	bits.psize = psize;
+	bt878_device_control(dst->bt, DST_IG_TS, &bits);
+}
+
+static int dst_gpio_outb(struct dst_data *dst, u32 mask, u32 enbb, u32 outhigh)
+{
+	union dst_gpio_packet enb;
+	union dst_gpio_packet bits;
+	int err;
+
+	enb.enb.mask = mask;
+	enb.enb.enable = enbb;
+        if ((err = bt878_device_control(dst->bt, DST_IG_ENABLE, &enb)) < 0) {
+		dprintk ("%s: dst_gpio_enb error (err == %i, mask == 0x%02x, enb == 0x%02x)\n", __FUNCTION__, err, mask, enbb);
+		return -EREMOTEIO;
+	}
+
+	/* because complete disabling means no output, no need to do
+	 * output packet */
+	if (enbb == 0)
+		return 0;
+
+	bits.outp.mask = enbb;
+	bits.outp.highvals = outhigh;
+
+        if ((err = bt878_device_control(dst->bt, DST_IG_WRITE, &bits)) < 0) {
+		dprintk ("%s: dst_gpio_outb error (err == %i, enbb == 0x%02x, outhigh == 0x%02x)\n", __FUNCTION__, err, enbb, outhigh);
+		return -EREMOTEIO;
+	}
+        return 0;
+}
+
+static int dst_gpio_inb(struct dst_data *dst, u8 *result)
+{
+	union dst_gpio_packet rd_packet;
+	int err;
+
+	*result = 0;
+
+        if ((err = bt878_device_control(dst->bt, DST_IG_READ, &rd_packet)) < 0) {
+		dprintk ("%s: dst_gpio_inb error (err == %i)\n", __FUNCTION__, err);
+		return -EREMOTEIO;
+	}
+	*result = (u8)rd_packet.rd.value;
+        return 0;
+}
+
+#define DST_I2C_ENABLE	1
+#define DST_8820  	2
+
+static int
+dst_reset8820(struct dst_data *dst)
+{
+int retval;
+	/* pull 8820 gpio pin low, wait, high, wait, then low */
+	// dprintk ("%s: reset 8820\n", __FUNCTION__);
+	retval = dst_gpio_outb(dst, DST_8820, DST_8820, 0);
+	if (retval < 0)
+		return retval;
+	dvb_delay(10);
+	retval = dst_gpio_outb(dst, DST_8820, DST_8820, DST_8820);
+	if (retval < 0)
+		return retval;
+	/* wait for more feedback on what works here *
+	dvb_delay(10);
+	retval = dst_gpio_outb(dst, DST_8820, DST_8820, 0);
+	if (retval < 0)
+		return retval;
+	*/
+	return 0;
+}
+
+static int
+dst_i2c_enable(struct dst_data *dst)
+{
+int retval;
+	/* pull I2C enable gpio pin low, wait */
+	// dprintk ("%s: i2c enable\n", __FUNCTION__);
+	retval = dst_gpio_outb(dst, ~0, DST_I2C_ENABLE, 0);
+	if (retval < 0)
+		return retval;
+	// dprintk ("%s: i2c enable delay\n", __FUNCTION__);
+	dvb_delay(33);
+	return 0;
+}
+
+static int
+dst_i2c_disable(struct dst_data *dst)
+{
+int retval;
+	/* release I2C enable gpio pin, wait */
+	// dprintk ("%s: i2c disable\n", __FUNCTION__);
+	retval = dst_gpio_outb(dst, ~0, 0, 0);
+	if (retval < 0)
+		return retval;
+	// dprintk ("%s: i2c disable delay\n", __FUNCTION__);
+	dvb_delay(33);
+	return 0;
+}
+
+static int
+dst_wait_dst_ready(struct dst_data *dst)
+{
+u8 reply;
+int retval;
+int i;
+	for (i = 0; i < 200; i++) {
+		retval = dst_gpio_inb(dst, &reply);
+		if (retval < 0)
+			return retval;
+		if ((reply & DST_I2C_ENABLE) == 0) {
+			dprintk ("%s: dst wait ready after %d\n", __FUNCTION__, i);
+			return 1;
+		}
+		dvb_delay(5);
+	}
+	dprintk ("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
+	return 0;
+}
+
+#define DST_I2C_ADDR 0x55
+
+static int write_dst (struct dst_data *dst, u8 *data, u8 len)
+{
+	struct i2c_msg msg = {
+		.addr = DST_I2C_ADDR, .flags = 0, .buf = data, .len = len };
+	int err;
+	int cnt;
+
+	if (dst_debug && dst_verbose) {
+		u8 i;
+		dprintk("%s writing",__FUNCTION__);
+		for (i = 0 ; i < len ; i++) {
+			dprintk(" 0x%02x", data[i]);
+		}
+		dprintk("\n");
+	}
+	dvb_delay(30);
+	for (cnt = 0; cnt < 4; cnt++) {
+		if ((err = dst->i2c->xfer (dst->i2c, &msg, 1)) < 0) {
+			dprintk ("%s: write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
+			dst_i2c_disable(dst);
+			dvb_delay(500);
+			dst_i2c_enable(dst);
+			dvb_delay(500);
+			continue;
+		} else
+			break;
+	}
+	if (cnt >= 4)
+		return -EREMOTEIO;
+        return 0;
+}
+
+static int read_dst (struct dst_data *dst, u8 *ret, u8 len)
+{
+	struct i2c_msg msg = 
+		{ .addr = DST_I2C_ADDR, .flags = I2C_M_RD, .buf = ret, .len = len };
+	int err;
+	int cnt;
+
+	for (cnt = 0; cnt < 4; cnt++) {
+		if ((err = dst->i2c->xfer (dst->i2c, &msg, 1)) < 0) {
+			dprintk ("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]);
+			dst_i2c_disable(dst);
+			dst_i2c_enable(dst);
+			continue;
+		} else
+			break;
+	}
+	if (cnt >= 4)
+		return -EREMOTEIO;
+	dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
+	if (dst_debug && dst_verbose) {
+		for (err = 1; err < len; err++)
+			dprintk(" 0x%x", ret[err]);
+		if (err > 1)
+			dprintk("\n");
+	}
+	return 0;
+}
+
+static int dst_set_freq(struct dst_data *dst, u32 freq)
+{
+	u8 *val;
+
+	dst->frequency = freq;
+
+	// dprintk("%s: set frequency %u\n", __FUNCTION__, freq);
+	if (dst->dst_type == DST_TYPE_IS_SAT) {
+		freq = freq / 1000;
+		if (freq < 950 || freq > 2150)
+			return -EINVAL;
+		val = &dst->tx_tuna[0];
+		val[2] = (freq >> 8) & 0x7f;
+		val[3] = (u8)freq;
+		val[4] = 1;
+		val[8] &= ~4;
+		if (freq < 1531)
+			val[8] |= 4;
+	} else if (dst->dst_type == DST_TYPE_IS_TERR) {
+		freq = freq / 1000;
+		if (freq < 137000 || freq > 858000)
+			return -EINVAL;
+		val = &dst->tx_tuna[0];
+		val[2] = (freq >> 16) & 0xff;
+		val[3] = (freq >> 8) & 0xff;
+		val[4] = (u8)freq;
+		val[5] = 0;
+		switch (dst->bandwidth) {
+		case BANDWIDTH_6_MHZ:
+			val[6] = 6;
+			break;
+
+		case BANDWIDTH_7_MHZ:
+		case BANDWIDTH_AUTO:
+			val[6] = 7;
+			break;
+
+		case BANDWIDTH_8_MHZ:
+			val[6] = 8;
+			break;
+		}
+
+		val[7] = 0;
+		val[8] = 0;
+	} else if (dst->dst_type == DST_TYPE_IS_CABLE) {
+		/* guess till will get one */
+		freq = freq / 1000;
+		val = &dst->tx_tuna[0];
+		val[2] = (freq >> 16) & 0xff;
+		val[3] = (freq >> 8) & 0xff;
+		val[4] = (u8)freq;
+	} else
+		return -EINVAL;
+	return 0;
+}
+
+static int dst_set_bandwidth(struct dst_data *dst, fe_bandwidth_t bandwidth)
+{
+	u8 *val;
+
+	dst->bandwidth = bandwidth;
+
+	if (dst->dst_type != DST_TYPE_IS_TERR)
+		return 0;
+
+	val = &dst->tx_tuna[0];
+        switch (bandwidth) {
+	case BANDWIDTH_6_MHZ:
+		val[6] = 6;
+		break;
+
+	case BANDWIDTH_7_MHZ:
+		val[6] = 7;
+		break;
+
+	case BANDWIDTH_8_MHZ:
+		val[6] = 8;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int dst_set_inversion (struct dst_data *dst, fe_spectral_inversion_t inversion)
+{
+	u8 *val;
+
+	dst->inversion = inversion;
+
+	val = &dst->tx_tuna[0];
+
+	val[8] &= ~0x80;
+
+	switch (inversion) {
+	case INVERSION_OFF:
+		break;
+	case INVERSION_ON:
+		val[8] |= 0x80;
+		break;
+	case INVERSION_AUTO:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+static int dst_set_fec (struct dst_data *dst, fe_code_rate_t fec)
+{
+	dst->fec = fec;
+	return 0;
+}
+
+static fe_code_rate_t dst_get_fec (struct dst_data *dst)
+{
+	return dst->fec;
+}
+
+static int dst_set_symbolrate (struct dst_data *dst, u32 srate)
+{
+	u8 *val;
+	u32 symcalc;
+	u64 sval;
+
+	dst->symbol_rate = srate;
+
+	if (dst->dst_type == DST_TYPE_IS_TERR) {
+		return 0;
+	}
+
+	// dprintk("%s: set srate %u\n", __FUNCTION__, srate);
+	srate /= 1000;
+	val = &dst->tx_tuna[0];
+
+	if (dst->type_flags & DST_TYPE_HAS_SYMDIV) {
+		sval = srate;
+		sval <<= 20;
+		do_div(sval, 88000);
+	        symcalc = (u32)sval;
+		// dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
+		val[5] = (u8)(symcalc >> 12);
+		val[6] = (u8)(symcalc >> 4);
+		val[7] = (u8)(symcalc << 4);
+	} else {
+		val[5] = (u8)(srate >> 16) & 0x7f;
+		val[6] = (u8)(srate >> 8);
+		val[7] = (u8)srate;
+	}
+	val[8] &= ~0x20;
+	if (srate > 8000)
+		val[8] |= 0x20;
+	return 0;
+}
+
+
+static u8 dst_check_sum(u8 *buf, u32 len)
+{
+	u32 i;
+	u8  val = 0;
+	if (!len)
+		return 0;
+	for (i = 0; i < len; i++) {
+		val += buf[i];
+	}
+	return ((~val) + 1);
+}
+
+typedef struct dst_types {
+	char	*mstr;
+	int	offs;
+	u8	dst_type;
+	u32	type_flags;
+} DST_TYPES;
+
+struct dst_types dst_tlist[] = {
+	{ "DST-020", 0,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_SYMDIV },
+	{ "DST-030", 0,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },
+	{ "DST-03T", 0,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_SYMDIV|DST_TYPE_HAS_TS204},
+	{ "DST-MOT", 0,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_SYMDIV },
+	{ "DST-CI",  1,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },
+	{ "DSTMCI",  1,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_NEWTUNE },
+	{ "DSTFCI",  1,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_NEWTUNE },
+	{ "DCTNEW",  1,  DST_TYPE_IS_CABLE,  DST_TYPE_HAS_NEWTUNE },
+	{ "DCT_CI",  1,  DST_TYPE_IS_CABLE,  DST_TYPE_HAS_NEWTUNE|DST_TYPE_HAS_TS204 },
+	{ "DTTDIG" , 1,  DST_TYPE_IS_TERR,   0} };
+/* DCTNEW and DCT-CI are guesses */
+
+static void dst_type_flags_print(u32 type_flags)
+{
+	printk("DST type flags :");
+	if (type_flags & DST_TYPE_HAS_NEWTUNE)
+		printk(" 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+	if (type_flags & DST_TYPE_HAS_TS204)
+		printk(" 0x%x ts204", DST_TYPE_HAS_TS204);
+	if (type_flags & DST_TYPE_HAS_SYMDIV)
+		printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+	printk("\n");
+}
+
+static int dst_type_print(u8 type)
+{
+	char *otype;
+	switch (type) {
+		case DST_TYPE_IS_SAT:
+			otype = "satellite";
+			break;
+		case DST_TYPE_IS_TERR:
+			otype = "terrestial TV";
+			break;
+		case DST_TYPE_IS_CABLE:
+			otype = "terrestial TV";
+			break;
+		default:
+			printk("%s: invalid dst type %d\n",
+				__FUNCTION__, type);
+			return -EINVAL;
+	}
+	printk("DST type : %s\n", otype);
+	return 0;
+}
+
+static int dst_check_ci (struct dst_data *dst)
+{
+	u8 txbuf[8];
+	u8 rxbuf[8];
+	int retval;
+	int i;
+	struct dst_types *dsp;
+	u8 use_dst_type;
+	u32 use_type_flags;
+
+	memset(txbuf, 0, sizeof(txbuf));
+	txbuf[1] = 6;
+	txbuf[7] = dst_check_sum (txbuf, 7);
+ 
+	dst_i2c_enable(dst);
+	dst_reset8820(dst);
+	retval = write_dst (dst, txbuf, 8);
+	if (retval < 0) {
+		dst_i2c_disable(dst);
+		dprintk("%s: write not successful, maybe no card?\n", __FUNCTION__);
+		return retval;
+	}
+	dvb_delay(3);
+	retval = read_dst (dst, rxbuf, 1);
+	dst_i2c_disable(dst);
+	if (retval < 0) {
+		dprintk("%s: read not successful, maybe no card?\n", __FUNCTION__);
+		return retval;
+	}
+	if (rxbuf[0] != 0xff) {
+		dprintk("%s: write reply not 0xff, not ci (%02x)\n", __FUNCTION__, rxbuf[0]);
+		return retval;
+	}
+	if (!dst_wait_dst_ready(dst))
+		return 0;
+	// dst_i2c_enable(i2c); Dimitri
+	retval = read_dst (dst, rxbuf, 8);
+	dst_i2c_disable(dst);
+	if (retval < 0) {
+		dprintk("%s: read not successful\n", __FUNCTION__);
+		return retval;
+	}
+	if (rxbuf[7] != dst_check_sum (rxbuf, 7)) {
+		dprintk("%s: checksum failure\n", __FUNCTION__);
+		return retval;
+	}
+	rxbuf[7] = '\0';
+	for (i = 0, dsp = &dst_tlist[0]; i < sizeof(dst_tlist) / sizeof(dst_tlist[0]); i++, dsp++) {
+		if (!strncmp(&rxbuf[dsp->offs],
+				dsp->mstr,
+				strlen(dsp->mstr))) {
+			use_type_flags = dsp->type_flags;
+			use_dst_type = dsp->dst_type;
+			printk("%s: recognize %s\n", __FUNCTION__, dsp->mstr);
+			break;
+		}
+	}
+	if (i >= sizeof(dst_tlist) / sizeof(dst_tlist[0])) {
+		printk("%s: unable to recognize %s or %s\n", __FUNCTION__, &rxbuf[0], &rxbuf[1]);
+		printk("%s please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__);
+		use_dst_type = DST_TYPE_IS_SAT;
+		use_type_flags = DST_TYPE_HAS_SYMDIV;
+	}
+	switch (dst_type) {
+		case (-1U):
+			/* not used */
+			break;
+		case DST_TYPE_IS_SAT:
+		case DST_TYPE_IS_TERR:
+		case DST_TYPE_IS_CABLE:
+			use_dst_type = (u8)dst_type;
+			break;
+		default:
+			printk("%s: invalid user override dst type %d, not used\n",
+				__FUNCTION__, dst_type);
+			break;
+	}
+	dst_type_print(use_dst_type);
+	if (dst_type_flags != (-1U)) {
+		printk("%s: user override dst type flags 0x%x\n",
+				__FUNCTION__, dst_type_flags);
+		use_type_flags = dst_type_flags;
+	}
+	dst->type_flags = use_type_flags;
+	dst->dst_type= use_dst_type;
+	dst_type_flags_print(dst->type_flags);
+
+	if (dst->type_flags & DST_TYPE_HAS_TS204) {
+		dst_packsize(dst, 204);
+	}
+	return 0;
+}
+
+static int dst_command (struct dst_data *dst, u8 *data, u8 len)
+{
+	int retval;
+	u8 reply;
+
+	dst_i2c_enable(dst);
+	dst_reset8820(dst);
+	retval = write_dst (dst, data, len);
+	if (retval < 0) {
+		dst_i2c_disable(dst);
+		dprintk("%s: write not successful\n", __FUNCTION__);
+		return retval;
+	}
+	dvb_delay(33);
+	retval = read_dst (dst, &reply, 1);
+	dst_i2c_disable(dst);
+	if (retval < 0) {
+		dprintk("%s: read verify  not successful\n", __FUNCTION__);
+		return retval;
+	}
+	if (reply != 0xff) {
+		dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply);
+		return 0;
+	}
+	if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
+		return 0;
+	if (!dst_wait_dst_ready(dst))
+		return 0;
+	// dst_i2c_enable(i2c); Per dimitri
+	retval = read_dst (dst, dst->rxbuffer, 8);
+	dst_i2c_disable(dst);
+	if (retval < 0) {
+		dprintk("%s: read not successful\n", __FUNCTION__);
+		return 0;
+	}
+	if (dst->rxbuffer[7] != dst_check_sum (dst->rxbuffer, 7)) {
+		dprintk("%s: checksum failure\n", __FUNCTION__);
+		return 0;
+	}
+	return 0;
+}
+
+static int dst_get_signal(struct dst_data *dst)
+{
+	int retval;
+	u8 get_signal[] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb};
+
+	if ((dst->diseq_flags & ATTEMPT_TUNE) == 0) {
+		dst->decode_lock = dst->decode_strength = dst->decode_snr = 0;
+		return 0;
+	}
+	if (0 == (dst->diseq_flags & HAS_LOCK)) {
+		dst->decode_lock = dst->decode_strength = dst->decode_snr = 0;
+		return 0;
+	}
+	if (time_after_eq(jiffies, dst->cur_jiff + (HZ/5))) {
+		retval =  dst_command(dst, get_signal, 8);
+		if (retval < 0)
+			return retval;
+		if (dst->dst_type == DST_TYPE_IS_SAT) {
+			dst->decode_lock = ((dst->rxbuffer[6] & 0x10) == 0) ?
+					1 : 0;
+			dst->decode_strength = dst->rxbuffer[5] << 8;
+			dst->decode_snr = dst->rxbuffer[2] << 8 |
+				dst->rxbuffer[3];
+		} else if ((dst->dst_type == DST_TYPE_IS_TERR) ||
+				(dst->dst_type == DST_TYPE_IS_CABLE)) {
+			dst->decode_lock = (dst->rxbuffer[1]) ?
+					1 : 0;
+			dst->decode_strength = dst->rxbuffer[4] << 8;
+			dst->decode_snr = dst->rxbuffer[3] << 8;
+		}
+		dst->cur_jiff = jiffies;
+	}
+	return 0;
+}
+
+/*
+ * line22k0    0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00
+ * line22k1    0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00
+ * line22k2    0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00
+ * tone        0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00
+ * data        0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00
+ * power_off   0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+ * power_on    0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00
+ * Diseqc 1    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec
+ * Diseqc 2    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8 
+ * Diseqc 3    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4 
+ * Diseqc 4    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0 
+ */
+
+static int dst_set_diseqc (struct dst_data *dst, u8 *cmd, u8 len)
+{
+	u8 paket[8] =  {0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
+
+	if (dst->dst_type == DST_TYPE_IS_TERR)
+		return 0;
+
+	if (len == 0 || len > 4)
+		return -EINVAL;
+	memcpy(&paket[3], cmd, len);
+	paket[7] = dst_check_sum (&paket[0], 7);
+	dst_command(dst, paket, 8);
+	return 0;
+}
+
+static int dst_tone_power_cmd (struct dst_data *dst)
+{
+	u8 paket[8] =  {0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00};
+
+	if (dst->dst_type == DST_TYPE_IS_TERR)
+		return 0;
+
+	if (dst->voltage == SEC_VOLTAGE_OFF) 
+		paket[4] = 0;
+	else
+		paket[4] = 1;
+	if (dst->tone == SEC_TONE_ON)
+		paket[2] = dst->k22;
+	else
+		paket[2] = 0;
+	paket[7] = dst_check_sum (&paket[0], 7);
+	dst_command(dst, paket, 8);
+	return 0;
+}
+
+static int dst_set_voltage (struct dst_data *dst, fe_sec_voltage_t voltage)
+{
+	u8 *val;
+	int need_cmd;
+
+	dst->voltage = voltage;
+
+	if (dst->dst_type == DST_TYPE_IS_TERR)
+		return 0;
+
+	need_cmd = 0;
+	val = &dst->tx_tuna[0];
+	val[8] &= ~0x40;
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		if ((dst->diseq_flags & HAS_POWER) == 0)
+			need_cmd = 1;
+		dst->diseq_flags |= HAS_POWER;
+		break;
+	case SEC_VOLTAGE_18:
+		if ((dst->diseq_flags & HAS_POWER) == 0)
+			need_cmd = 1;
+		dst->diseq_flags |= HAS_POWER;
+		val[8] |= 0x40;
+		break;
+	case SEC_VOLTAGE_OFF:
+		need_cmd = 1;
+		dst->diseq_flags &= ~(HAS_POWER|HAS_LOCK|ATTEMPT_TUNE);
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (need_cmd) {
+		dst_tone_power_cmd(dst);
+	}
+	return 0;
+}
+
+
+static int dst_set_tone (struct dst_data *dst, fe_sec_tone_mode_t tone)
+{
+	u8 *val;
+
+	dst->tone = tone;
+
+	if (dst->dst_type == DST_TYPE_IS_TERR)
+		return 0;
+
+	val = &dst->tx_tuna[0];
+
+	val[8] &= ~0x1;
+
+	switch (tone) {
+	case SEC_TONE_OFF:
+		break;
+	case SEC_TONE_ON:
+		val[8] |= 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	dst_tone_power_cmd(dst);
+	return 0;
+}
+
+static int dst_get_tuna (struct dst_data *dst)
+{
+int retval;
+	if ((dst->diseq_flags & ATTEMPT_TUNE) == 0)
+		return 0;
+	dst->diseq_flags &= ~(HAS_LOCK);
+	if (!dst_wait_dst_ready(dst))
+		return 0;
+	if (dst->type_flags & DST_TYPE_HAS_NEWTUNE) {
+		/* how to get variable length reply ???? */
+		retval = read_dst (dst, dst->rx_tuna, 10);
+	} else {
+		retval = read_dst (dst, &dst->rx_tuna[2], 8);
+	}
+	if (retval < 0) {
+		dprintk("%s: read not successful\n", __FUNCTION__);
+		return 0;
+	}
+	if (dst->type_flags & DST_TYPE_HAS_NEWTUNE) {
+		if (dst->rx_tuna[9] != dst_check_sum (&dst->rx_tuna[0], 9)) {
+			dprintk("%s: checksum failure?\n", __FUNCTION__);
+			return 0;
+		}
+	} else {
+		if (dst->rx_tuna[9] != dst_check_sum (&dst->rx_tuna[2], 7)) {
+			dprintk("%s: checksum failure?\n", __FUNCTION__);
+			return 0;
+		}
+	}
+	if (dst->rx_tuna[2] == 0 && dst->rx_tuna[3] == 0)
+		return 0;
+	dst->decode_freq = ((dst->rx_tuna[2] & 0x7f) << 8) +  dst->rx_tuna[3];
+
+	dst->decode_lock = 1;
+	/*
+	dst->decode_n1 = (dst->rx_tuna[4] << 8) +  
+			(dst->rx_tuna[5]);
+
+	dst->decode_n2 = (dst->rx_tuna[8] << 8) +  
+			(dst->rx_tuna[7]);
+	*/
+	dst->diseq_flags |= HAS_LOCK;
+	/* dst->cur_jiff = jiffies; */
+	return 1;
+}
+
+static int dst_write_tuna (struct dst_data *dst)
+{
+	int retval;
+	u8 reply;
+
+	dprintk("%s: type_flags 0x%x \n", __FUNCTION__, dst->type_flags);
+	dst->decode_freq = 0;
+	dst->decode_lock = dst->decode_strength = dst->decode_snr = 0;
+	if (dst->dst_type == DST_TYPE_IS_SAT) {
+		if (!(dst->diseq_flags & HAS_POWER))
+			dst_set_voltage (dst, SEC_VOLTAGE_13);
+	}
+	dst->diseq_flags &= ~(HAS_LOCK|ATTEMPT_TUNE);
+	dst_i2c_enable(dst);
+	if (dst->type_flags & DST_TYPE_HAS_NEWTUNE) {
+		dst_reset8820(dst);
+		dst->tx_tuna[9] = dst_check_sum (&dst->tx_tuna[0], 9);
+		retval = write_dst (dst, &dst->tx_tuna[0], 10);
+	} else {
+		dst->tx_tuna[9] = dst_check_sum (&dst->tx_tuna[2], 7);
+		retval = write_dst (dst, &dst->tx_tuna[2], 8);
+	}
+	if (retval < 0) {
+		dst_i2c_disable(dst);
+		dprintk("%s: write not successful\n", __FUNCTION__);
+		return retval;
+	}
+	dvb_delay(3);
+	retval = read_dst (dst, &reply, 1);
+	dst_i2c_disable(dst);
+	if (retval < 0) {
+		dprintk("%s: read verify  not successful\n", __FUNCTION__);
+		return retval;
+	}
+	if (reply != 0xff) {
+		dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply);
+		return 0;
+	}
+	dst->diseq_flags |= ATTEMPT_TUNE;
+	return dst_get_tuna(dst);
+}
+
+static void dst_init (struct dst_data *dst)
+{
+static u8 ini_satci_tuna[] = {  9, 0, 3, 0xb6, 1, 0,    0x73, 0x21, 0, 0 };
+static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 };
+static u8 ini_tvfta_tuna[] = { 0, 0,  3, 0xb6, 1, 7,    0x0,   0x0, 0, 0 };
+static u8 ini_tvci_tuna[] = { 9, 0,  3, 0xb6, 1, 7,    0x0,   0x0, 0, 0 };
+static u8 ini_cabfta_tuna[] = { 0, 0,  3, 0xb6, 1, 7,    0x0,   0x0, 0, 0 };
+static u8 ini_cabci_tuna[] = { 9, 0,  3, 0xb6, 1, 7,    0x0,   0x0, 0, 0 };
+	dst->inversion = INVERSION_ON;
+	dst->voltage = SEC_VOLTAGE_13;
+	dst->tone = SEC_TONE_OFF;
+	dst->symbol_rate = 29473000;
+	dst->fec = FEC_AUTO;
+	dst->diseq_flags = 0;
+	dst->k22 = 0x02;
+	dst->bandwidth = BANDWIDTH_7_MHZ;
+	dst->cur_jiff = jiffies;
+	if (dst->dst_type == DST_TYPE_IS_SAT) {
+		dst->frequency = 950000;
+		memcpy(dst->tx_tuna, ((dst->type_flags &  DST_TYPE_HAS_NEWTUNE )? 
+					ini_satci_tuna : ini_satfta_tuna),
+				sizeof(ini_satfta_tuna));
+	} else if (dst->dst_type == DST_TYPE_IS_TERR) {
+		dst->frequency = 137000000;
+		memcpy(dst->tx_tuna, ((dst->type_flags &  DST_TYPE_HAS_NEWTUNE )? 
+					ini_tvci_tuna : ini_tvfta_tuna),
+				sizeof(ini_tvfta_tuna));
+	} else if (dst->dst_type == DST_TYPE_IS_CABLE) {
+		dst->frequency = 51000000;
+		memcpy(dst->tx_tuna, ((dst->type_flags &  DST_TYPE_HAS_NEWTUNE )? 
+					ini_cabci_tuna : ini_cabfta_tuna),
+				sizeof(ini_cabfta_tuna));
+	}
+}
+
+struct lkup {
+	unsigned int cmd;
+	char *desc;
+} looker[] = {
+	{FE_GET_INFO,                "FE_GET_INFO:"},
+	{FE_READ_STATUS,             "FE_READ_STATUS:" },
+	{FE_READ_BER,                "FE_READ_BER:" },
+	{FE_READ_SIGNAL_STRENGTH,    "FE_READ_SIGNAL_STRENGTH:" },
+	{FE_READ_SNR,                "FE_READ_SNR:" },
+	{FE_READ_UNCORRECTED_BLOCKS, "FE_READ_UNCORRECTED_BLOCKS:" },
+	{FE_SET_FRONTEND,            "FE_SET_FRONTEND:" },
+	{FE_GET_FRONTEND,            "FE_GET_FRONTEND:" },
+	{FE_SLEEP,                   "FE_SLEEP:" },
+	{FE_INIT,                    "FE_INIT:" },
+	{FE_RESET,                   "FE_RESET:" },
+	{FE_SET_TONE,                "FE_SET_TONE:" },
+	{FE_SET_VOLTAGE,             "FE_SET_VOLTAGE:" },
+	};
+
+static int dst_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
+{
+	struct dst_data *dst = fe->data;
+	int retval;
+	/*
+	char  *cc;
+                
+	cc = "FE_UNSUPP:";
+	for(retval = 0; retval < sizeof(looker) / sizeof(looker[0]); retval++) {
+		if (looker[retval].cmd == cmd) {
+			cc = looker[retval].desc;
+			break;
+		}
+	}
+	dprintk("%s cmd %s (0x%x)\n",__FUNCTION__, cc, cmd);
+	*/
+	// printk("%s: dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, dst, dst->bt, dst->i2c);
+	/* should be set by attach, but just in case */
+	dst->i2c = fe->i2c;
+        switch (cmd) {
+        case FE_GET_INFO: 
+	{
+	     struct dvb_frontend_info *info;
+		info = &dst_info_sat;
+		if (dst->dst_type == DST_TYPE_IS_TERR)
+			info = &dst_info_tv;
+		else if (dst->dst_type == DST_TYPE_IS_CABLE)
+			info = &dst_info_cable;
+		memcpy (arg, info, sizeof(struct dvb_frontend_info));
+		break;
+	}
+        case FE_READ_STATUS:
+	{
+		fe_status_t *status = arg;
+
+		*status = 0;
+		if (dst->diseq_flags & HAS_LOCK) {
+			dst_get_signal(dst);
+			if (dst->decode_lock)
+				*status |= FE_HAS_LOCK 
+					| FE_HAS_SIGNAL 
+					| FE_HAS_CARRIER
+					| FE_HAS_SYNC
+					| FE_HAS_VITERBI;
+		}
+		break;
+	}
+
+        case FE_READ_BER:
+	{
+		/* guess */
+		// *(u32*) arg = dst->decode_n1;
+		*(u32*) arg = 0;
+		return -EOPNOTSUPP; 
+	}
+
+        case FE_READ_SIGNAL_STRENGTH:
+	{
+		dst_get_signal(dst);
+		*((u16*) arg) = dst->decode_strength;
+		break;
+	}
+
+        case FE_READ_SNR:
+	{
+		dst_get_signal(dst);
+		*((u16*) arg) = dst->decode_snr;
+		break;
+	}
+
+	case FE_READ_UNCORRECTED_BLOCKS: 
+	{
+		*((u32*) arg) = 0;    /* the stv0299 can't measure BER and */
+		return -EOPNOTSUPP;   /* errors at the same time.... */
+	}
+
+        case FE_SET_FRONTEND:
+        {
+		struct dvb_frontend_parameters *p = arg;
+
+		dst_set_freq (dst, p->frequency);
+		dst_set_inversion (dst, p->inversion);
+		if (dst->dst_type == DST_TYPE_IS_SAT) {
+			dst_set_fec (dst, p->u.qpsk.fec_inner);
+			dst_set_symbolrate (dst, p->u.qpsk.symbol_rate);
+		} else if (dst->dst_type == DST_TYPE_IS_TERR) {
+			dst_set_bandwidth(dst, p->u.ofdm.bandwidth);
+		} else if (dst->dst_type == DST_TYPE_IS_CABLE) {
+			dst_set_fec (dst, p->u.qam.fec_inner);
+			dst_set_symbolrate (dst, p->u.qam.symbol_rate);
+		}
+		dst_write_tuna (dst);
+
+                break;
+        }
+
+	case FE_GET_FRONTEND:
+	{
+		struct dvb_frontend_parameters *p = arg;
+
+
+		p->frequency = dst->decode_freq;
+		p->inversion = dst->inversion;
+		if (dst->dst_type == DST_TYPE_IS_SAT) {
+			p->u.qpsk.symbol_rate = dst->symbol_rate;
+			p->u.qpsk.fec_inner = dst_get_fec (dst);
+		} else if (dst->dst_type == DST_TYPE_IS_TERR) {
+			p->u.ofdm.bandwidth = dst->bandwidth;
+		} else if (dst->dst_type == DST_TYPE_IS_CABLE) {
+			p->u.qam.symbol_rate = dst->symbol_rate;
+			p->u.qam.fec_inner = dst_get_fec (dst);
+			p->u.qam.modulation = QAM_AUTO;
+		}
+		break;
+	}
+
+        case FE_SLEEP:
+		return 0;
+
+        case FE_INIT:
+		dst_init(dst);
+		break;
+
+	case FE_RESET:
+		break;
+
+	case FE_DISEQC_SEND_MASTER_CMD:
+	{
+		struct dvb_diseqc_master_cmd *cmd = (struct dvb_diseqc_master_cmd *)arg;
+		retval = dst_set_diseqc (dst, cmd->msg, cmd->msg_len);
+		if (retval < 0)
+			return retval;
+		break;
+	}
+	case FE_SET_TONE:
+		retval = dst_set_tone (dst, (fe_sec_tone_mode_t) arg);
+		if (retval < 0)
+			return retval;
+		break;
+	case FE_SET_VOLTAGE:
+		retval = dst_set_voltage (dst, (fe_sec_voltage_t) arg);
+		if (retval < 0)
+			return retval;
+		break;
+	default:
+		return -EOPNOTSUPP;
+        };
+        
+        return 0;
+} 
+
+
+static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
+{
+	struct dst_data *dst;
+	struct bt878 *bt;
+	struct dvb_frontend_info *info;
+
+	dprintk("%s: check ci\n", __FUNCTION__);
+	bt = bt878_find_by_dvb_adap(i2c->adapter);
+	if (!bt)
+		return -ENODEV;
+	dst = kmalloc(sizeof(struct dst_data), GFP_KERNEL);
+	if (dst == NULL) {
+		printk(KERN_INFO "%s: Out of memory.\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	memset(dst, 0, sizeof(*dst));
+	*data = dst;
+	dst->bt = bt;
+	dst->i2c = i2c;
+	if (dst_check_ci(dst) < 0) {
+		kfree(dst);
+		return -ENODEV;
+	}
+
+	dst_init (dst);
+	dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, 
+			(u32)dst, (u32)(dst->bt), (u32)(dst->i2c));
+
+	info = &dst_info_sat;
+	if (dst->dst_type == DST_TYPE_IS_TERR)
+		info = &dst_info_tv;
+	else if (dst->dst_type == DST_TYPE_IS_CABLE)
+		info = &dst_info_cable;
+
+	dvb_register_frontend (dst_ioctl, i2c, dst, info);
+
+	return 0;
+}
+
+static void dst_detach (struct dvb_i2c_bus *i2c, void *data)
+{
+	dvb_unregister_frontend (dst_ioctl, i2c);
+	dprintk("%s: unregister dst %8.8x\n", __FUNCTION__, (u32)(data));
+	if (data)
+		kfree(data);
+}
+
+static int __init init_dst (void)
+{
+	return dvb_register_i2c_device (THIS_MODULE, dst_attach, dst_detach);
+}
+
+static void __exit exit_dst (void)
+{
+	dvb_unregister_i2c_device (dst_attach);
+}
+
+
+module_init(init_dst);
+module_exit(exit_dst);
+
+MODULE_DESCRIPTION("DST DVB-S Frontend");
+MODULE_AUTHOR("Jamie Honan");
+MODULE_LICENSE("GPL");
+


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 4/12] Update Skystar2 DVB driver
  2003-12-19 12:28     ` [PATCH 3/12] Add new DVB driver Michael Hunold
@ 2003-12-19 12:28       ` Michael Hunold
  2003-12-19 12:28         ` [PATCH 5/12] Update DVB core Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - complete revamp of the original driver: code beautification + linux coding sytle, full diseqc support, hardware filtering support, support for different card revisions and lots of other stuff. 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/b2c2/skystar2.c linux-2.6.0-p/drivers/media/dvb/b2c2/skystar2.c
--- linux-2.6.0/drivers/media/dvb/b2c2/skystar2.c	2003-12-18 03:59:16.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/b2c2/skystar2.c	2003-12-11 15:03:39.000000000 +0100
@@ -2,7 +2,19 @@
  * skystar2.c - driver for the Technisat SkyStar2 PCI DVB card
  *              based on the FlexCopII by B2C2,Inc.
  *
- * Copyright (C) 2003  V.C. , skystar@moldova.cc
+ * Copyright (C) 2003  Vadim Catana, skystar@moldova.cc
+ *
+ * FIX: DISEQC Tone Burst in flexcop_diseqc_ioctl()
+ * FIX: FULL soft DiSEqC for skystar2 (FlexCopII rev 130) VP310 equipped 
+ *     Vincenzo Di Massa, hawk.it at tiscalinet.it
+ * 	
+ * Converted to Linux coding style
+ * Misc reorganization, polishing, restyling
+ *     Roberto Ragusa, r.ragusa at libero.it
+ *       
+ * Added hardware filtering support, 
+ *     Niklas Peinecke, peinecke at gdv.uni-hannover.de
+ *
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -27,7 +40,6 @@
 
 #include "dvb_i2c.h"
 #include "dvb_frontend.h"
-#include "dvb_functions.h"
 
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/dmx.h>
@@ -38,14 +50,20 @@
 #include "demux.h"
 #include "dvb_net.h"
 
+#include "dvb_functions.h"
+
 static int debug = 0;
-#define dprintk(x...) do { if (debug) printk(x); } while (0)
+#define dprintk(x...)	do { if (debug>=1) printk(x); } while (0)
+#define ddprintk(x...)	do { if (debug>=2) printk(x); } while (0)
+static int enable_hw_filters = 2;
 
-#define SizeOfBufDMA1	0x3AC00
-#define SizeOfBufDMA2	0x758
+#define SIZE_OF_BUF_DMA1	0x3ac00
+#define SIZE_OF_BUF_DMA2	0x758
 
-struct dmaq {
+#define MAX_N_HW_FILTERS	(6+32)
+#define N_PID_SLOTS		256
 
+struct dmaq {
 	u32 bus_addr;
 	u32 head;
 	u32 tail;
@@ -53,20 +71,8 @@
 	u8 *buffer;
 };
 
-struct packet_header {
-
-	u32 sync_byte;
-	u32 transport_error_indicator;
-	u32 payload_unit_start_indicator;
-	u32 transport_priority;
-	u32 pid;
-	u32 transport_scrambling_control;
-	u32 adaptation_field_control;
-	u32 continuity_counter;
-};
 
 struct adapter {
-
 	struct pci_dev *pdev;
 
 	u8 card_revision;
@@ -71,13 +77,13 @@
 
 	u8 card_revision;
 	u32 b2c2_revision;
-	u32 PidFilterMax;
-	u32 MacFilterMax;
+	u32 pid_filter_max;
+	u32 mac_filter_max;
 	u32 irq;
 	unsigned long io_mem;
 	unsigned long io_port;
 	u8 mac_addr[8];
-	u32 dwSramType;
+	u32 dw_sram_type;
 
 	struct dvb_adapter *dvb_adapter;
 	struct dvb_demux demux;
@@ -95,44 +101,42 @@
 	u32 dma_ctrl;
 	u32 dma_status;
 
-	u32 capturing;
+	int capturing;
 
 	spinlock_t lock;
 
-	u16 pids[0x27];
+	int useable_hw_filters;
+	u16 hw_pids[MAX_N_HW_FILTERS];
+	u16 pid_list[N_PID_SLOTS];
+	int pid_rc[N_PID_SLOTS];	// ref counters for the pids
+	int pid_count;
+	int whole_bandwidth_count;
 	u32 mac_filter;
 };
 
-#define WriteRegDW(adapter,reg,value) writel(value, adapter->io_mem + reg)
-#define ReadRegDW(adapter,reg) readl(adapter->io_mem + reg)
+#define write_reg_dw(adapter,reg,value) writel(value, adapter->io_mem + reg)
+#define read_reg_dw(adapter,reg) readl(adapter->io_mem + reg)
 
-static void WriteRegOp(struct adapter *adapter, u32 reg, u32 operation, u32 andvalue, u32 orvalue)
+static void write_reg_bitfield(struct adapter *adapter, u32 reg, u32 zeromask, u32 orvalue)
 {
 	u32 tmp;
 
-	tmp = ReadRegDW(adapter, reg);
-
-	if (operation == 1)
-		tmp = tmp | orvalue;
-	if (operation == 2)
-		tmp = tmp & andvalue;
-	if (operation == 3)
-		tmp = (tmp & andvalue) | orvalue;
-
-	WriteRegDW(adapter, reg, tmp);
+	tmp = read_reg_dw(adapter, reg);
+	tmp = (tmp & ~zeromask) | orvalue;
+	write_reg_dw(adapter, reg, tmp);
 }
 
 /* i2c functions */
-static int i2cMainWriteForFlex2(struct adapter * adapter, u32 command, u8 * buf, u32 retries)
+static int i2c_main_write_for_flex2(struct adapter *adapter, u32 command, u8 *buf, int retries)
 {
-	u32 i;
+	int i;
 	u32 value;
 
-	WriteRegDW(adapter, 0x100, 0);
-	WriteRegDW(adapter, 0x100, command);
+	write_reg_dw(adapter, 0x100, 0);
+	write_reg_dw(adapter, 0x100, command);
 
 	for (i = 0; i < retries; i++) {
-		value = ReadRegDW(adapter, 0x100);
+		value = read_reg_dw(adapter, 0x100);
 
 		if ((value & 0x40000000) == 0) {
 			if ((value & 0x81000000) == 0x80000000) {
@@ -141,11 +145,9 @@
 
 				return 1;
 			}
-
 		} else {
-
-			WriteRegDW(adapter, 0x100, 0);
-			WriteRegDW(adapter, 0x100, command);
+			write_reg_dw(adapter, 0x100, 0);
+			write_reg_dw(adapter, 0x100, command);
 		}
 	}
 
@@ -153,7 +155,7 @@
 }
 
 /* device = 0x10000000 for tuner, 0x20000000 for eeprom */
-static void i2cMainSetup(u32 device, u32 chip_addr, u8 op, u8 addr, u32 value, u32 len, u32 *command)
+static void i2c_main_setup(u32 device, u32 chip_addr, u8 op, u8 addr, u32 value, u32 len, u32 *command)
 {
 	*command = device | ((len - 1) << 26) | (value << 16) | (addr << 8) | chip_addr;
 
@@ -163,20 +165,20 @@
 		*command = *command | 0x01000000;
 }
 
-static int FlexI2cRead4(struct adapter * adapter, u32 device, u32 chip_addr, u16 addr, u8 * buf, u8 len)
+static int flex_i2c_read4(struct adapter *adapter, u32 device, u32 chip_addr, u16 addr, u8 *buf, u8 len)
 {
 	u32 command;
 	u32 value;
 
 	int result, i;
 
-	i2cMainSetup(device, chip_addr, 1, addr, 0, len, &command);
+	i2c_main_setup(device, chip_addr, 1, addr, 0, len, &command);
 
-	result = i2cMainWriteForFlex2(adapter, command, buf, 100000);
+	result = i2c_main_write_for_flex2(adapter, command, buf, 100000);
 
 	if ((result & 0xff) != 0) {
 		if (len > 1) {
-			value = ReadRegDW(adapter, 0x104);
+			value = read_reg_dw(adapter, 0x104);
 
 			for (i = 1; i < len; i++) {
 				buf[i] = value & 0xff;
@@ -188,7 +190,7 @@
 	return result;
 }
 
-static int FlexI2cWrite4(struct adapter * adapter, u32 device, u32 chip_addr, u32 addr, u8 * buf, u8 len)
+static int flex_i2c_write4(struct adapter *adapter, u32 device, u32 chip_addr, u32 addr, u8 *buf, u8 len)
 {
 	u32 command;
 	u32 value;
@@ -202,12 +204,12 @@
 			value = value | buf[i - 1];
 		}
 
-		WriteRegDW(adapter, 0x104, value);
+		write_reg_dw(adapter, 0x104, value);
 	}
 
-	i2cMainSetup(device, chip_addr, 0, addr, buf[0], len, &command);
+	i2c_main_setup(device, chip_addr, 0, addr, buf[0], len, &command);
 
-	return i2cMainWriteForFlex2(adapter, command, 0, 100000);
+	return i2c_main_write_for_flex2(adapter, command, 0, 100000);
 }
 
 static void fixchipaddr(u32 device, u32 bus, u32 addr, u32 *ret)
@@ -218,13 +220,13 @@
 	*ret = bus;
 }
 
-static u32 FLEXI2C_read(struct adapter * adapter, u32 device, u32 bus, u32 addr, u8 * buf, u32 len)
+static u32 flex_i2c_read(struct adapter *adapter, u32 device, u32 bus, u32 addr, u8 *buf, u32 len)
 {
 	u32 chipaddr;
 	u32 bytes_to_transfer;
 	u8 *start;
 
-//  dprintk("%s:\n", __FUNCTION__);
+	ddprintk("%s:\n", __FUNCTION__);
 
 	start = buf;
 
@@ -236,7 +238,7 @@
 
 		fixchipaddr(device, bus, addr, &chipaddr);
 
-		if (FlexI2cRead4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)
+		if (flex_i2c_read4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)
 			return buf - start;
 
 		buf = buf + bytes_to_transfer;
@@ -247,13 +249,13 @@
 	return buf - start;
 }
 
-static u32 FLEXI2C_write(struct adapter * adapter, u32 device, u32 bus, u32 addr, u8 * buf, u32 len)
+static u32 flex_i2c_write(struct adapter *adapter, u32 device, u32 bus, u32 addr, u8 *buf, u32 len)
 {
 	u32 chipaddr;
 	u32 bytes_to_transfer;
 	u8 *start;
 
-//  dprintk("%s:\n", __FUNCTION__);
+	ddprintk("%s:\n", __FUNCTION__);
 
 	start = buf;
 
@@ -265,7 +267,7 @@
 
 		fixchipaddr(device, bus, addr, &chipaddr);
 
-		if (FlexI2cWrite4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)
+		if (flex_i2c_write4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)
 			return buf - start;
 
 		buf = buf + bytes_to_transfer;
@@ -284,75 +286,81 @@
 	if (down_interruptible(&tmp->i2c_sem))
 		return -ERESTARTSYS;
 
-	if (0) {
-		dprintk("%s:\n", __FUNCTION__);
+	ddprintk("%s: %d messages to transfer\n", __FUNCTION__, num);
 
 		for (i = 0; i < num; i++) {
-			printk("message %d: flags=%x, addr=0x%04x, buf=%p, len=%d \n", i, msgs[i].flags, msgs[i].addr, msgs[i].buf, msgs[i].len);
-		}
-	}
+		ddprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i,
+			 msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);
 	
-	/* allow only the vp310 frontend to access the bus */
-	if ((msgs[0].addr != 0x0E) && (msgs[0].addr != 0x61)) {
+		/* allow only the mt312 and stv0299 frontends to access the bus */
+		if ((msgs[i].addr != 0x0e) && (msgs[i].addr != 0x68) && (msgs[i].addr != 0x61)) {
 		up(&tmp->i2c_sem);
 
 		return -EREMOTEIO;
 	}
+	}
 
-	if ((num == 1) && (msgs[0].buf != NULL)) {
-		if (msgs[0].flags == I2C_M_RD) {
-			ret = -EINVAL;
+	// read command
+	if ((num == 2) && (msgs[0].flags == 0) && (msgs[1].flags == I2C_M_RD) && (msgs[0].buf != NULL) && (msgs[1].buf != NULL)) {
 
-		} else {
+		ret = flex_i2c_read(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
 
-			// single writes do have the reg addr in buf[0] and data in buf[1] to buf[n]
-			ret = FLEXI2C_write(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], &msgs[0].buf[1], msgs[0].len - 1);
+		up(&tmp->i2c_sem);
 
-			if (ret != msgs[0].len - 1)
-				ret = -EREMOTEIO;
-			else
-				ret = num;
+		if (ret != msgs[1].len) {
+			printk("%s: read error !\n", __FUNCTION__);
+
+			for (i = 0; i < 2; i++) {
+				printk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i,
+				       msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);
 		}
 
-	} else if ((num == 2) && (msgs[1].buf != NULL)) {
+			return -EREMOTEIO;
+		}
 
-		// i2c reads consist of a reg addr _write_ followed by a data read, so msg[1].flags has to be examined
-		if (msgs[1].flags == I2C_M_RD) {
-			ret = FLEXI2C_read(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+		return num;
+	}
+	// write command
+	for (i = 0; i < num; i++) {
 
-		} else {
+		if ((msgs[i].flags != 0) || (msgs[i].buf == NULL) || (msgs[i].len < 2))
+			return -EINVAL;
+
+		ret = flex_i2c_write(tmp, 0x10000000, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);
+
+		up(&tmp->i2c_sem);
 
-			ret = FLEXI2C_write(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+		if (ret != msgs[0].len - 1) {
+			printk("%s: write error %i !\n", __FUNCTION__, ret);
+
+			printk("message %d: flags=0x%x, addr=0x%x, buf[0]=0x%x, len=%d \n", i,
+			       msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);
+
+			return -EREMOTEIO;
 		}
 
-		if (ret != msgs[1].len)
-			ret = -EREMOTEIO;
-		else
-			ret = num;
+		return num;
 	}
 
-	up(&tmp->i2c_sem);
+	printk("%s: unknown command format !\n", __FUNCTION__);
 
-	/* master xfer functions always return the number of successfully
-	   transmitted messages, not the number of transmitted bytes.
-	   return -EREMOTEIO in case of failure. */
-	return ret;
+	return -EINVAL;
 }
 
 /* SRAM (Skystar2 rev2.3 has one "ISSI IS61LV256" chip on board,
    but it seems that FlexCopII can work with more than one chip) */
-static void SRAMSetNetDest(struct adapter * adapter, u8 dest)
+static void sram_set_net_dest(struct adapter *adapter, u8 dest)
 {
 	u32 tmp;
 
 	udelay(1000);
 
-	tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFFC) | (dest & 3);
+	tmp = (read_reg_dw(adapter, 0x714) & 0xfffffffc) | (dest & 3);
 
 	udelay(1000);
 
-	WriteRegDW(adapter, 0x714, tmp);
-	WriteRegDW(adapter, 0x714, tmp);
+	write_reg_dw(adapter, 0x714, tmp);
+	write_reg_dw(adapter, 0x714, tmp);
 
 	udelay(1000);
 
@@ -360,19 +368,19 @@
 /*	return tmp; */
 }
 
-static void SRAMSetCaiDest(struct adapter * adapter, u8 dest)
+static void sram_set_cai_dest(struct adapter *adapter, u8 dest)
 {
 	u32 tmp;
 
 	udelay(1000);
 
-	tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFF3) | ((dest & 3) << 2);
+	tmp = (read_reg_dw(adapter, 0x714) & 0xfffffff3) | ((dest & 3) << 2);
 
 	udelay(1000);
 	udelay(1000);
 
-	WriteRegDW(adapter, 0x714, tmp);
-	WriteRegDW(adapter, 0x714, tmp);
+	write_reg_dw(adapter, 0x714, tmp);
+	write_reg_dw(adapter, 0x714, tmp);
 
 	udelay(1000);
 
@@ -380,19 +388,19 @@
 /*	return tmp; */
 }
 
-static void SRAMSetCaoDest(struct adapter * adapter, u8 dest)
+static void sram_set_cao_dest(struct adapter *adapter, u8 dest)
 {
 	u32 tmp;
 
 	udelay(1000);
 
-	tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFCF) | ((dest & 3) << 4);
+	tmp = (read_reg_dw(adapter, 0x714) & 0xffffffcf) | ((dest & 3) << 4);
 
 	udelay(1000);
 	udelay(1000);
 
-	WriteRegDW(adapter, 0x714, tmp);
-	WriteRegDW(adapter, 0x714, tmp);
+	write_reg_dw(adapter, 0x714, tmp);
+	write_reg_dw(adapter, 0x714, tmp);
 
 	udelay(1000);
 
@@ -400,19 +408,19 @@
 /*	return tmp; */
 }
 
-static void SRAMSetMediaDest(struct adapter * adapter, u8 dest)
+static void sram_set_media_dest(struct adapter *adapter, u8 dest)
 {
 	u32 tmp;
 
 	udelay(1000);
 
-	tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFF3F) | ((dest & 3) << 6);
+	tmp = (read_reg_dw(adapter, 0x714) & 0xffffff3f) | ((dest & 3) << 6);
 
 	udelay(1000);
 	udelay(1000);
 
-	WriteRegDW(adapter, 0x714, tmp);
-	WriteRegDW(adapter, 0x714, tmp);
+	write_reg_dw(adapter, 0x714, tmp);
+	write_reg_dw(adapter, 0x714, tmp);
 
 	udelay(1000);
 
@@ -429,16 +437,17 @@
     bits 28-29 : memory bank selector
     bit  31    : busy flag
 */
-static void FlexSramWrite(struct adapter *adapter, u32 bank, u32 addr, u8 * buf, u32 len)
+static void flex_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
 {
-	u32 i, command, retries;
+	int i, retries;
+	u32 command;
 
 	for (i = 0; i < len; i++) {
 		command = bank | addr | 0x04000000 | (*buf << 0x10);
 
 		retries = 2;
 
-		while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
 			mdelay(1);
 			retries--;
 		};
@@ -446,23 +455,24 @@
 		if (retries == 0)
 			printk("%s: SRAM timeout\n", __FUNCTION__);
 
-		WriteRegDW(adapter, 0x700, command);
+		write_reg_dw(adapter, 0x700, command);
 
 		buf++;
 		addr++;
 	}
 }
 
-static void FlexSramRead(struct adapter *adapter, u32 bank, u32 addr, u8 * buf, u32 len)
+static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
 {
-	u32 i, command, value, retries;
+	int i, retries;
+	u32 command, value;
 
 	for (i = 0; i < len; i++) {
 		command = bank | addr | 0x04008000;
 
 		retries = 10000;
 
-		while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
 			mdelay(1);
 			retries--;
 		};
@@ -470,11 +480,11 @@
 		if (retries == 0)
 			printk("%s: SRAM timeout\n", __FUNCTION__);
 
-		WriteRegDW(adapter, 0x700, command);
+		write_reg_dw(adapter, 0x700, command);
 
 		retries = 10000;
 
-		while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
 			mdelay(1);
 			retries--;
 		};
@@ -482,7 +492,7 @@
 		if (retries == 0)
 			printk("%s: SRAM timeout\n", __FUNCTION__);
 
-		value = ReadRegDW(adapter, 0x700) >> 0x10;
+		value = read_reg_dw(adapter, 0x700) >> 0x10;
 
 		*buf = (value & 0xff);
 
@@ -491,47 +501,47 @@
 	}
 }
 
-static void SRAM_writeChunk(struct adapter *adapter, u32 addr, u8 * buf, u16 len)
+static void sram_writeChunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
 {
 	u32 bank;
 
 	bank = 0;
 
-	if (adapter->dwSramType == 0x20000) {
-		bank = (addr & 0x18000) << 0x0D;
+	if (adapter->dw_sram_type == 0x20000) {
+		bank = (addr & 0x18000) << 0x0d;
 	}
 
-	if (adapter->dwSramType == 0x00000) {
-		if ((addr >> 0x0F) == 0)
+	if (adapter->dw_sram_type == 0x00000) {
+		if ((addr >> 0x0f) == 0)
 			bank = 0x20000000;
 		else
 			bank = 0x10000000;
 	}
 
-	FlexSramWrite(adapter, bank, addr & 0x7FFF, buf, len);
+	flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);
 }
 
-static void SRAM_readChunk(struct adapter *adapter, u32 addr, u8 * buf, u16 len)
+static void sram_readChunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
 {
 	u32 bank;
 
 	bank = 0;
 
-	if (adapter->dwSramType == 0x20000) {
-		bank = (addr & 0x18000) << 0x0D;
+	if (adapter->dw_sram_type == 0x20000) {
+		bank = (addr & 0x18000) << 0x0d;
 	}
 
-	if (adapter->dwSramType == 0x00000) {
-		if ((addr >> 0x0F) == 0)
+	if (adapter->dw_sram_type == 0x00000) {
+		if ((addr >> 0x0f) == 0)
 			bank = 0x20000000;
 		else
 			bank = 0x10000000;
 	}
 
-	FlexSramRead(adapter, bank, addr & 0x7FFF, buf, len);
+	flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);
 }
 
-static void SRAM_read(struct adapter *adapter, u32 addr, u8 * buf, u32 len)
+static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
 {
 	u32 length;
 
@@ -541,11 +551,11 @@
 		// check if the address range belongs to the same 
 		// 32K memory chip. If not, the data is read from 
 		// one chip at a time.
-		if ((addr >> 0x0F) != ((addr + len - 1) >> 0x0F)) {
-			length = (((addr >> 0x0F) + 1) << 0x0F) - addr;
+		if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
+			length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
 		}
 
-		SRAM_readChunk(adapter, addr, buf, length);
+		sram_readChunk(adapter, addr, buf, length);
 
 		addr = addr + length;
 		buf = buf + length;
@@ -553,7 +563,7 @@
 	}
 }
 
-static void SRAM_write(struct adapter *adapter, u32 addr, u8 * buf, u32 len)
+static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
 {
 	u32 length;
 
@@ -563,11 +573,11 @@
 		// check if the address range belongs to the same 
 		// 32K memory chip. If not, the data is written to
 		// one chip at a time.
-		if ((addr >> 0x0F) != ((addr + len - 1) >> 0x0F)) {
-			length = (((addr >> 0x0F) + 1) << 0x0F) - addr;
+		if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
+			length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
 		}
 
-		SRAM_writeChunk(adapter, addr, buf, length);
+		sram_writeChunk(adapter, addr, buf, length);
 
 		addr = addr + length;
 		buf = buf + length;
@@ -575,92 +585,92 @@
 	}
 }
 
-static void SRAM_setSize(struct adapter *adapter, u32 mask)
+static void sram_set_size(struct adapter *adapter, u32 mask)
 {
-	WriteRegDW(adapter, 0x71C, (mask | (~0x30000 & ReadRegDW(adapter, 0x71C))));
+	write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));
 }
 
-static void SRAM_init(struct adapter *adapter)
+static void sram_init(struct adapter *adapter)
 {
 	u32 tmp;
 
-	tmp = ReadRegDW(adapter, 0x71C);
+	tmp = read_reg_dw(adapter, 0x71c);
 
-	WriteRegDW(adapter, 0x71C, 1);
+	write_reg_dw(adapter, 0x71c, 1);
 
-	if (ReadRegDW(adapter, 0x71C) != 0) {
-		WriteRegDW(adapter, 0x71C, tmp);
+	if (read_reg_dw(adapter, 0x71c) != 0) {
+		write_reg_dw(adapter, 0x71c, tmp);
 
-		adapter->dwSramType = tmp & 0x30000;
+		adapter->dw_sram_type = tmp & 0x30000;
 
-		dprintk("%s: dwSramType = %x\n", __FUNCTION__, adapter->dwSramType);
+		ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
 
 	} else {
 
-		adapter->dwSramType = 0x10000;
+		adapter->dw_sram_type = 0x10000;
 
-		dprintk("%s: dwSramType = %x\n", __FUNCTION__, adapter->dwSramType);
+		ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
 	}
 
 	/* return value is never used? */
-/*	return adapter->dwSramType; */
+/*	return adapter->dw_sram_type; */
 }
 
-static int SRAM_testLocation(struct adapter *adapter, u32 mask, u32 addr)
+static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
 {
 	u8 tmp1, tmp2;
 
 	dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
 
-	SRAM_setSize(adapter, mask);
-	SRAM_init(adapter);
+	sram_set_size(adapter, mask);
+	sram_init(adapter);
 
-	tmp2 = 0xA5;
-	tmp1 = 0x4F;
+	tmp2 = 0xa5;
+	tmp1 = 0x4f;
 
-	SRAM_write(adapter, addr, &tmp2, 1);
-	SRAM_write(adapter, addr + 4, &tmp1, 1);
+	sram_write(adapter, addr, &tmp2, 1);
+	sram_write(adapter, addr + 4, &tmp1, 1);
 
 	tmp2 = 0;
 
 	mdelay(20);
 
-	SRAM_read(adapter, addr, &tmp2, 1);
-	SRAM_read(adapter, addr, &tmp2, 1);
+	sram_read(adapter, addr, &tmp2, 1);
+	sram_read(adapter, addr, &tmp2, 1);
 
-	dprintk("%s: wrote 0xA5, read 0x%2x\n", __FUNCTION__, tmp2);
+	dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
 
-	if (tmp2 != 0xA5)
+	if (tmp2 != 0xa5)
 		return 0;
 
-	tmp2 = 0x5A;
-	tmp1 = 0xF4;
+	tmp2 = 0x5a;
+	tmp1 = 0xf4;
 
-	SRAM_write(adapter, addr, &tmp2, 1);
-	SRAM_write(adapter, addr + 4, &tmp1, 1);
+	sram_write(adapter, addr, &tmp2, 1);
+	sram_write(adapter, addr + 4, &tmp1, 1);
 
 	tmp2 = 0;
 
 	mdelay(20);
 
-	SRAM_read(adapter, addr, &tmp2, 1);
-	SRAM_read(adapter, addr, &tmp2, 1);
+	sram_read(adapter, addr, &tmp2, 1);
+	sram_read(adapter, addr, &tmp2, 1);
 
-	dprintk("%s: wrote 0x5A, read 0x%2x\n", __FUNCTION__, tmp2);
+	dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
 
-	if (tmp2 != 0x5A)
+	if (tmp2 != 0x5a)
 		return 0;
 
 	return 1;
 }
 
-static u32 SRAM_length(struct adapter * adapter)
+static u32 sram_length(struct adapter *adapter)
 {
-	if (adapter->dwSramType == 0x10000)
+	if (adapter->dw_sram_type == 0x10000)
 		return 32768;	//  32K
-	if (adapter->dwSramType == 0x00000)
+	if (adapter->dw_sram_type == 0x00000)
 		return 65536;	//  64K        
-	if (adapter->dwSramType == 0x20000)
+	if (adapter->dw_sram_type == 0x20000)
 		return 131072;	// 128K
 
 	return 32768;		// 32K
@@ -674,103 +684,104 @@
    FlexCop works only with one bank at a time. The bank is selected
    by bits 28-29 of the 0x700 register.
   
-   bank 0 covers addresses 0x00000-0x07FFF
-   bank 1 covers addresses 0x08000-0x0FFFF
-   bank 2 covers addresses 0x10000-0x17FFF
-   bank 3 covers addresses 0x18000-0x1FFFF
+   bank 0 covers addresses 0x00000-0x07fff
+   bank 1 covers addresses 0x08000-0x0ffff
+   bank 2 covers addresses 0x10000-0x17fff
+   bank 3 covers addresses 0x18000-0x1ffff
 */
-static int SramDetectForFlex2(struct adapter *adapter)
+static int sram_detect_for_flex2(struct adapter *adapter)
 {
 	u32 tmp, tmp2, tmp3;
 
 	dprintk("%s:\n", __FUNCTION__);
 
-	tmp = ReadRegDW(adapter, 0x208);
-	WriteRegDW(adapter, 0x208, 0);
+	tmp = read_reg_dw(adapter, 0x208);
+	write_reg_dw(adapter, 0x208, 0);
 
-	tmp2 = ReadRegDW(adapter, 0x71C);
+	tmp2 = read_reg_dw(adapter, 0x71c);
 
 	dprintk("%s: tmp2 = %x\n", __FUNCTION__, tmp2);
 
-	WriteRegDW(adapter, 0x71C, 1);
+	write_reg_dw(adapter, 0x71c, 1);
 
-	tmp3 = ReadRegDW(adapter, 0x71C);
+	tmp3 = read_reg_dw(adapter, 0x71c);
 
 	dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
 
-	WriteRegDW(adapter, 0x71C, tmp2);
+	write_reg_dw(adapter, 0x71c, tmp2);
 
 	// check for internal SRAM ???
 	tmp3--;
 	if (tmp3 != 0) {
-		SRAM_setSize(adapter, 0x10000);
-		SRAM_init(adapter);
-		WriteRegDW(adapter, 0x208, tmp);
+		sram_set_size(adapter, 0x10000);
+		sram_init(adapter);
+		write_reg_dw(adapter, 0x208, tmp);
 
 		dprintk("%s: sram size = 32K\n", __FUNCTION__);
 
 		return 32;
 	}
 
-	if (SRAM_testLocation(adapter, 0x20000, 0x18000) != 0) {
-		SRAM_setSize(adapter, 0x20000);
-		SRAM_init(adapter);
-		WriteRegDW(adapter, 0x208, tmp);
+	if (sram_test_location(adapter, 0x20000, 0x18000) != 0) {
+		sram_set_size(adapter, 0x20000);
+		sram_init(adapter);
+		write_reg_dw(adapter, 0x208, tmp);
 
 		dprintk("%s: sram size = 128K\n", __FUNCTION__);
 
 		return 128;
 	}
 
-	if (SRAM_testLocation(adapter, 0x00000, 0x10000) != 0) {
-		SRAM_setSize(adapter, 0x00000);
-		SRAM_init(adapter);
-		WriteRegDW(adapter, 0x208, tmp);
+	if (sram_test_location(adapter, 0x00000, 0x10000) != 0) {
+		sram_set_size(adapter, 0x00000);
+		sram_init(adapter);
+		write_reg_dw(adapter, 0x208, tmp);
 
 		dprintk("%s: sram size = 64K\n", __FUNCTION__);
 
 		return 64;
 	}
 
-	if (SRAM_testLocation(adapter, 0x10000, 0x00000) != 0) {
-		SRAM_setSize(adapter, 0x10000);
-		SRAM_init(adapter);
-		WriteRegDW(adapter, 0x208, tmp);
+	if (sram_test_location(adapter, 0x10000, 0x00000) != 0) {
+		sram_set_size(adapter, 0x10000);
+		sram_init(adapter);
+		write_reg_dw(adapter, 0x208, tmp);
 
 		dprintk("%s: sram size = 32K\n", __FUNCTION__);
 
 		return 32;
 	}
 
-	SRAM_setSize(adapter, 0x10000);
-	SRAM_init(adapter);
-	WriteRegDW(adapter, 0x208, tmp);
+	sram_set_size(adapter, 0x10000);
+	sram_init(adapter);
+	write_reg_dw(adapter, 0x208, tmp);
 
 	dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
 
 	return 0;
 }
 
-static void SLL_detectSramSize(struct adapter *adapter)
+static void sll_detect_sram_size(struct adapter *adapter)
 {
-	SramDetectForFlex2(adapter);
+	sram_detect_for_flex2(adapter);
 }
+
 /* EEPROM (Skystar2 has one "24LC08B" chip on board) */
 /*
-static int EEPROM_write(struct adapter *adapter, u16 addr, u8 * buf, u16 len)
+static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
 {
-	return FLEXI2C_write(adapter, 0x20000000, 0x50, addr, buf, len);
+	return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len);
 }
 */
 
-static int EEPROM_read(struct adapter *adapter, u16 addr, u8 * buf, u16 len)
+static int eeprom_read(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
 {
-	return FLEXI2C_read(adapter, 0x20000000, 0x50, addr, buf, len);
+	return flex_i2c_read(adapter, 0x20000000, 0x50, addr, buf, len);
 }
 
-u8 calc_LRC(u8 * buf, u32 len)
+u8 calc_lrc(u8 *buf, int len)
 {
-	u32 i;
+	int i;
 	u8 sum;
 
 	sum = 0;
@@ -781,13 +792,13 @@
 	return sum;
 }
 
-static int EEPROM_LRC_read(struct adapter *adapter, u32 addr, u32 len, u8 * buf, u32 retries)
+static int eeprom_lrc_read(struct adapter *adapter, u32 addr, u32 len, u8 *buf, int retries)
 {
 	int i;
 
 	for (i = 0; i < retries; i++) {
-		if (EEPROM_read(adapter, addr, buf, len) == len) {
-			if (calc_LRC(buf, len - 1) == buf[len - 1])
+		if (eeprom_read(adapter, addr, buf, len) == len) {
+			if (calc_lrc(buf, len - 1) == buf[len - 1])
 				return 1;
 		}
 	}
@@ -796,13 +807,13 @@
 }
 
 /*
-static int EEPROM_LRC_write(struct adapter *adapter, u32 addr, u32 len, u8 * wbuf, u8 * rbuf, u32 retries)
+static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries)
 {
 	int i;
 
 	for (i = 0; i < retries; i++) {
-		if (EEPROM_write(adapter, addr, wbuf, len) == len) {
-			if (EEPROM_LRC_read(adapter, addr, len, rbuf, retries) == 1)
+		if (eeprom_write(adapter, addr, wbuf, len) == len) {
+			if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
 				return 1;
 		}
 	}
@@ -811,33 +822,11 @@
 }
 */
 
-/* These functions could be called from the initialization routine 
-   to unlock SkyStar2 cards, locked by "Europe On Line".
-        
-   in cards from "Europe On Line" the key is:
-
-       u8 key[20] = {
- 	    0xB2, 0x01, 0x00, 0x00,
- 	    0x00, 0x00, 0x00, 0x00,
- 	    0x00, 0x00, 0x00, 0x00,
- 	    0x00, 0x00, 0x00, 0x00,
-       };
-
-       LRC = 0xB3;
 
-  in unlocked cards the key is:
+/* These functions could be used to unlock SkyStar2 cards. */
 
-       u8 key[20] = {
- 	    0xB2, 0x00, 0x00, 0x00,
- 	    0x00, 0x00, 0x00, 0x00,
- 	    0x00, 0x00, 0x00, 0x00,
- 	    0x00, 0x00, 0x00, 0x00,
-       };
-
-      LRC = 0xB2;
-*/
 /*
-static int EEPROM_writeKey(struct adapter *adapter, u8 * key, u32 len)
+static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
 {
 	u8 rbuf[20];
 	u8 wbuf[20];
@@ -850,37 +839,38 @@
 	wbuf[16] = 0;
 	wbuf[17] = 0;
 	wbuf[18] = 0;
-	wbuf[19] = calc_LRC(wbuf, 19);
+	wbuf[19] = calc_lrc(wbuf, 19);
 
-	return EEPROM_LRC_write(adapter, 0x3E4, 20, wbuf, rbuf, 4);
+	return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4);
 }
-*/
-static int EEPROM_readKey(struct adapter *adapter, u8 * key, u32 len)
+
+static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len)
 {
 	u8 buf[20];
 
 	if (len != 16)
 		return 0;
 
-	if (EEPROM_LRC_read(adapter, 0x3E4, 20, buf, 4) == 0)
+	if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0)
 		return 0;
 
 	memcpy(key, buf, len);
 
 	return 1;
 }
+*/
 
-static int EEPROM_getMacAddr(struct adapter *adapter, char type, u8 * mac)
+static int eeprom_get_mac_addr(struct adapter *adapter, char type, u8 *mac)
 {
 	u8 tmp[8];
 
-	if (EEPROM_LRC_read(adapter, 0x3F8, 8, tmp, 4) != 0) {
+	if (eeprom_lrc_read(adapter, 0x3f8, 8, tmp, 4) != 0) {
 		if (type != 0) {
 			mac[0] = tmp[0];
 			mac[1] = tmp[1];
 			mac[2] = tmp[2];
-			mac[3] = 0xFE;
-			mac[4] = 0xFF;
+			mac[3] = 0xfe;
+			mac[4] = 0xff;
 			mac[5] = tmp[3];
 			mac[6] = tmp[4];
 			mac[7] = tmp[5];
@@ -912,7 +902,7 @@
 }
 
 /*
-static char EEPROM_setMacAddr(struct adapter *adapter, char type, u8 * mac)
+static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
 {
 	u8 tmp[8];
 
@@ -935,9 +925,9 @@
 	}
 
 	tmp[6] = 0;
-	tmp[7] = calc_LRC(tmp, 7);
+	tmp[7] = calc_lrc(tmp, 7);
 
-	if (EEPROM_write(adapter, 0x3F8, tmp, 8) == 8)
+	if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8)
 		return 1;
 
 	return 0;
@@ -945,529 +935,319 @@
 */
 
 /* PID filter */
-static void FilterEnableStream1Filter(struct adapter *adapter, u32 op)
-{
-	dprintk("%s: op=%x\n", __FUNCTION__, op);
-
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000001, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000001);
-	}
-}
-
-static void FilterEnableStream2Filter(struct adapter *adapter, u32 op)
-{
-	dprintk("%s: op=%x\n", __FUNCTION__, op);
-
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000002, 0);
 
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000002);
+/* every flexcop has 6 "lower" hw PID filters     */
+/* these are enabled by setting bits 0-5 of 0x208 */
+/* for the 32 additional filters we have to select one */
+/* of them through 0x310 and modify through 0x314 */
+/* op: 0=disable, 1=enable */
+static void filter_enable_hw_filter(struct adapter *adapter, int id, u8 op)
+{
+	dprintk("%s: id=%d op=%d\n", __FUNCTION__, id, op);
+	if (id <= 5) {
+		u32 mask = (0x00000001 << id);
+		write_reg_bitfield(adapter, 0x208, mask, op ? mask : 0);
+	} else {
+		/* select */
+		write_reg_bitfield(adapter, 0x310, 0x1f, (id - 6) & 0x1f);
+		/* modify */
+		write_reg_bitfield(adapter, 0x314, 0x00006000, op ? 0x00004000 : 0);
 	}
 }
 
-static void FilterEnablePcrFilter(struct adapter *adapter, u32 op)
-{
-	dprintk("%s: op=%x\n", __FUNCTION__, op);
-
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000004, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000004);
+/* this sets the PID that should pass the specified filter */
+static void pid_set_hw_pid(struct adapter *adapter, int id, u16 pid)
+{
+	dprintk("%s: id=%d  pid=%d\n", __FUNCTION__, id, pid);
+	if (id <= 5) {
+		u32 adr = 0x300 + ((id & 6) << 1);
+		int shift = (id & 1) ? 16 : 0;
+		dprintk("%s: id=%d  addr=%x %c  pid=%d\n", __FUNCTION__, id, adr, (id & 1) ? 'h' : 'l', pid);
+		write_reg_bitfield(adapter, adr, (0x7fff) << shift, (pid & 0x1fff) << shift);
+	} else {
+		/* select */
+		write_reg_bitfield(adapter, 0x310, 0x1f, (id - 6) & 0x1f);
+		/* modify */
+		write_reg_bitfield(adapter, 0x314, 0x1fff, pid & 0x1fff);
 	}
 }
 
-static void FilterEnablePmtFilter(struct adapter *adapter, u32 op)
-{
-	dprintk("%s: op=%x\n", __FUNCTION__, op);
-
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000008, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000008);
-	}
-}
-
-static void FilterEnableEmmFilter(struct adapter *adapter, u32 op)
-{
-	dprintk("%s: op=%x\n", __FUNCTION__, op);
-
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000010, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000010);
-	}
-}
-
-static void FilterEnableEcmFilter(struct adapter *adapter, u32 op)
-{
-	dprintk("%s: op=%x\n", __FUNCTION__, op);
-
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000020, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000020);
-	}
-}
 
 /*
-static void FilterEnableNullFilter(struct adapter *adapter, u32 op)
+static void filter_enable_null_filter(struct adapter *adapter, u32 op)
 {
 	dprintk("%s: op=%x\n", __FUNCTION__, op);
 
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000040, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000040);
-	}
+	write_reg_bitfield(adapter, 0x208, 0x00000040, op?0x00000040:0);
 }
 */
 
-static void FilterEnableMaskFilter(struct adapter *adapter, u32 op)
+static void filter_enable_mask_filter(struct adapter *adapter, u32 op)
 {
 	dprintk("%s: op=%x\n", __FUNCTION__, op);
 
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000080, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000080);
-	}
+	write_reg_bitfield(adapter, 0x208, 0x00000080, op ? 0x00000080 : 0);
 }
 
 
-static void CtrlEnableMAC(struct adapter *adapter, u32 op)
+static void ctrl_enable_mac(struct adapter *adapter, u32 op)
 {
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00004000, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00004000);
-	}
+	write_reg_bitfield(adapter, 0x208, 0x00004000, op ? 0x00004000 : 0);
 }
 
-static int CASetMacDstAddrFilter(struct adapter *adapter, u8 * mac)
+static int ca_set_mac_dst_addr_filter(struct adapter *adapter, u8 *mac)
 {
 	u32 tmp1, tmp2;
 
 	tmp1 = (mac[3] << 0x18) | (mac[2] << 0x10) | (mac[1] << 0x08) | mac[0];
 	tmp2 = (mac[5] << 0x08) | mac[4];
 
-	WriteRegDW(adapter, 0x418, tmp1);
-	WriteRegDW(adapter, 0x41C, tmp2);
+	write_reg_dw(adapter, 0x418, tmp1);
+	write_reg_dw(adapter, 0x41c, tmp2);
 
 	return 0;
 }
 
 /*
-static void SetIgnoreMACFilter(struct adapter *adapter, u8 op)
+static void set_ignore_mac_filter(struct adapter *adapter, u8 op)
 {
 	if (op != 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00004000, 0);
-
+		write_reg_bitfield(adapter, 0x208, 0x00004000, 0);
 		adapter->mac_filter = 1;
-
 	} else {
-
 		if (adapter->mac_filter != 0) {
 			adapter->mac_filter = 0;
-
-			WriteRegOp(adapter, 0x208, 1, 0, 0x00004000);
+			write_reg_bitfield(adapter, 0x208, 0x00004000, 0x00004000);
 		}
 	}
 }
 */
 
 /*
-static void CheckNullFilterEnable(struct adapter *adapter)
+static void check_null_filter_enable(struct adapter *adapter)
 {
-	FilterEnableNullFilter(adapter, 1);
-	FilterEnableMaskFilter(adapter, 1);
+	filter_enable_null_filter(adapter, 1);
+	filter_enable_mask_filter(adapter, 1);
 }
 */
 
-static void InitPIDsInfo(struct adapter *adapter)
-{
-	int i;
-
-	for (i = 0; i < 0x27; i++)
-		adapter->pids[i] = 0x1FFF;
-}
-
-static int CheckPID(struct adapter *adapter, u16 pid)
-{
-	u32 i;
-
-	if (pid == 0x1FFF)
-		return 0;
-
-	for (i = 0; i < 0x27; i++) {
-		if (adapter->pids[i] == pid)
-			return 1;
-	}
-
-	return 0;
-}
-
-static void PidSetGroupPID(struct adapter * adapter, u32 pid)
+static void pid_set_group_pid(struct adapter *adapter, u16 pid)
 {
 	u32 value;
 
 	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
-	value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x30C) & 0xFFFF0000);
-
-	WriteRegDW(adapter, 0x30C, value);
-
-	/* return value is never used? */
-/*	return value; */
+	value = (pid & 0x3fff) | (read_reg_dw(adapter, 0x30c) & 0xffff0000);
+	write_reg_dw(adapter, 0x30c, value);
 }
 
-static void PidSetGroupMASK(struct adapter * adapter, u32 pid)
+static void pid_set_group_mask(struct adapter *adapter, u16 pid)
 {
 	u32 value;
 
 	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
-	value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x30C) & 0xFFFF);
-
-	WriteRegDW(adapter, 0x30C, value);
-
-	/* return value is never used? */
-/*	return value; */
+	value = ((pid & 0x3fff) << 0x10) | (read_reg_dw(adapter, 0x30c) & 0xffff);
+	write_reg_dw(adapter, 0x30c, value);
 }
 
-static void PidSetStream1PID(struct adapter * adapter, u32 pid)
-{
-	u32 value;
-
-	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
-	value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x300) & 0xFFFFC000);
-
-	WriteRegDW(adapter, 0x300, value);
-
-	/* return value is never used? */
-/*	return value; */
-}
-
-static void PidSetStream2PID(struct adapter * adapter, u32 pid)
-{
-	u32 value;
-
-	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
-	value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x300) & 0xFFFF);
-
-	WriteRegDW(adapter, 0x300, value);
-
-	/* return value is never used? */
-/*	return value; */
-}
-
-static void PidSetPcrPID(struct adapter * adapter, u32 pid)
-{
-	u32 value;
-
-	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
-	value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x304) & 0xFFFFC000);
-
-	WriteRegDW(adapter, 0x304, value);
-
-	/* return value is never used? */
-/*	return value; */
-}
-
-static void PidSetPmtPID(struct adapter * adapter, u32 pid)
+/*
+static int pid_get_group_pid(struct adapter *adapter)
 {
-	u32 value;
-
-	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
-	value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x304) & 0x3FFF);
-
-	WriteRegDW(adapter, 0x304, value);
-
-	/* return value is never used? */
-/*	return value; */
+	return read_reg_dw(adapter, 0x30c) & 0x00001fff;
 }
 
-static void PidSetEmmPID(struct adapter * adapter, u32 pid)
+static int pid_get_group_mask(struct adapter *adapter)
 {
-	u32 value;
-
-	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
-	value = (pid & 0xFFFF) | (ReadRegDW(adapter, 0x308) & 0xFFFF0000);
-
-	WriteRegDW(adapter, 0x308, value);
-
-	/* return value is never used? */
-/*	return value; */
+	return (read_reg_dw(adapter, 0x30c) >> 0x10)& 0x00001fff;
 }
+*/
 
-static void PidSetEcmPID(struct adapter * adapter, u32 pid)
+/*
+static void reset_hardware_pid_filter(struct adapter *adapter)
 {
-	u32 value;
-
-	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+	pid_set_stream1_pid(adapter, 0x1fff);
 
-	value = (pid << 0x10) | (ReadRegDW(adapter, 0x308) & 0xFFFF);
+	pid_set_stream2_pid(adapter, 0x1fff);
+	filter_enable_stream2_filter(adapter, 0);
 
-	WriteRegDW(adapter, 0x308, value);
+	pid_set_pcr_pid(adapter, 0x1fff);
+	filter_enable_pcr_filter(adapter, 0);
 
-	/* return value is never used? */
-/*	return value; */
-}
+	pid_set_pmt_pid(adapter, 0x1fff);
+	filter_enable_pmt_filter(adapter, 0);
 
-static int PidGetStream1PID(struct adapter * adapter)
-{
-	return ReadRegDW(adapter, 0x300) & 0x00001FFF;
-}
+	pid_set_ecm_pid(adapter, 0x1fff);
+	filter_enable_ecm_filter(adapter, 0);
 
-static int PidGetStream2PID(struct adapter * adapter)
-{
-	return (ReadRegDW(adapter, 0x300) >> 0x10)& 0x00001FFF;
+	pid_set_emm_pid(adapter, 0x1fff);
+	filter_enable_emm_filter(adapter, 0);
 }
+*/
 
-static int PidGetPcrPID(struct adapter * adapter)
+static void init_pids(struct adapter *adapter)
 {
-	return ReadRegDW(adapter, 0x304) & 0x00001FFF;
-}
+	int i;
 
-static int PidGetPmtPID(struct adapter * adapter)
-{
-	return (ReadRegDW(adapter, 0x304) >> 0x10)& 0x00001FFF;
+	adapter->pid_count = 0;
+	adapter->whole_bandwidth_count = 0;
+	for (i = 0; i < adapter->useable_hw_filters; i++) {
+		dprintk("%s: setting filter %d to 0x1fff\n", __FUNCTION__, i);
+		adapter->hw_pids[i] = 0x1fff;
+		pid_set_hw_pid(adapter, i, 0x1fff);
 }
 
-static int PidGetEmmPID(struct adapter * adapter)
-{
-	return ReadRegDW(adapter, 0x308) & 0x00001FFF;
+	pid_set_group_pid(adapter, 0);
+	pid_set_group_mask(adapter, 0x1fe0);
 }
 
-static int PidGetEcmPID(struct adapter * adapter)
+static void open_whole_bandwidth(struct adapter *adapter)
 {
-	return (ReadRegDW(adapter, 0x308) >> 0x10)& 0x00001FFF;
+	dprintk("%s:\n", __FUNCTION__);
+	pid_set_group_pid(adapter, 0);
+	pid_set_group_mask(adapter, 0);
+/*
+	filter_enable_mask_filter(adapter, 1);
+*/
 }
 
-static int PidGetGroupPID(struct adapter * adapter)
+static void close_whole_bandwidth(struct adapter *adapter)
 {
-	return ReadRegDW(adapter, 0x30C) & 0x00001FFF;
+	dprintk("%s:\n", __FUNCTION__);
+	pid_set_group_pid(adapter, 0);
+	pid_set_group_mask(adapter, 0x1fe0);
+/*
+	filter_enable_mask_filter(adapter, 1);
+*/
 }
 
-static int PidGetGroupMASK(struct adapter * adapter)
+static void whole_bandwidth_inc(struct adapter *adapter)
 {
-	return (ReadRegDW(adapter, 0x30C) >> 0x10)& 0x00001FFF;
+	if (adapter->whole_bandwidth_count++ == 0)
+		open_whole_bandwidth(adapter);
 }
 
-/*
-static void ResetHardwarePIDFilter(struct adapter *adapter)
+static void whole_bandwidth_dec(struct adapter *adapter)
 {
-	PidSetStream1PID(adapter, 0x1FFF);
-
-	PidSetStream2PID(adapter, 0x1FFF);
-	FilterEnableStream2Filter(adapter, 0);
-
-	PidSetPcrPID(adapter, 0x1FFF);
-	FilterEnablePcrFilter(adapter, 0);
-
-	PidSetPmtPID(adapter, 0x1FFF);
-	FilterEnablePmtFilter(adapter, 0);
-
-	PidSetEcmPID(adapter, 0x1FFF);
-	FilterEnableEcmFilter(adapter, 0);
-
-	PidSetEmmPID(adapter, 0x1FFF);
-	FilterEnableEmmFilter(adapter, 0);
+	if (--adapter->whole_bandwidth_count <= 0)
+		close_whole_bandwidth(adapter);
 }
-*/
 
-static void OpenWholeBandwidth(struct adapter *adapter)
+/* The specified PID has to be let through the
+   hw filters.
+   We try to allocate an hardware filter and open whole
+   bandwidth when allocation is impossible.
+   All pids<=0x1f pass through the group filter.
+   Returns 1 on success, -1 on error */
+static int add_hw_pid(struct adapter *adapter, u16 pid)
 {
-	PidSetGroupPID(adapter, 0);
-
-	PidSetGroupMASK(adapter, 0);
-
-	FilterEnableMaskFilter(adapter, 1);
-}
+	int i;
 
-static int AddHwPID(struct adapter *adapter, u32 pid)
-{
 	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
 
-	if (pid <= 0x1F)
-		return 1;
-
-	if ((PidGetGroupMASK(adapter) == 0) && (PidGetGroupPID(adapter) == 0))
-		return 0;
-
-	if (PidGetStream1PID(adapter) == 0x1FFF) {
-		PidSetStream1PID(adapter, pid & 0xFFFF);
-
-		FilterEnableStream1Filter(adapter, 1);
-
+	if (pid <= 0x1f)
 		return 1;
-	}
-
-	if (PidGetStream2PID(adapter) == 0x1FFF) {
-		PidSetStream2PID(adapter, (pid & 0xFFFF));
-
-		FilterEnableStream2Filter(adapter, 1);
 
+	/* we can't use a filter for 0x2000, so no search */
+	if (pid != 0x2000) {
+		/* find an unused hardware filter */
+		for (i = 0; i < adapter->useable_hw_filters; i++) {
+			dprintk("%s: pid=%d searching slot=%d\n", __FUNCTION__, pid, i);
+			if (adapter->hw_pids[i] == 0x1fff) {
+				dprintk("%s: pid=%d slot=%d\n", __FUNCTION__, pid, i);
+				adapter->hw_pids[i] = pid;
+				pid_set_hw_pid(adapter, i, pid);
+				filter_enable_hw_filter(adapter, i, 1);
 		return 1;
 	}
-
-	if (PidGetPcrPID(adapter) == 0x1FFF) {
-		PidSetPcrPID(adapter, (pid & 0xFFFF));
-
-		FilterEnablePcrFilter(adapter, 1);
-
-		return 1;
 	}
-
-	if ((PidGetPmtPID(adapter) & 0x1FFF) == 0x1FFF) {
-		PidSetPmtPID(adapter, (pid & 0xFFFF));
-
-		FilterEnablePmtFilter(adapter, 1);
-
-		return 1;
 	}
-
-	if ((PidGetEmmPID(adapter) & 0x1FFF) == 0x1FFF) {
-		PidSetEmmPID(adapter, (pid & 0xFFFF));
-
-		FilterEnableEmmFilter(adapter, 1);
-
+	/* if we have not used a filter, this pid depends on whole bandwidth */
+	dprintk("%s: pid=%d whole_bandwidth\n", __FUNCTION__, pid);
+	whole_bandwidth_inc(adapter);
 		return 1;
 	}
 
-	if ((PidGetEcmPID(adapter) & 0x1FFF) == 0x1FFF) {
-		PidSetEcmPID(adapter, (pid & 0xFFFF));
-
-		FilterEnableEcmFilter(adapter, 1);
-
-		return 1;
-	}
-
-	return -1;
-}
-
-static int RemoveHwPID(struct adapter *adapter, u32 pid)
+/* returns -1 if the pid was not present in the filters */
+static int remove_hw_pid(struct adapter *adapter, u16 pid)
 {
-	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
-	if (pid <= 0x1F)
-		return 1;
-
-	if (PidGetStream1PID(adapter) == pid) {
-		PidSetStream1PID(adapter, 0x1FFF);
-
-		return 1;
-	}
-
-	if (PidGetStream2PID(adapter) == pid) {
-		PidSetStream2PID(adapter, 0x1FFF);
+	int i;
 
-		FilterEnableStream2Filter(adapter, 0);
+	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
 
+	if (pid <= 0x1f)
 		return 1;
-	}
-
-	if (PidGetPcrPID(adapter) == pid) {
-		PidSetPcrPID(adapter, 0x1FFF);
-
-		FilterEnablePcrFilter(adapter, 0);
 
+	/* we can't use a filter for 0x2000, so no search */
+	if (pid != 0x2000) {
+		for (i = 0; i < adapter->useable_hw_filters; i++) {
+			dprintk("%s: pid=%d searching slot=%d\n", __FUNCTION__, pid, i);
+			if (adapter->hw_pids[i] == pid) {	// find the pid slot
+				dprintk("%s: pid=%d slot=%d\n", __FUNCTION__, pid, i);
+				adapter->hw_pids[i] = 0x1fff;
+				pid_set_hw_pid(adapter, i, 0x1fff);
+				filter_enable_hw_filter(adapter, i, 0);
 		return 1;
 	}
-
-	if (PidGetPmtPID(adapter) == pid) {
-		PidSetPmtPID(adapter, 0x1FFF);
-
-		FilterEnablePmtFilter(adapter, 0);
-
-		return 1;
 	}
-
-	if (PidGetEmmPID(adapter) == pid) {
-		PidSetEmmPID(adapter, 0x1FFF);
-
-		FilterEnableEmmFilter(adapter, 0);
-
-		return 1;
 	}
-
-	if (PidGetEcmPID(adapter) == pid) {
-		PidSetEcmPID(adapter, 0x1FFF);
-
-		FilterEnableEcmFilter(adapter, 0);
-
+	/* if we have not used a filter, this pid depended on whole bandwith */
+	dprintk("%s: pid=%d whole_bandwidth\n", __FUNCTION__, pid);
+	whole_bandwidth_dec(adapter);
 		return 1;
 	}
 
-	return -1;
-}
-
-static int AddPID(struct adapter *adapter, u32 pid)
+/* Adds a PID to the filters.
+   Adding a pid more than once is possible, we keep reference counts.
+   Whole stream available through pid==0x2000.
+   Returns 1 on success, -1 on error */
+static int add_pid(struct adapter *adapter, u16 pid)
 {
 	int i;
 
 	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
 
-	if (pid > 0x1FFE)
+	if (pid > 0x1ffe && pid != 0x2000)
 		return -1;
 
-	if (CheckPID(adapter, pid) == 1)
+	// check if the pid is already present
+	for (i = 0; i < adapter->pid_count; i++)
+		if (adapter->pid_list[i] == pid) {
+			adapter->pid_rc[i]++;	// increment ref counter
 		return 1;
+		}
 
-	for (i = 0; i < 0x27; i++) {
-		if (adapter->pids[i] == 0x1FFF)	// find free pid filter
-		{
-			adapter->pids[i] = pid;
-
-			if (AddHwPID(adapter, pid) < 0)
-				OpenWholeBandwidth(adapter);
+	if (adapter->pid_count == N_PID_SLOTS)
+		return -1;	// no more pids can be added
+	adapter->pid_list[adapter->pid_count] = pid;	// register pid
+	adapter->pid_rc[adapter->pid_count] = 1;
+	adapter->pid_count++;
+	// hardware setting
+	add_hw_pid(adapter, pid);
 
 			return 1;
 		}
-	}
-
-	return -1;
-}
 
-static int RemovePID(struct adapter *adapter, u32 pid)
+/* Removes a PID from the filters. */
+static int remove_pid(struct adapter *adapter, u16 pid)
 {
-	u32 i;
+	int i, j;
 
 	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
 
-	if (pid > 0x1FFE)
+	if (pid > 0x1ffe && pid != 0x2000)
 		return -1;
 
-	for (i = 0; i < 0x27; i++) {
-		if (adapter->pids[i] == pid) {
-			adapter->pids[i] = 0x1FFF;
-
-			RemoveHwPID(adapter, pid);
-
+	// check if the pid is present (it must be!)
+	for (i = 0; i < adapter->pid_count; i++) {
+		if (adapter->pid_list[i] == pid) {
+			adapter->pid_rc[i]--;
+			if (adapter->pid_rc[i] <= 0) {
+				// remove from the list
+				adapter->pid_count--;
+				adapter->pid_list[i]=adapter->pid_list[adapter->pid_count];
+				adapter->pid_rc[i] = adapter->pid_rc[adapter->pid_count];
+				// hardware setting
+				remove_hw_pid(adapter, pid);
+			}
 			return 1;
 		}
 	}
@@ -1475,21 +1254,16 @@
 	return -1;
 }
 
+
 /* dma & irq */
-static void CtrlEnableSmc(struct adapter *adapter, u32 op)
+static void ctrl_enable_smc(struct adapter *adapter, u32 op)
 {
-	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00000800, 0);
-
-	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00000800);
-	}
+	write_reg_bitfield(adapter, 0x208, 0x00000800, op ? 0x00000800 : 0);
 }
 
-static void DmaEnableDisableIrq(struct adapter *adapter, u32 flag1, u32 flag2, u32 flag3)
+static void dma_enable_disable_irq(struct adapter *adapter, u32 flag1, u32 flag2, u32 flag3)
 {
-	adapter->dma_ctrl = adapter->dma_ctrl & 0x000F0000;
+	adapter->dma_ctrl = adapter->dma_ctrl & 0x000f0000;
 
 	if (flag1 == 0) {
 		if (flag2 == 0)
@@ -1516,16 +1290,16 @@
 	}
 }
 
-static void IrqDmaEnableDisableIrq(struct adapter * adapter, u32 op)
+static void irq_dma_enable_disable_irq(struct adapter *adapter, u32 op)
 {
 	u32 value;
 
-	value = ReadRegDW(adapter, 0x208) & 0xFFF0FFFF;
+	value = read_reg_dw(adapter, 0x208) & 0xfff0ffff;
 
 	if (op != 0)
-		value = value | (adapter->dma_ctrl & 0x000F0000);
+		value = value | (adapter->dma_ctrl & 0x000f0000);
 
-	WriteRegDW(adapter, 0x208, value);
+	write_reg_dw(adapter, 0x208, value);
 }
 
 /* FlexCopII has 2 dma channels. DMA1 is used to transfer TS data to
@@ -1544,7 +1318,7 @@
        subbuffer. The last 2 bits contain 0, when dma1 is disabled and 1,
        when dma1 is enabled.
 
-       the first 30 bits of register 0x00C contain the address of the second
+       the first 30 bits of register 0x00c contain the address of the second
        subbuffer. the last 2 bits contain 1.
 
        register 0x008 will contain the address of the subbuffer that was filled
@@ -1559,13 +1333,13 @@
        subbuffer.  The last 2 bits contain 0, when dma1 is disabled and 1,
        when dma1 is enabled.
 
-       the first 30 bits of register 0x01C contain the address of the second
+       the first 30 bits of register 0x01c contain the address of the second
        subbuffer. the last 2 bits contain 1.
 
        register 0x018 contains the address of the subbuffer that was filled
        with TS data, when FlexCopII generates an interrupt.
 */
-static int DmaInitDMA(struct adapter *adapter, u32 dma_channel)
+static int dma_init_dma(struct adapter *adapter, u32 dma_channel)
 {
 	u32 subbuffers, subbufsize, subbuf0, subbuf1;
 
@@ -1576,37 +1350,37 @@
 
 		subbufsize = (((adapter->dmaq1.buffer_size / 2) / 4) << 8) | subbuffers;
 
-		subbuf0 = adapter->dmaq1.bus_addr & 0xFFFFFFFC;
+		subbuf0 = adapter->dmaq1.bus_addr & 0xfffffffc;
 
-		subbuf1 = ((adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) & 0xFFFFFFFC) | 1;
+		subbuf1 = ((adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) & 0xfffffffc) | 1;
 
 		dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0);
 		udelay(1000);
-		WriteRegDW(adapter, 0x000, subbuf0);
+		write_reg_dw(adapter, 0x000, subbuf0);
 
 		dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4);
 		udelay(1000);
-		WriteRegDW(adapter, 0x004, subbufsize);
+		write_reg_dw(adapter, 0x004, subbufsize);
 
 		dprintk("%s: second subbuffer address = 0x%x\n", __FUNCTION__, subbuf1);
 		udelay(1000);
-		WriteRegDW(adapter, 0x00C, subbuf1);
+		write_reg_dw(adapter, 0x00c, subbuf1);
 
-		dprintk("%s: counter = 0x%x\n", __FUNCTION__, adapter->dmaq1.bus_addr & 0xFFFFFFFC);
-		WriteRegDW(adapter, 0x008, adapter->dmaq1.bus_addr & 0xFFFFFFFC);
+		dprintk("%s: counter = 0x%x\n", __FUNCTION__, adapter->dmaq1.bus_addr & 0xfffffffc);
+		write_reg_dw(adapter, 0x008, adapter->dmaq1.bus_addr & 0xfffffffc);
 		udelay(1000);
 
 		if (subbuffers == 0)
-			DmaEnableDisableIrq(adapter, 0, 1, 0);
+			dma_enable_disable_irq(adapter, 0, 1, 0);
 		else
-			DmaEnableDisableIrq(adapter, 0, 1, 1);
+			dma_enable_disable_irq(adapter, 0, 1, 1);
 
-		IrqDmaEnableDisableIrq(adapter, 1);
+		irq_dma_enable_disable_irq(adapter, 1);
 
-		SRAMSetMediaDest(adapter, 1);
-		SRAMSetNetDest(adapter, 1);
-		SRAMSetCaiDest(adapter, 2);
-		SRAMSetCaoDest(adapter, 2);
+		sram_set_media_dest(adapter, 1);
+		sram_set_net_dest(adapter, 1);
+		sram_set_cai_dest(adapter, 2);
+		sram_set_cao_dest(adapter, 2);
 	}
 
 	if (dma_channel == 1) {
@@ -1616,39 +1390,35 @@
 
 		subbufsize = (((adapter->dmaq2.buffer_size / 2) / 4) << 8) | subbuffers;
 
-		subbuf0 = adapter->dmaq2.bus_addr & 0xFFFFFFFC;
+		subbuf0 = adapter->dmaq2.bus_addr & 0xfffffffc;
 
-		subbuf1 = ((adapter->dmaq2.bus_addr + adapter->dmaq2.buffer_size / 2) & 0xFFFFFFFC) | 1;
+		subbuf1 = ((adapter->dmaq2.bus_addr + adapter->dmaq2.buffer_size / 2) & 0xfffffffc) | 1;
 
 		dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0);
 		udelay(1000);
-		WriteRegDW(adapter, 0x010, subbuf0);
+		write_reg_dw(adapter, 0x010, subbuf0);
 
 		dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4);
 		udelay(1000);
-		WriteRegDW(adapter, 0x014, subbufsize);
+		write_reg_dw(adapter, 0x014, subbufsize);
 
 		dprintk("%s: second buffer address = 0x%x\n", __FUNCTION__, subbuf1);
 		udelay(1000);
-		WriteRegDW(adapter, 0x01C, subbuf1);
+		write_reg_dw(adapter, 0x01c, subbuf1);
 
-		SRAMSetCaiDest(adapter, 2);
+		sram_set_cai_dest(adapter, 2);
 	}
 
 	return 0;
 }
 
-static void CtrlEnableReceiveData(struct adapter *adapter, u32 op)
+static void ctrl_enable_receive_data(struct adapter *adapter, u32 op)
 {
 	if (op == 0) {
-		WriteRegOp(adapter, 0x208, 2, ~0x00008000, 0);
-
+		write_reg_bitfield(adapter, 0x208, 0x00008000, 0);
 		adapter->dma_status = adapter->dma_status & ~0x00000004;
-
 	} else {
-
-		WriteRegOp(adapter, 0x208, 1, 0, 0x00008000);
-
+		write_reg_bitfield(adapter, 0x208, 0x00008000, 0x00008000);
 		adapter->dma_status = adapter->dma_status | 0x00000004;
 	}
 }
@@ -1656,7 +1426,7 @@
 /* bit 0 of dma_mask is set to 1 if dma1 channel has to be enabled/disabled
    bit 1 of dma_mask is set to 1 if dma2 channel has to be enabled/disabled
 */
-static void DmaStartStop0x2102(struct adapter *adapter, u32 dma_mask, u32 start_stop)
+static void dma_start_stop(struct adapter *adapter, u32 dma_mask, int start_stop)
 {
 	u32 dma_enable, dma1_enable, dma2_enable;
 
@@ -1679,83 +1449,82 @@
 		}
 		// enable dma1 and dma2
 		if ((dma1_enable == 1) && (dma2_enable == 1)) {
-			WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr | 1);
-			WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
-			WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr | 1);
+			write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr | 1);
+			write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
+			write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr | 1);
 
-			CtrlEnableReceiveData(adapter, 1);
+			ctrl_enable_receive_data(adapter, 1);
 
 			return;
 		}
 		// enable dma1
 		if ((dma1_enable == 1) && (dma2_enable == 0)) {
-			WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr | 1);
-			WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
+			write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr | 1);
+			write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
 
-			CtrlEnableReceiveData(adapter, 1);
+			ctrl_enable_receive_data(adapter, 1);
 
 			return;
 		}
 		// enable dma2
 		if ((dma1_enable == 0) && (dma2_enable == 1)) {
-			WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr | 1);
+			write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr | 1);
 
-			CtrlEnableReceiveData(adapter, 1);
+			ctrl_enable_receive_data(adapter, 1);
 
 			return;
 		}
 		// start dma
 		if ((dma1_enable == 0) && (dma2_enable == 0)) {
-			CtrlEnableReceiveData(adapter, 1);
+			ctrl_enable_receive_data(adapter, 1);
 
 			return;
 		}
 
 	} else {
 
-		dprintk("%s: stoping dma\n", __FUNCTION__);
+		dprintk("%s: stopping dma\n", __FUNCTION__);
 
 		dma_enable = adapter->dma_status & 0x00000003;
 
 		if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0)) {
-			dma_enable = dma_enable & 0xFFFFFFFE;
+			dma_enable = dma_enable & 0xfffffffe;
 		}
 
 		if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0)) {
-			dma_enable = dma_enable & 0xFFFFFFFD;
+			dma_enable = dma_enable & 0xfffffffd;
 		}
 		//stop dma
 		if ((dma_enable == 0) && ((adapter->dma_status & 4) != 0)) {
-			CtrlEnableReceiveData(adapter, 0);
+			ctrl_enable_receive_data(adapter, 0);
 
 			udelay(3000);
 		}
 		//disable dma1
 		if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0) && (adapter->dmaq1.bus_addr != 0)) {
-			WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr);
-			WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
+			write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr);
+			write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
 
 			adapter->dma_status = adapter->dma_status & ~0x00000001;
 		}
 		//disable dma2
 		if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0) && (adapter->dmaq2.bus_addr != 0)) {
-			WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr);
+			write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr);
 
 			adapter->dma_status = adapter->dma_status & ~0x00000002;
 		}
 	}
 }
 
-static void OpenStream(struct adapter *adapter, u32 pid)
+static void open_stream(struct adapter *adapter, u16 pid)
 {
 	u32 dma_mask;
 
-	if (adapter->capturing == 0)
-		adapter->capturing = 1;
+	++adapter->capturing;
 
-	FilterEnableMaskFilter(adapter, 1);
+	filter_enable_mask_filter(adapter, 1);
 
-	AddPID(adapter, pid);
+	add_pid(adapter, pid);
 
 	dprintk("%s: adapter->dma_status=%x\n", __FUNCTION__, adapter->dma_status);
 
@@ -1779,23 +1548,22 @@
 		}
 
 		if (dma_mask != 0) {
-			IrqDmaEnableDisableIrq(adapter, 1);
+			irq_dma_enable_disable_irq(adapter, 1);
 
-			DmaStartStop0x2102(adapter, dma_mask, 1);
+			dma_start_stop(adapter, dma_mask, 1);
 		}
 	}
 }
 
-static void CloseStream(struct adapter *adapter, u32 pid)
+static void close_stream(struct adapter *adapter, u16 pid)
 {
-	u32 dma_mask;
-
-	if (adapter->capturing != 0)
-		adapter->capturing = 0;
+	if (adapter->capturing > 0)
+		--adapter->capturing;
 
 	dprintk("%s: dma_status=%x\n", __FUNCTION__, adapter->dma_status);
 
-	dma_mask = 0;
+	if (adapter->capturing == 0) {
+		u32 dma_mask = 0;
 
 	if ((adapter->dma_status & 1) != 0)
 		dma_mask = dma_mask | 0x00000001;
@@ -1803,94 +1571,76 @@
 		dma_mask = dma_mask | 0x00000002;
 
 	if (dma_mask != 0) {
-		DmaStartStop0x2102(adapter, dma_mask, 0);
+			dma_start_stop(adapter, dma_mask, 0);
 	}
-
-	RemovePID(adapter, pid);
+	}
+	remove_pid(adapter, pid);
 }
 
-static void InterruptServiceDMA1(struct adapter *adapter)
+static void interrupt_service_dma1(struct adapter *adapter)
 {
 	struct dvb_demux *dvbdmx = &adapter->demux;
-	struct packet_header packet_header;
 
-	int nCurDmaCounter;
-	u32 nNumBytesParsed;
-	u32 nNumNewBytesTransferred;
-	u32 dwDefaultPacketSize = 188;
-	u8 gbTmpBuffer[188];
-	u8 *pbDMABufCurPos;
+	int n_cur_dma_counter;
+	u32 n_num_bytes_parsed;
+	u32 n_num_new_bytes_transferred;
+	u32 dw_default_packet_size = 188;
+	u8 gb_tmp_buffer[188];
+	u8 *pb_dma_buf_cur_pos;
 
-	nCurDmaCounter = readl(adapter->io_mem + 0x008) - adapter->dmaq1.bus_addr;
-	nCurDmaCounter = (nCurDmaCounter / dwDefaultPacketSize) * dwDefaultPacketSize;
+	n_cur_dma_counter = readl(adapter->io_mem + 0x008) - adapter->dmaq1.bus_addr;
+	n_cur_dma_counter = (n_cur_dma_counter / dw_default_packet_size) * dw_default_packet_size;
 
-	if ((nCurDmaCounter < 0) || (nCurDmaCounter > adapter->dmaq1.buffer_size)) {
+	if ((n_cur_dma_counter < 0) || (n_cur_dma_counter > adapter->dmaq1.buffer_size)) {
 		dprintk("%s: dma counter outside dma buffer\n", __FUNCTION__);
 		return;
 	}
 
-	adapter->dmaq1.head = nCurDmaCounter;
+	adapter->dmaq1.head = n_cur_dma_counter;
 
-	if (adapter->dmaq1.tail <= nCurDmaCounter) {
-		nNumNewBytesTransferred = nCurDmaCounter - adapter->dmaq1.tail;
+	if (adapter->dmaq1.tail <= n_cur_dma_counter) {
+		n_num_new_bytes_transferred = n_cur_dma_counter - adapter->dmaq1.tail;
 
 	} else {
 
-		nNumNewBytesTransferred = (adapter->dmaq1.buffer_size - adapter->dmaq1.tail) + nCurDmaCounter;
+		n_num_new_bytes_transferred = (adapter->dmaq1.buffer_size - adapter->dmaq1.tail) + n_cur_dma_counter;
 	}
 
-//  dprintk("%s: nCurDmaCounter   = %d\n" , __FUNCTION__, nCurDmaCounter);
-//	dprintk("%s: dmaq1.tail       = %d\n" , __FUNCTION__, adapter->dmaq1.tail):
-//  dprintk("%s: BytesTransferred = %d\n" , __FUNCTION__, nNumNewBytesTransferred);
+	ddprintk("%s: n_cur_dma_counter = %d\n", __FUNCTION__, n_cur_dma_counter);
+	ddprintk("%s: dmaq1.tail        = %d\n", __FUNCTION__, adapter->dmaq1.tail);
+	ddprintk("%s: bytes_transferred = %d\n", __FUNCTION__, n_num_new_bytes_transferred);
 
-	if (nNumNewBytesTransferred < dwDefaultPacketSize)
+	if (n_num_new_bytes_transferred < dw_default_packet_size)
 		return;
 
-	nNumBytesParsed = 0;
+	n_num_bytes_parsed = 0;
 
-	while (nNumBytesParsed < nNumNewBytesTransferred) {
-		pbDMABufCurPos = adapter->dmaq1.buffer + adapter->dmaq1.tail;
+	while (n_num_bytes_parsed < n_num_new_bytes_transferred) {
+		pb_dma_buf_cur_pos = adapter->dmaq1.buffer + adapter->dmaq1.tail;
 
 		if (adapter->dmaq1.buffer + adapter->dmaq1.buffer_size < adapter->dmaq1.buffer + adapter->dmaq1.tail + 188) {
-			memcpy(gbTmpBuffer, adapter->dmaq1.buffer + adapter->dmaq1.tail, adapter->dmaq1.buffer_size - adapter->dmaq1.tail);
-			memcpy(gbTmpBuffer + (adapter->dmaq1.buffer_size - adapter->dmaq1.tail), adapter->dmaq1.buffer, (188 - (adapter->dmaq1.buffer_size - adapter->dmaq1.tail)));
+			memcpy(gb_tmp_buffer, adapter->dmaq1.buffer + adapter->dmaq1.tail,
+			       adapter->dmaq1.buffer_size - adapter->dmaq1.tail);
+			memcpy(gb_tmp_buffer + (adapter->dmaq1.buffer_size - adapter->dmaq1.tail), adapter->dmaq1.buffer,
+			       (188 - (adapter->dmaq1.buffer_size - adapter->dmaq1.tail)));
 
-			pbDMABufCurPos = gbTmpBuffer;
+			pb_dma_buf_cur_pos = gb_tmp_buffer;
 		}
 
 		if (adapter->capturing != 0) {
-			u32 *dq = (u32 *) pbDMABufCurPos;
-
-			packet_header.sync_byte = *dq & 0x000000FF;
-			packet_header.transport_error_indicator = *dq & 0x00008000;
-			packet_header.payload_unit_start_indicator = *dq & 0x00004000;
-			packet_header.transport_priority = *dq & 0x00002000;
-			packet_header.pid = ((*dq & 0x00FF0000) >> 0x10) | (*dq & 0x00001F00);
-			packet_header.transport_scrambling_control = *dq >> 0x1E;
-			packet_header.adaptation_field_control = (*dq & 0x30000000) >> 0x1C;
-			packet_header.continuity_counter = (*dq & 0x0F000000) >> 0x18;
-
-			if ((packet_header.sync_byte == 0x47) && (packet_header.transport_error_indicator == 0) && (packet_header.pid != 0x1FFF)) {
-				if (CheckPID(adapter, packet_header.pid & 0x0000FFFF) != 0) {
-					dvb_dmx_swfilter_packets(dvbdmx, pbDMABufCurPos, dwDefaultPacketSize / 188);
-
-				} else {
-
-//                  dprintk("%s: pid=%x\n", __FUNCTION__, packet_header.pid);
-				}
-			}
+			dvb_dmx_swfilter_packets(dvbdmx, pb_dma_buf_cur_pos, dw_default_packet_size / 188);
 		}
 
-		nNumBytesParsed = nNumBytesParsed + dwDefaultPacketSize;
+		n_num_bytes_parsed = n_num_bytes_parsed + dw_default_packet_size;
 
-		adapter->dmaq1.tail = adapter->dmaq1.tail + dwDefaultPacketSize;
+		adapter->dmaq1.tail = adapter->dmaq1.tail + dw_default_packet_size;
 
 		if (adapter->dmaq1.tail >= adapter->dmaq1.buffer_size)
 			adapter->dmaq1.tail = adapter->dmaq1.tail - adapter->dmaq1.buffer_size;
 	};
 }
 
-static void InterruptServiceDMA2(struct adapter *adapter)
+static void interrupt_service_dma2(struct adapter *adapter)
 {
 	printk("%s:\n", __FUNCTION__);
 }
@@ -1901,28 +1651,28 @@
 
 	u32 value;
 
-//  dprintk("%s:\n", __FUNCTION__);
+	ddprintk("%s:\n", __FUNCTION__);
 
 	spin_lock_irq(&tmp->lock);
 
-	if (0 == ((value = ReadRegDW(tmp, 0x20C)) & 0x0F)) {
+	if (0 == ((value = read_reg_dw(tmp, 0x20c)) & 0x0f)) {
 		spin_unlock_irq(&tmp->lock);
 		return IRQ_NONE;
 	}
 	
 	while (value != 0) {
 		if ((value & 0x03) != 0)
-			InterruptServiceDMA1(tmp);
-		if ((value & 0x0C) != 0)
-			InterruptServiceDMA2(tmp);
-		value = ReadRegDW(tmp, 0x20C) & 0x0F;
+			interrupt_service_dma1(tmp);
+		if ((value & 0x0c) != 0)
+			interrupt_service_dma2(tmp);
+		value = read_reg_dw(tmp, 0x20c) & 0x0f;
 	}
 
 	spin_unlock_irq(&tmp->lock);
 	return IRQ_HANDLED;
 }
 
-static void Initdmaqueue(struct adapter *adapter)
+static void init_dma_queue(struct adapter *adapter)
 {
 	dma_addr_t dma_addr;
 
@@ -1933,19 +1683,19 @@
 	adapter->dmaq1.tail = 0;
 	adapter->dmaq1.buffer = 0;
 
-	adapter->dmaq1.buffer = pci_alloc_consistent(adapter->pdev, SizeOfBufDMA1 + 0x80, &dma_addr);
+	adapter->dmaq1.buffer = pci_alloc_consistent(adapter->pdev, SIZE_OF_BUF_DMA1 + 0x80, &dma_addr);
 
 	if (adapter->dmaq1.buffer != 0) {
-		memset(adapter->dmaq1.buffer, 0, SizeOfBufDMA1);
+		memset(adapter->dmaq1.buffer, 0, SIZE_OF_BUF_DMA1);
 
 		adapter->dmaq1.bus_addr = dma_addr;
-		adapter->dmaq1.buffer_size = SizeOfBufDMA1;
+		adapter->dmaq1.buffer_size = SIZE_OF_BUF_DMA1;
 
-		DmaInitDMA(adapter, 0);
+		dma_init_dma(adapter, 0);
 
 		adapter->dma_status = adapter->dma_status | 0x10000000;
 
-		dprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq1.buffer, SizeOfBufDMA1);
+		ddprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq1.buffer, SIZE_OF_BUF_DMA1);
 
 	} else {
 
@@ -1959,19 +1709,19 @@
 	adapter->dmaq2.tail = 0;
 	adapter->dmaq2.buffer = 0;
 
-	adapter->dmaq2.buffer = pci_alloc_consistent(adapter->pdev, SizeOfBufDMA2 + 0x80, &dma_addr);
+	adapter->dmaq2.buffer = pci_alloc_consistent(adapter->pdev, SIZE_OF_BUF_DMA2 + 0x80, &dma_addr);
 
 	if (adapter->dmaq2.buffer != 0) {
-		memset(adapter->dmaq2.buffer, 0, SizeOfBufDMA2);
+		memset(adapter->dmaq2.buffer, 0, SIZE_OF_BUF_DMA2);
 
 		adapter->dmaq2.bus_addr = dma_addr;
-		adapter->dmaq2.buffer_size = SizeOfBufDMA2;
+		adapter->dmaq2.buffer_size = SIZE_OF_BUF_DMA2;
 
-		DmaInitDMA(adapter, 1);
+		dma_init_dma(adapter, 1);
 
 		adapter->dma_status = adapter->dma_status | 0x20000000;
 
-		dprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq2.buffer, (int) SizeOfBufDMA2);
+		ddprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq2.buffer, (int) SIZE_OF_BUF_DMA2);
 
 	} else {
 
@@ -1979,10 +1729,10 @@
 	}
 }
 
-static void Freedmaqueue(struct adapter *adapter)
+static void free_dma_queue(struct adapter *adapter)
 {
 	if (adapter->dmaq1.buffer != 0) {
-		pci_free_consistent(adapter->pdev, SizeOfBufDMA1 + 0x80, adapter->dmaq1.buffer, adapter->dmaq1.bus_addr);
+		pci_free_consistent(adapter->pdev, SIZE_OF_BUF_DMA1 + 0x80, adapter->dmaq1.buffer, adapter->dmaq1.bus_addr);
 
 		adapter->dmaq1.bus_addr = 0;
 		adapter->dmaq1.head = 0;
@@ -1992,7 +1742,7 @@
 	}
 
 	if (adapter->dmaq2.buffer != 0) {
-		pci_free_consistent(adapter->pdev, SizeOfBufDMA2 + 0x80, adapter->dmaq2.buffer, adapter->dmaq2.bus_addr);
+		pci_free_consistent(adapter->pdev, SIZE_OF_BUF_DMA2 + 0x80, adapter->dmaq2.buffer, adapter->dmaq2.bus_addr);
 
 		adapter->dmaq2.bus_addr = 0;
 		adapter->dmaq2.head = 0;
@@ -2002,16 +1752,16 @@
 	}
 }
 
-static void FreeAdapterObject(struct adapter *adapter)
+static void free_adapter_object(struct adapter *adapter)
 {
 	dprintk("%s:\n", __FUNCTION__);
 
-	CloseStream(adapter, 0);
+	close_stream(adapter, 0);
 
 	if (adapter->irq != 0)
 		free_irq(adapter->irq, adapter);
 
-	Freedmaqueue(adapter);
+	free_dma_queue(adapter);
 
 	if (adapter->io_mem != 0)
 		iounmap((void *) adapter->io_mem);
@@ -2022,7 +1772,7 @@
 
 static struct pci_driver skystar2_pci_driver;
 
-static int ClaimAdapter(struct adapter *adapter)
+static int claim_adapter(struct adapter *adapter)
 {
 	struct pci_dev *pdev = adapter->pdev;
 
@@ -2062,20 +1812,58 @@
 }
 
 /*
-static int SLL_reset_FlexCOP(struct adapter *adapter)
+static int sll_reset_flexcop(struct adapter *adapter)
 {
-	WriteRegDW(adapter, 0x208, 0);
-	WriteRegDW(adapter, 0x210, 0xB2FF);
+	write_reg_dw(adapter, 0x208, 0);
+	write_reg_dw(adapter, 0x210, 0xb2ff);
 
 	return 0;
 }
 */
 
-static int DriverInitialize(struct pci_dev * pdev)
+static void decide_how_many_hw_filters(struct adapter *adapter)
+{
+	int hw_filters;
+	int mod_option_hw_filters;
+
+	// FlexCop IIb & III have 6+32 hw filters    
+	// FlexCop II has 6 hw filters, every other should have at least 6
+	switch (adapter->b2c2_revision) {
+	case 0x82:		/* II */
+		hw_filters = 6;
+		break;
+	case 0xc3:		/* IIB */
+		hw_filters = 6 + 32;
+		break;
+	case 0xc0:		/* III */
+		hw_filters = 6 + 32;
+		break;
+	default:
+		hw_filters = 6;
+		break;
+	}
+	printk("%s: the chip has %i hardware filters", __FILE__, hw_filters);
+
+	mod_option_hw_filters = 0;
+	if (enable_hw_filters >= 1)
+		mod_option_hw_filters += 6;
+	if (enable_hw_filters >= 2)
+		mod_option_hw_filters += 32;
+
+	if (mod_option_hw_filters >= hw_filters) {
+		adapter->useable_hw_filters = hw_filters;
+	} else {
+		adapter->useable_hw_filters = mod_option_hw_filters;
+		printk(", but only %d will be used because of module option", mod_option_hw_filters);
+	}
+	printk("\n");
+	dprintk("%s: useable_hardware_filters set to %i\n", __FILE__, adapter->useable_hw_filters);
+}
+
+static int driver_initialize(struct pci_dev *pdev)
 {
 	struct adapter *adapter;
 	u32 tmp;
-	u8 key[16];
 
 	if (!(adapter = kmalloc(sizeof(struct adapter), GFP_KERNEL))) {
 		dprintk("%s: out of memory!\n", __FUNCTION__);
@@ -2090,113 +1878,114 @@
 	adapter->pdev = pdev;
 	adapter->irq = pdev->irq;
 
-	if ((ClaimAdapter(adapter)) != 1) {
-		FreeAdapterObject(adapter);
+	if ((claim_adapter(adapter)) != 1) {
+		free_adapter_object(adapter);
 
 		return -ENODEV;
 	}
 
-	IrqDmaEnableDisableIrq(adapter, 0);
+	irq_dma_enable_disable_irq(adapter, 0);
 
 	if (request_irq(pdev->irq, isr, 0x4000000, "Skystar2", adapter) != 0) {
 		dprintk("%s: unable to allocate irq=%d !\n", __FUNCTION__, pdev->irq);
 
-		FreeAdapterObject(adapter);
+		free_adapter_object(adapter);
 
 		return -ENODEV;
 	}
 
-	ReadRegDW(adapter, 0x208);
-	WriteRegDW(adapter, 0x208, 0);
-	WriteRegDW(adapter, 0x210, 0xB2FF);
-	WriteRegDW(adapter, 0x208, 0x40);
-
-	InitPIDsInfo(adapter);
-
-	PidSetGroupPID(adapter, 0);
-	PidSetGroupMASK(adapter, 0x1FE0);
-	PidSetStream1PID(adapter, 0x1FFF);
-	PidSetStream2PID(adapter, 0x1FFF);
-	PidSetPmtPID(adapter, 0x1FFF);
-	PidSetPcrPID(adapter, 0x1FFF);
-	PidSetEcmPID(adapter, 0x1FFF);
-	PidSetEmmPID(adapter, 0x1FFF);
+	read_reg_dw(adapter, 0x208);
+	write_reg_dw(adapter, 0x208, 0);
+	write_reg_dw(adapter, 0x210, 0xb2ff);
+	write_reg_dw(adapter, 0x208, 0x40);
 
-	Initdmaqueue(adapter);
+	init_dma_queue(adapter);
 
 	if ((adapter->dma_status & 0x30000000) == 0) {
-		FreeAdapterObject(adapter);
+		free_adapter_object(adapter);
 
 		return -ENODEV;
 	}
 
-	adapter->b2c2_revision = (ReadRegDW(adapter, 0x204) >> 0x18);
-
-	if ((adapter->b2c2_revision != 0x82) && (adapter->b2c2_revision != 0xC3))
-		if (adapter->b2c2_revision != 0x82) {
-			dprintk("%s: The revision of the FlexCopII chip on your card is - %d\n", __FUNCTION__, adapter->b2c2_revision);
-			dprintk("%s: This driver works now only with FlexCopII(rev.130) and FlexCopIIB(rev.195).\n", __FUNCTION__);
-
-			FreeAdapterObject(adapter);
+	adapter->b2c2_revision = (read_reg_dw(adapter, 0x204) >> 0x18);
 
+	switch (adapter->b2c2_revision) {
+	case 0x82:
+		printk("%s: FlexCopII(rev.130) chip found\n", __FILE__);
+		break;
+	case 0xc3:
+		printk("%s: FlexCopIIB(rev.195) chip found\n", __FILE__);
+		break;
+	case 0xc0:
+		printk("%s: FlexCopIII(rev.192) chip found\n", __FILE__);
+		break;
+	default:
+		printk("%s: The revision of the FlexCop chip on your card is %d\n", __FILE__, adapter->b2c2_revision);
+		printk("%s: This driver works only with FlexCopII(rev.130), FlexCopIIB(rev.195) and FlexCopIII(rev.192).\n", __FILE__);
+		free_adapter_object(adapter);
+		pci_set_drvdata(pdev, NULL);
+		release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
+		release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
 			return -ENODEV;
 		}
 
-	tmp = ReadRegDW(adapter, 0x204);
+	decide_how_many_hw_filters(adapter);
+
+	init_pids(adapter);
 
-	WriteRegDW(adapter, 0x204, 0);
+	tmp = read_reg_dw(adapter, 0x204);
+
+	write_reg_dw(adapter, 0x204, 0);
 	mdelay(20);
 
-	WriteRegDW(adapter, 0x204, tmp);
+	write_reg_dw(adapter, 0x204, tmp);
 	mdelay(10);
 
-	tmp = ReadRegDW(adapter, 0x308);
-	WriteRegDW(adapter, 0x308, 0x4000 | tmp);
+	tmp = read_reg_dw(adapter, 0x308);
+	write_reg_dw(adapter, 0x308, 0x4000 | tmp);
 
-	adapter->dwSramType = 0x10000;
+	adapter->dw_sram_type = 0x10000;
 
-	SLL_detectSramSize(adapter);
+	sll_detect_sram_size(adapter);
 
-	dprintk("%s sram length = %d, sram type= %x\n", __FUNCTION__, SRAM_length(adapter), adapter->dwSramType);
+	dprintk("%s sram length = %d, sram type= %x\n", __FUNCTION__, sram_length(adapter), adapter->dw_sram_type);
 
-	SRAMSetMediaDest(adapter, 1);
-	SRAMSetNetDest(adapter, 1);
+	sram_set_media_dest(adapter, 1);
+	sram_set_net_dest(adapter, 1);
 
-	CtrlEnableSmc(adapter, 0);
+	ctrl_enable_smc(adapter, 0);
 
-	SRAMSetCaiDest(adapter, 2);
-	SRAMSetCaoDest(adapter, 2);
+	sram_set_cai_dest(adapter, 2);
+	sram_set_cao_dest(adapter, 2);
 
-	DmaEnableDisableIrq(adapter, 1, 0, 0);
+	dma_enable_disable_irq(adapter, 1, 0, 0);
 
-	if (EEPROM_getMacAddr(adapter, 0, adapter->mac_addr) != 0) {
-		printk("%s MAC address = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", __FUNCTION__, adapter->mac_addr[0], adapter->mac_addr[1], adapter->mac_addr[2], adapter->mac_addr[3], adapter->mac_addr[4], adapter->mac_addr[5], adapter->mac_addr[6], adapter->mac_addr[7]
+	if (eeprom_get_mac_addr(adapter, 0, adapter->mac_addr) != 0) {
+		printk("%s MAC address = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", __FUNCTION__, adapter->mac_addr[0],
+		       adapter->mac_addr[1], adapter->mac_addr[2], adapter->mac_addr[3], adapter->mac_addr[4], adapter->mac_addr[5],
+		       adapter->mac_addr[6], adapter->mac_addr[7]
 		    );
 
-		CASetMacDstAddrFilter(adapter, adapter->mac_addr);
-		CtrlEnableMAC(adapter, 1);
+		ca_set_mac_dst_addr_filter(adapter, adapter->mac_addr);
+		ctrl_enable_mac(adapter, 1);
 	}
 
-	EEPROM_readKey(adapter, key, 16);
-
-	printk("%s key = \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n", __FUNCTION__, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7], key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
-
 	adapter->lock = SPIN_LOCK_UNLOCKED;
 
 	return 0;
 }
 
-static void DriverHalt(struct pci_dev *pdev)
+static void driver_halt(struct pci_dev *pdev)
 {
 	struct adapter *adapter;
 
 	adapter = pci_get_drvdata(pdev);
 
-	IrqDmaEnableDisableIrq(adapter, 0);
+	irq_dma_enable_disable_irq(adapter, 0);
 
-	CtrlEnableReceiveData(adapter, 0);
+	ctrl_enable_receive_data(adapter, 0);
 
-	FreeAdapterObject(adapter);
+	free_adapter_object(adapter);
 
 	pci_set_drvdata(pdev, NULL);
 
@@ -2212,7 +2001,7 @@
 
 	dprintk("%s: PID=%d, type=%d\n", __FUNCTION__, dvbdmxfeed->pid, dvbdmxfeed->type);
 
-	OpenStream(adapter, dvbdmxfeed->pid);
+	open_stream(adapter, dvbdmxfeed->pid);
 
 	return 0;
 }
@@ -2224,7 +2013,7 @@
 
 	dprintk("%s: PID=%d, type=%d\n", __FUNCTION__, dvbdmxfeed->pid, dvbdmxfeed->type);
 
-	CloseStream(adapter, dvbdmxfeed->pid);
+	close_stream(adapter, dvbdmxfeed->pid);
 
 	return 0;
 }
@@ -2232,23 +2021,23 @@
 /* lnb control */
 static void set_tuner_tone(struct adapter *adapter, u8 tone)
 {
-	u16 wzHalfPeriodFor45MHz[] = { 0x01FF, 0x0154, 0x00FF, 0x00CC };
+	u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc };
 	u16 ax;
 
 	dprintk("%s: %u\n", __FUNCTION__, tone);
 
 	switch (tone) {
 	case 1:
-		ax = wzHalfPeriodFor45MHz[0];
+		ax = wz_half_period_for_45_mhz[0];
 		break;
 	case 2:
-		ax = wzHalfPeriodFor45MHz[1];
+		ax = wz_half_period_for_45_mhz[1];
 		break;
 	case 3:
-		ax = wzHalfPeriodFor45MHz[2];
+		ax = wz_half_period_for_45_mhz[2];
 		break;
 	case 4:
-		ax = wzHalfPeriodFor45MHz[3];
+		ax = wz_half_period_for_45_mhz[3];
 		break;
 
 	default:
@@ -2256,11 +2045,11 @@
 	}
 
 	if (ax != 0) {
-		WriteRegDW(adapter, 0x200, ((ax << 0x0F) + (ax & 0x7FFF)) | 0x40000000);
+		write_reg_dw(adapter, 0x200, ((ax << 0x0f) + (ax & 0x7fff)) | 0x40000000);
 
 	} else {
 
-		WriteRegDW(adapter, 0x200, 0x40FF8000);
+		write_reg_dw(adapter, 0x200, 0x40ff8000);
 	}
 }
 
@@ -2270,7 +2059,7 @@
 
 	dprintk("%s : polarity = %u \n", __FUNCTION__, polarity);
 
-	var = ReadRegDW(adapter, 0x204);
+	var = read_reg_dw(adapter, 0x204);
 
 	if (polarity == 0) {
 		dprintk("%s: LNB power off\n", __FUNCTION__);
@@ -2287,82 +2076,150 @@
 		var = var | 4;
 	}
 
-	WriteRegDW(adapter, 0x204, var);
+	write_reg_dw(adapter, 0x204, var);
 }
 
-static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
+static void diseqc_send_bit(struct adapter *adapter, int data)
 {
-	struct adapter *adapter = fe->before_after_data;
+	set_tuner_tone(adapter, 1);
+	udelay(data ? 500 : 1000);
+	set_tuner_tone(adapter, 0);
+	udelay(data ? 1000 : 500);
+}
 
-	switch (cmd) {
-	case FE_SLEEP:
+
+static void diseqc_send_byte(struct adapter *adapter, int data)
 		{
-			printk("%s: FE_SLEEP\n", __FUNCTION__);
+	int i, par = 1, d;
 
-			set_tuner_polarity(adapter, 0);
+	for (i = 7; i >= 0; i--) {
+		d = (data >> i) & 1;
+		par ^= d;
+		diseqc_send_bit(adapter, d);
+	}
 
-			// return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command to frontend.
-			return -EOPNOTSUPP;
+	diseqc_send_bit(adapter, par);
 		}
 
-	case FE_SET_VOLTAGE:
-		{
-			dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
 
-			switch ((fe_sec_voltage_t) arg) {
-			case SEC_VOLTAGE_13:
+static int send_diseqc_msg(struct adapter *adapter, int len, u8 *msg, unsigned long burst)
+{
+	int i;
 
-				printk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13);
+	set_tuner_tone(adapter, 0);
+	mdelay(16);
 
-				set_tuner_polarity(adapter, 1);
+	for (i = 0; i < len; i++)
+		diseqc_send_byte(adapter, msg[i]);
 
-				break;
+	mdelay(16);
 
-			case SEC_VOLTAGE_18:
+	if (burst != -1) {
+		if (burst)
+			diseqc_send_byte(adapter, 0xff);
+		else {
+			set_tuner_tone(adapter, 1);
+			udelay(12500);
+			set_tuner_tone(adapter, 0);
+		}
+		dvb_delay(20);
+	}
 
-				printk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18);
+	return 0;
+}
 
-				set_tuner_polarity(adapter, 2);
 
+int soft_diseqc(struct adapter *adapter, unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case FE_SET_TONE:
+		switch ((fe_sec_tone_mode_t) arg) {
+		case SEC_TONE_ON:
+			set_tuner_tone(adapter, 1);
+			break;
+		case SEC_TONE_OFF:
+			set_tuner_tone(adapter, 0);
 				break;
-
 			default:
-
 				return -EINVAL;
 			};
+		break;
 
+	case FE_DISEQC_SEND_MASTER_CMD:
+		{
+			struct dvb_diseqc_master_cmd *cmd = arg;
+
+			send_diseqc_msg(adapter, cmd->msg_len, cmd->msg, 0);
 			break;
 		}
 
-	case FE_SET_TONE:
+	case FE_DISEQC_SEND_BURST:
+		send_diseqc_msg(adapter, 0, NULL, (unsigned long) arg);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	};
+
+	return 0;
+}
+
+static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
 		{
-			dprintk("%s: FE_SET_TONE\n", __FUNCTION__);
+	struct adapter *adapter = fe->before_after_data;
 
-			switch ((fe_sec_tone_mode_t) arg) {
-			case SEC_TONE_ON:
+	struct dvb_frontend_info info;
 
-				printk("%s: SEC_TONE_ON, %x\n", __FUNCTION__, SEC_TONE_ON);
+	fe->ioctl(fe, FE_GET_INFO, &info);
 
-				set_tuner_tone(adapter, 1);
+	// we must use different DiSEqC hw
 
-				break;
+	if (strcmp(info.name, "Zarlink MT312") == 0) {
+		//VP310 using mt312 driver for tuning only: diseqc not wired
+		//use FCII instead
+		if (!soft_diseqc(adapter, cmd, arg))
+			return 0;
+	}
 
-			case SEC_TONE_OFF:
+	switch (cmd) {
+	case FE_SLEEP:
+		{
+			dprintk("%s: FE_SLEEP\n", __FUNCTION__);
 
-				printk("%s: SEC_TONE_OFF, %x\n", __FUNCTION__, SEC_TONE_OFF);
+			set_tuner_polarity(adapter, 0);
 
-				set_tuner_tone(adapter, 0);
+			// return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command to frontend.
+			return -EOPNOTSUPP;
+		}
 
-				break;
+	case FE_SET_VOLTAGE:
+		{
+			dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
+
+			switch ((fe_sec_voltage_t) arg) {
+			case SEC_VOLTAGE_13:
+
+				dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13);
+
+				set_tuner_polarity(adapter, 1);
+
+				return 0;
+
+			case SEC_VOLTAGE_18:
+
+				dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18);
+
+				set_tuner_polarity(adapter, 2);
+
+				return 0;
 
 			default:
 
 				return -EINVAL;
 			};
-
-			break;
 		}
 
+
 	default:
 
 		return -EOPNOTSUPP;
@@ -2382,7 +2240,7 @@
 	if (pdev == NULL)
 		return -ENODEV;
 
-	if (DriverInitialize(pdev) != 0)
+	if (driver_initialize(pdev) != 0)
 		return -ENODEV;
 
 	dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name);
@@ -2390,7 +2248,7 @@
 	if (dvb_adapter == NULL) {
 		printk("%s: Error registering DVB adapter\n", __FUNCTION__);
 
-		DriverHalt(pdev);
+		driver_halt(pdev);
 
 		return -ENODEV;
 	}
@@ -2411,8 +2269,8 @@
 	dvbdemux = &adapter->demux;
 
 	dvbdemux->priv = (void *) adapter;
-	dvbdemux->filternum = 32;
-	dvbdemux->feednum = 32;
+	dvbdemux->filternum = N_PID_SLOTS;
+	dvbdemux->feednum = N_PID_SLOTS;
 	dvbdemux->start_feed = dvb_start_feed;
 	dvbdemux->stop_feed = dvb_stop_feed;
 	dvbdemux->write_to_decoder = 0;
@@ -2422,7 +2280,7 @@
 
 	adapter->hw_frontend.source = DMX_FRONTEND_0;
 
-	adapter->dmxdev.filternum = 32;
+	adapter->dmxdev.filternum = N_PID_SLOTS;
 	adapter->dmxdev.demux = &dvbdemux->dmx;
 	adapter->dmxdev.capabilities = 0;
 
@@ -2475,13 +2333,13 @@
 
 			dvb_unregister_adapter(adapter->dvb_adapter);
 		}
-
-		DriverHalt(pdev);
+		driver_halt(pdev);
 	}
 }
 
 static struct pci_device_id skystar2_pci_tbl[] = {
-	{0x000013D0, 0x00002103, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000},
+	{0x000013d0, 0x00002103, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000},
+	{0x000013d0, 0x00002200, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000},	//FCIII
 	{0,},
 };
 
@@ -2505,5 +2363,10 @@
 module_init(skystar2_init);
 module_exit(skystar2_cleanup);
 
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "enable verbose debug messages: supported values: 1 and 2");
+MODULE_PARM(enable_hw_filters, "i");
+MODULE_PARM_DESC(enable_hw_filters, "enable hardware filters: supported values: 0 (none), 1, 2");
+
 MODULE_DESCRIPTION("Technisat SkyStar2 DVB PCI Driver");
 MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 5/12] Update DVB core
  2003-12-19 12:28       ` [PATCH 4/12] Update Skystar2 " Michael Hunold
@ 2003-12-19 12:28         ` Michael Hunold
  2003-12-19 12:28           ` [PATCH 6/12] Update DVB frontend drivers Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - add a parameter to dvb_filter_pes2ts function to specify whether the packet is a payload unit start or not.
DVB: - new section demux code by emard
DVB: - change license GPL -> LGPL for dvb_ringbuffer, like all other DVB core files
DVB: - fix rare crash on invalid packets, patch by Asier Aguirre
DVB: - i2c: copy the data variable as well on register client so that detach sees it.
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/demux.h linux-2.6.0-p/drivers/media/dvb/dvb-core/demux.h
--- linux-2.6.0/drivers/media/dvb/dvb-core/demux.h	2003-12-18 03:58:40.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/demux.h	2003-12-08 16:19:00.000000000 +0100
@@ -44,6 +44,15 @@
 #endif 
 
 /*
+ * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
+ */ 
+
+#ifndef DMX_MAX_SECFEED_SIZE 
+#define DMX_MAX_SECFEED_SIZE 4096
+#endif 
+
+
+/*
  * enum dmx_success: Success codes for the Demux Callback API. 
  */ 
 
@@ -143,9 +152,9 @@
         int check_crc;
 	u32 crc_val;
 
-        u8 secbuf[4096];
-        int secbufp;
-        int seclen;
+        u8 *secbuf;
+        u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
+        u16 secbufp, seclen, tsfeedp;
 
         int (*set) (struct dmx_section_feed* feed, 
 		    u16 pid, 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/dvb_demux.c linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_demux.c
--- linux-2.6.0/drivers/media/dvb/dvb-core/dvb_demux.c	2003-12-18 03:58:16.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_demux.c	2003-12-08 16:19:00.000000000 +0100
@@ -34,6 +34,11 @@
 #include "dvb_functions.h"
 
 #define NOBUFS  
+/* 
+** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
+*/
+// #define DVB_DEMUX_SECTION_LOSS_LOG
+
 
 LIST_HEAD(dmx_muxs);
 
@@ -87,7 +92,7 @@
 }
 
 
-static inline int payload(const u8 *tsp)
+static inline u8 payload(const u8 *tsp)
 {
 	if (!(tsp[3]&0x10)) // no payload?
 		return 0;
@@ -188,9 +195,7 @@
 	struct dvb_demux_filter *f = feed->filter;
 	struct dmx_section_feed *sec = &feed->feed.sec;
 	u8 *buf = sec->secbuf;
-
-	if (sec->secbufp != sec->seclen)
-		return -1;
+	int section_syntax_indicator;
 
 	if (!sec->is_filtering)
 		return 0;
@@ -198,15 +203,19 @@
 	if (!f)
 		return 0;
 
-	if (sec->check_crc && demux->check_crc32(feed, sec->secbuf, sec->seclen))
+	if (sec->check_crc) {
+		section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
+		if (section_syntax_indicator &&
+		    demux->check_crc32(feed, sec->secbuf, sec->seclen))
 		return -1;
+	}
 
 	do {
 		if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0)
 			return -1;
 	} while ((f = f->next) && sec->is_filtering);
 
-	sec->secbufp = sec->seclen = 0;
+	sec->seclen = 0;
 
 	memset(buf, 0, DVB_DEMUX_MASK_MAX);
  
@@ -214,128 +223,147 @@
 }
 
 
-static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) 
+static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
 {
-	struct dvb_demux *demux = feed->demux;
 	struct dmx_section_feed *sec = &feed->feed.sec;
-	int p, count;
-	int ccok, rest;
-	u8 cc;
 
-	if (!(count = payload(buf)))
-		return -1;
-
-	p = 188-count;
-
-	cc = buf[3] & 0x0f;
-	ccok = ((feed->cc+1) & 0x0f) == cc ? 1 : 0;
-	feed->cc = cc;
-
-	if (buf[1] & 0x40) { // PUSI set
-		// offset to start of first section is in buf[p] 
-		if (p+buf[p]>187) // trash if it points beyond packet
-			return -1;
-
-		if (buf[p] && ccok) { // rest of previous section?
-			// did we have enough data in last packet to calc length?
-			int tmp = 3 - sec->secbufp;
-
-			if (tmp > 0 && tmp != 3) {
-				if (p + tmp >= 187)
-					return -1;
-
-				demux->memcopy (feed, sec->secbuf+sec->secbufp,
-					       buf+p+1, tmp);
-
-				sec->seclen = section_length(sec->secbuf);
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+	if(sec->secbufp < sec->tsfeedp)
+	{
+		int i, n = sec->tsfeedp - sec->secbufp;
 
-				if (sec->seclen > 4096) 
-					return -1;
+		/* section padding is done with 0xff bytes entirely.
+		** due to speed reasons, we won't check all of them
+		** but just first and last
+		*/
+		if(sec->secbuf[0] != 0xff || sec->secbuf[n-1] != 0xff)
+		{
+			printk("dvb_demux.c section ts padding loss: %d/%d\n", 
+			       n, sec->tsfeedp);
+			printk("dvb_demux.c pad data:");
+			for(i = 0; i < n; i++)
+				printk(" %02x", sec->secbuf[i]);
+			printk("\n");
 			}
-
-			rest = sec->seclen - sec->secbufp;
-
-			if (rest == buf[p] && sec->seclen) {
-				demux->memcopy (feed, sec->secbuf + sec->secbufp,
-					       buf+p+1, buf[p]);
-				sec->secbufp += buf[p];
-				dvb_dmx_swfilter_section_feed(feed);
 			}
+#endif
+
+	sec->tsfeedp = sec->secbufp = sec->seclen = 0;
+	sec->secbuf = sec->secbuf_base;
 		}
 
-		p += buf[p] + 1; 		// skip rest of last section
-		count = 188 - p;
+/* 
+** Losless Section Demux 1.4 by Emard
+*/
+static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const u8 *buf, u8 len)
+{
+	struct dvb_demux *demux = feed->demux;
+	struct dmx_section_feed *sec = &feed->feed.sec;
+	u16 limit, seclen, n;
 
-		while (count) {
+	if(sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
+		return 0;
 
-			sec->crc_val = ~0;
+	if(sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE)
+	{
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+		printk("dvb_demux.c section buffer full loss: %d/%d\n", 
+		       sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, DMX_MAX_SECFEED_SIZE);
+#endif
+		len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
+	}
 
-			if ((count>2) && // enough data to determine sec length?
-			    ((sec->seclen = section_length(buf+p)) <= count)) {
-				if (sec->seclen>4096) 
-					return -1;
+	if(len <= 0)
+		return 0;
 
-				demux->memcopy (feed, sec->secbuf, buf+p,
-					       sec->seclen);
+	demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
+	sec->tsfeedp += len;
 
-				sec->secbufp = sec->seclen;
-				p += sec->seclen;
-				count = 188 - p;
+	/* -----------------------------------------------------
+	** Dump all the sections we can find in the data (Emard)
+	*/
 
-				dvb_dmx_swfilter_section_feed(feed);
+	limit = sec->tsfeedp;
+	if(limit > DMX_MAX_SECFEED_SIZE)
+		return -1; /* internal error should never happen */
 
-				// filling bytes until packet end?
-				if (count && buf[p]==0xff) 
-					count=0;
+	/* to be sure always set secbuf */
+	sec->secbuf = sec->secbuf_base + sec->secbufp;
 
-			} else { // section continues to following TS packet
-				demux->memcopy(feed, sec->secbuf, buf+p, count);
-				sec->secbufp+=count;
-				count=0;
-			}
+	for(n = 0; sec->secbufp + 2 < limit; n++)
+	{
+		seclen = section_length(sec->secbuf);
+		if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE 
+		   || seclen + sec->secbufp > limit)
+			return 0;
+		sec->seclen = seclen;
+		sec->crc_val = ~0;
+		/* dump [secbuf .. secbuf+seclen) */
+		dvb_dmx_swfilter_section_feed(feed);
+		sec->secbufp += seclen; /* secbufp and secbuf moving together is */
+		sec->secbuf += seclen; /* redundand but saves pointer arithmetic */
 		}
 
 		return 0;
 	}
 
-	// section continued below
-	if (!ccok)
-		return -1;
 
-	if (!sec->secbufp) // any data in last ts packet?
-		return -1;
+static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) 
+{
+	u8 p, count;
+	int ccok;
+	u8 cc;
 
-	// did we have enough data in last packet to calc section length?
-	if (sec->secbufp < 3) {
-		int tmp = 3 - sec->secbufp;
+	count = payload(buf);
 		
-		if (tmp>count)
+	if (count == 0)  /* count == 0 if no payload or out of range */
 			return -1;
 
-		sec->crc_val = ~0;
-
-		demux->memcopy (feed, sec->secbuf + sec->secbufp, buf+p, tmp);
+	p = 188-count; /* payload start */
 
-		sec->seclen = section_length(sec->secbuf);
-
-		if (sec->seclen > 4096) 
-			return -1;
+	cc = buf[3] & 0x0f;
+	ccok = ((feed->cc+1) & 0x0f) == cc ? 1 : 0;
+	feed->cc = cc;
+	if(ccok == 0)
+	{
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+		printk("dvb_demux.c discontinuity detected %d bytes lost\n", count);
+		/* those bytes under sume circumstances will again be reported
+		** in the following dvb_dmx_swfilter_section_new
+		*/
+#endif
+		dvb_dmx_swfilter_section_new(feed);
+		return 0;
 	}
 
-	rest = sec->seclen - sec->secbufp;
-
-	if (rest < 0)
-		return -1;
+	if(buf[1] & 0x40)
+	{
+		// PUSI=1 (is set), section boundary is here
+		if(count > 1 && buf[p] < count)
+		{
+			const u8 *before = buf+p+1;
+			u8 before_len = buf[p];
+			const u8 *after = before+before_len;
+			u8 after_len = count-1-before_len;
 
-	if (rest <= count) {	// section completed in this TS packet
-		demux->memcopy (feed, sec->secbuf + sec->secbufp, buf+p, rest);
-		sec->secbufp += rest;
-		dvb_dmx_swfilter_section_feed(feed);
-	} else 	{	// section continues in following ts packet
-		demux->memcopy (feed, sec->secbuf + sec->secbufp, buf+p, count);
-		sec->secbufp += count;
+			dvb_dmx_swfilter_section_copy_dump(feed, before, before_len);
+			dvb_dmx_swfilter_section_new(feed);
+			dvb_dmx_swfilter_section_copy_dump(feed, after, after_len);
+		}
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+		else
+			if(count > 0)
+				printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
+#endif
 	}
+	else
+	{
+		// PUSI=0 (is not set), no section boundary
+		const u8 *entire = buf+p;
+		u8 entire_len = count;
 
+		dvb_dmx_swfilter_section_copy_dump(feed, entire, entire_len);
+	}
 	return 0;
 }
 
@@ -439,6 +467,50 @@
 	spin_unlock(&demux->lock);
 }
 
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+	int p = 0,i, j;
+	u8 tmppack[188];
+	spin_lock(&demux->lock);
+
+	if ((i = demux->tsbufp)) {
+		if (count < (j=204-i)) {
+			memcpy(&demux->tsbuf[i], buf, count);
+			demux->tsbufp += count;
+			goto bailout;
+		}
+		memcpy(&demux->tsbuf[i], buf, j);
+		if ((demux->tsbuf[0] == 0x47)|(demux->tsbuf[0]==0xB8))  {
+			memcpy(tmppack, demux->tsbuf, 188);
+			if (tmppack[0] == 0xB8) tmppack[0] = 0x47;
+			dvb_dmx_swfilter_packet(demux, tmppack);
+		}
+		demux->tsbufp = 0;
+		p += j;
+	}
+
+	while (p < count) {
+		if ((buf[p] == 0x47)|(buf[p] == 0xB8)) {
+			if (count-p >= 204) {
+				memcpy(tmppack, buf+p, 188);
+				if (tmppack[0] == 0xB8) tmppack[0] = 0x47;
+				dvb_dmx_swfilter_packet(demux, tmppack);
+				p += 204;
+			} else {
+				i = count-p;
+				memcpy(demux->tsbuf, buf+p, i);
+				demux->tsbufp=i;
+				goto bailout;
+			}
+		} else { 
+			p++;
+		}
+	}
+
+bailout:
+	spin_unlock(&demux->lock);
+}
+
 
 static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux)
 {
@@ -848,6 +924,9 @@
 		up(&dvbdmx->mutex);
 		return -EINVAL;
 	}
+
+	dvbdmxfeed->feed.sec.tsfeedp = 0;
+	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
 	dvbdmxfeed->feed.sec.secbufp=0;
 	dvbdmxfeed->feed.sec.seclen=0;
 	
@@ -946,7 +1032,9 @@
 	dvbdmxfeed->cb.sec=callback;
 	dvbdmxfeed->demux=dvbdmx;
 	dvbdmxfeed->pid=0xffff;
-	dvbdmxfeed->feed.sec.secbufp=0;
+	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
+	dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
+	dvbdmxfeed->feed.sec.tsfeedp = 0;
 	dvbdmxfeed->filter=0;
 	dvbdmxfeed->buffer=0;
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/dvb_demux.h linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_demux.h
--- linux-2.6.0/drivers/media/dvb/dvb-core/dvb_demux.h	2003-12-18 03:58:41.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_demux.h	2003-10-13 12:52:18.000000000 +0200
@@ -127,7 +127,7 @@
 
 #define DMX_MAX_PID 0x2000
 	struct list_head feed_list;
-        u8 tsbuf[188];
+        u8 tsbuf[204];
         int tsbufp;
 
 	struct semaphore mutex;
@@ -140,6 +140,7 @@
 void dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf);
 void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count);
 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count);
 
 int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend);
 int dvbdmx_disconnect_frontend(struct dmx_demux *demux);
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/dvb_filter.c linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_filter.c
--- linux-2.6.0/drivers/media/dvb/dvb-core/dvb_filter.c	2003-12-18 04:00:01.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_filter.c	2003-12-10 13:50:15.000000000 +0100
@@ -564,14 +564,18 @@
 	p2ts->priv=priv;
 }
 
-int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, int len)
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+		      int len, int payload_start)
 {
 	unsigned char *buf=p2ts->buf;
 	int ret=0, rest;
 	
 	//len=6+((pes[4]<<8)|pes[5]);
 
+	if (payload_start)
 	buf[1]|=0x40;
+	else
+		buf[1]&=~0x40;
 	while (len>=184) {
 		buf[3]=0x10|((p2ts->cc++)&0x0f);
 		memcpy(buf+4, pes, 184);
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/dvb_filter.h linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_filter.h
--- linux-2.6.0/drivers/media/dvb/dvb-core/dvb_filter.h	2003-12-18 03:58:28.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_filter.h	2003-12-10 13:50:15.000000000 +0100
@@ -37,7 +37,8 @@
 void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid, 
 		 	    dvb_filter_pes2ts_cb_t *cb, void *priv);
 
-int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, int len);
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+		      int len, int payload_start);
 
 
 #define PROG_STREAM_MAP  0xBC
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/dvb_i2c.c linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_i2c.c
--- linux-2.6.0/drivers/media/dvb/dvb-core/dvb_i2c.c	2003-12-18 03:59:16.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_i2c.c	2003-10-28 10:39:42.000000000 +0100
@@ -51,6 +51,7 @@
 
 	client->detach = dev->detach;
 	client->owner = dev->owner;
+	client->data = dev->data;
 
 	INIT_LIST_HEAD(&client->list_head);
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/dvb_ksyms.c linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_ksyms.c
--- linux-2.6.0/drivers/media/dvb/dvb-core/dvb_ksyms.c	2003-12-18 03:59:53.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_ksyms.c	2003-10-13 12:52:18.000000000 +0200
@@ -18,6 +18,7 @@
 EXPORT_SYMBOL(dvb_dmx_swfilter_packet);
 EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 EXPORT_SYMBOL(dvb_dmx_swfilter);
+EXPORT_SYMBOL(dvb_dmx_swfilter_204);
 EXPORT_SYMBOL(dvbdmx_connect_frontend);
 EXPORT_SYMBOL(dvbdmx_disconnect_frontend);
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/dvb_ringbuffer.c linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
--- linux-2.6.0/drivers/media/dvb/dvb-core/dvb_ringbuffer.c	2003-12-18 03:59:05.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_ringbuffer.c	2003-11-20 09:44:03.000000000 +0100
@@ -9,24 +9,18 @@
  *                       & Marcus Metzler for convergence integrated media GmbH
  *
  * 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
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
  * 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.
- * 
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- * 
- *
- * the project's page is at http://www.linuxtv.org/dvb/
  */
 
 
@@ -167,11 +161,11 @@
 }
 
 
-EXPORT_SYMBOL_GPL(dvb_ringbuffer_init);
-EXPORT_SYMBOL_GPL(dvb_ringbuffer_empty);
-EXPORT_SYMBOL_GPL(dvb_ringbuffer_free);
-EXPORT_SYMBOL_GPL(dvb_ringbuffer_avail);
-EXPORT_SYMBOL_GPL(dvb_ringbuffer_flush);
-EXPORT_SYMBOL_GPL(dvb_ringbuffer_flush_spinlock_wakeup);
-EXPORT_SYMBOL_GPL(dvb_ringbuffer_read);
-EXPORT_SYMBOL_GPL(dvb_ringbuffer_write);
+EXPORT_SYMBOL(dvb_ringbuffer_init);
+EXPORT_SYMBOL(dvb_ringbuffer_empty);
+EXPORT_SYMBOL(dvb_ringbuffer_free);
+EXPORT_SYMBOL(dvb_ringbuffer_avail);
+EXPORT_SYMBOL(dvb_ringbuffer_flush);
+EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
+EXPORT_SYMBOL(dvb_ringbuffer_read);
+EXPORT_SYMBOL(dvb_ringbuffer_write);
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/dvb-core/dvb_ringbuffer.h linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
--- linux-2.6.0/drivers/media/dvb/dvb-core/dvb_ringbuffer.h	2003-12-18 03:59:58.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/dvb-core/dvb_ringbuffer.h	2003-11-20 09:44:03.000000000 +0100
@@ -16,7 +16,7 @@
  * 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.
+ * GNU Lesser General Public License for more details.
  * 
  * You should have received a copy of the GNU Lesser General Public License
  * along with this program; if not, write to the Free Software


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 6/12] Update DVB frontend drivers
  2003-12-19 12:28         ` [PATCH 5/12] Update DVB core Michael Hunold
@ 2003-12-19 12:28           ` Michael Hunold
  2003-12-19 12:28             ` [PATCH 7/12] Update av7110 driver Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - alps_tdmb7, cx24110: use correct delay values, don't divide by HZ when using dvb_delay(), found by Artur Skawina
DVB: - alps_tdmb7: set FE_HAS_LOCK only when all low-order bits are valid
DVB: - mt312: patch for the mt312 module, targeting the VP310:  reduced heat, implement "auto" inversion mode, remove debugging verbosity, add module parameter for debugging (Augusto Cardoso)
DVB: - nxt6000: code review and beautification, use per i2c-adapater void pointer for private data in nxt_attach() / nxt_detach, fix frontend private data handling. patch by Mikael Rosbacke <rosbacke at nada.kth.se>
DVB: - sp887x: firmware loader implementation contributed by Martin Stubbs, C99 comile fixes by  Wolfgang Thiel
DVB: - stv0299: Added new module parameter to choose between BER and UCBLOCKs error monitoring since the STV0299 can't do both at once, Added modifications based on the recommended settings in the SU1278 datasheet.
DVB: - tda1004x: remove FE_CAN_INVERSION_AUTO
DVB: - ves1820:completed nokia board support, increased some delays to get constant results,set default pwm value to 0x48 for boards which don't have an eeprom  (by Andreas Oberritter)
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/alps_tdmb7.c linux-2.6.0-p/drivers/media/dvb/frontends/alps_tdmb7.c
--- linux-2.6.0/drivers/media/dvb/frontends/alps_tdmb7.c	2003-12-18 03:58:18.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/alps_tdmb7.c	2003-12-10 13:50:15.000000000 +0100
@@ -159,7 +159,7 @@
 	cx22700_writereg (i2c, 0x00, 0x02);   /*  soft reset */
 	cx22700_writereg (i2c, 0x00, 0x00);
 
-	dvb_delay (HZ/100);
+	dvb_delay(10);
 	
 	for (i=0; i<sizeof(init_tab); i+=2)
 		cx22700_writereg (i2c, init_tab[i], init_tab[i+1]);
@@ -281,15 +281,15 @@
 
 	val = cx22700_readreg (i2c, 0x02);
 
-	if ((val >> 3) > 4)
+	if (((val >> 3) & 0x07) > 4)
 		p->code_rate_HP = FEC_AUTO;
 	else
-		p->code_rate_HP = fec_tab[val >> 3];
+		p->code_rate_HP = fec_tab[(val >> 3) & 0x07];
 
-	if ((val & 0x7) > 4)
+	if ((val & 0x07) > 4)
 		p->code_rate_LP = FEC_AUTO;
 	else
-		p->code_rate_LP = fec_tab[val >> 3];
+		p->code_rate_LP = fec_tab[val & 0x07];
 
 
 	val = cx22700_readreg (i2c, 0x03);
@@ -333,7 +333,7 @@
 		if (sync & 0x10)
 			*status |= FE_HAS_SYNC;
 
-		if (sync & 0x10)
+		if (*status == 0x0f)
 			*status |= FE_HAS_LOCK;
 
 		break;
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/cx24110.c linux-2.6.0-p/drivers/media/dvb/frontends/cx24110.c
--- linux-2.6.0/drivers/media/dvb/frontends/cx24110.c	2003-12-18 03:58:04.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/cx24110.c	2003-12-10 13:50:15.000000000 +0100
@@ -248,7 +248,7 @@
         cx24108_write(i2c,pll);
         cx24110_writereg(i2c,0x56,0x7f);
 
-	dvb_delay(HZ/10); /* wait a moment for the tuner pll to lock */
+	dvb_delay(10); /* wait a moment for the tuner pll to lock */
 
 	/* tuner pll lock can be monitored on GPIO pin 4 of cx24110 */
         while (!(cx24110_readreg(i2c,0x66)&0x20)&&i<1000)
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/mt312.c linux-2.6.0-p/drivers/media/dvb/frontends/mt312.c
--- linux-2.6.0/drivers/media/dvb/frontends/mt312.c	2003-12-18 03:58:08.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/mt312.c	2003-12-08 16:19:00.000000000 +0100
@@ -39,11 +39,19 @@
 #define MT312_DEBUG		0
 
 #define MT312_SYS_CLK		90000000UL	/* 90 MHz */
+#define MT312_LPOWER_SYS_CLK	60000000UL	/* 60 MHz */
 #define MT312_PLL_CLK		10000000UL	/* 10 MHz */
 
 /* number of active frontends */
 static int mt312_count = 0;
 
+#if MT312_DEBUG == 0
+#define dprintk(x...)
+#else
+static int debug = 0;
+#define dprintk if(debug == 1) printk
+#endif
+
 static struct dvb_frontend_info mt312_info = {
 	.name = "Zarlink MT312",
 	.type = FE_QPSK,
@@ -86,7 +94,7 @@
 		return -EREMOTEIO;
 	}
 #if MT312_DEBUG
-	{
+	if(debug) {
 		int i;
 		printk(KERN_INFO "R(%d):", reg & 0x7f);
 		for (i = 0; i < count; i++)
@@ -107,7 +115,7 @@
 	struct i2c_msg msg;
 
 #if MT312_DEBUG
-	{
+	if(debug) {
 		int i;
 		printk(KERN_INFO "W(%d):", reg & 0x7f);
 		for (i = 0; i < count; i++)
@@ -205,7 +213,7 @@
 	if (freq < 1550000)
 		buf[3] |= 0x10;
 
-	printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
+	dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
 	       buf[1], buf[2], buf[3]);
 
 	return mt312_pll_write(i2c, I2C_ADDR_SL1935, buf, sizeof(buf));
@@ -225,7 +233,7 @@
 	if (freq < 1550000)
 		buf[3] |= 0x02;
 
-	printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
+	dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
 	       buf[1], buf[2], buf[3]);
 
 	return mt312_pll_write(i2c, I2C_ADDR_TSA5059, buf, sizeof(buf));
@@ -236,13 +244,13 @@
 	return mt312_writereg(i2c, RESET, full ? 0x80 : 0x40);
 }
 
-static int mt312_init(struct dvb_i2c_bus *i2c, const long id)
+static int mt312_init(struct dvb_i2c_bus *i2c, const long id, u8 pll)
 {
 	int ret;
 	u8 buf[2];
 
 	/* wake up */
-	if ((ret = mt312_writereg(i2c, CONFIG, 0x8c)) < 0)
+	if ((ret = mt312_writereg(i2c, CONFIG, (pll == 60 ? 0x88 : 0x8c))) < 0)
 		return ret;
 
 	/* wait at least 150 usec */
@@ -252,8 +260,17 @@
 	if ((ret = mt312_reset(i2c, 1)) < 0)
 		return ret;
 
+// Per datasheet, write correct values. 09/28/03 ACCJr.
+// If we don't do this, we won't get FE_HAS_VITERBI in the VP310.
+	{
+		u8 buf_def[8]={0x14, 0x12, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00};
+
+		if ((ret = mt312_write(i2c, VIT_SETUP, buf_def, sizeof(buf_def))) < 0)
+			return ret;
+	}
+
 	/* SYS_CLK */
-	buf[0] = mt312_div(MT312_SYS_CLK * 2, 1000000);
+	buf[0] = mt312_div((pll == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000);
 
 	/* DISEQC_RATIO */
 	buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
@@ -370,16 +387,18 @@
 	return mt312_writereg(i2c, DISEQC_MODE, volt_tab[v]);
 }
 
-static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t * s)
+static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t *s, const long id)
 {
 	int ret;
-	u8 status[3];
+	u8 status[3], vit_mode;
 
 	*s = 0;
 
 	if ((ret = mt312_read(i2c, QPSK_STAT_H, status, sizeof(status))) < 0)
 		return ret;
 
+	dprintk(KERN_DEBUG "QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
+
 	if (status[0] & 0xc0)
 		*s |= FE_HAS_SIGNAL;	/* signal noise ratio */
 	if (status[0] & 0x04)
@@ -390,6 +409,16 @@
 		*s |= FE_HAS_SYNC;	/* byte align lock */
 	if (status[0] & 0x01)
 		*s |= FE_HAS_LOCK;	/* qpsk lock */
+	// VP310 doesn't have AUTO, so we "implement it here" ACCJr
+	if ((id == ID_VP310) && !(status[0] & 0x01)) {
+		if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0)
+			return ret;
+		vit_mode ^= 0x40;
+		if ((ret = mt312_writereg(i2c, VIT_MODE, vit_mode)) < 0)
+                	return ret;
+		if ((ret = mt312_writereg(i2c, GO, 0x01)) < 0)
+                	return ret;
+	}
 
 	return 0;
 }
@@ -422,7 +451,7 @@
 
 	*signal_strength = agc;
 
-	printk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
+	dprintk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
 
 	return 0;
 }
@@ -458,7 +487,7 @@
 			      const long id)
 {
 	int ret;
-	u8 buf[5];
+	u8 buf[5], config_val;
 	u16 sr;
 
 	const u8 fec_tab[10] =
@@ -467,6 +496,8 @@
 
 	int (*set_tv_freq)(struct dvb_i2c_bus *i2c, u32 freq, u32 sr);
 
+	dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
+
 	if ((p->frequency < mt312_info.frequency_min)
 	    || (p->frequency > mt312_info.frequency_max))
 		return -EINVAL;
@@ -489,6 +520,22 @@
 
 	switch (id) {
 	case ID_VP310:
+	// For now we will do this only for the VP310.
+	// It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03
+		if ((ret = mt312_readreg(i2c, CONFIG, &config_val) < 0))
+			return ret;
+		if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz
+		{
+			if ((config_val & 0x0c) == 0x08) //We are running 60MHz
+				if ((ret = mt312_init(i2c, id, (u8) 90)) < 0)
+					return ret;
+		}
+		else
+		{
+			if ((config_val & 0x0c) == 0x0C) //We are running 90MHz
+				if ((ret = mt312_init(i2c, id, (u8) 60)) < 0)
+					return ret;
+		}
 		set_tv_freq = tsa5059_set_tv_freq;
 		break;
 	case ID_MT312:
@@ -562,7 +609,7 @@
 
 		monitor = (buf[0] << 8) | buf[1];
 
-		printk(KERN_DEBUG "sr(auto) = %u\n",
+		dprintk(KERN_DEBUG "sr(auto) = %u\n",
 		       mt312_div(monitor * 15625, 4));
 	} else {
 		if ((ret = mt312_writereg(i2c, MON_CTRL, 0x05)) < 0)
@@ -578,9 +625,9 @@
 
 		sym_rat_op = (buf[0] << 8) | buf[1];
 
-		printk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
+		dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
 		       sym_rat_op, dec_ratio);
-		printk(KERN_DEBUG "*sr(manual) = %lu\n",
+		dprintk(KERN_DEBUG "*sr(manual) = %lu\n",
 		       (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
 			2) - dec_ratio);
 	}
@@ -675,7 +722,7 @@
 		return -EOPNOTSUPP;
 
 	case FE_READ_STATUS:
-		return mt312_read_status(i2c, arg);
+		return mt312_read_status(i2c, arg, (long) fe->data);
 
 	case FE_READ_BER:
 		return mt312_read_bercnt(i2c, arg);
@@ -702,7 +749,12 @@
 		return mt312_sleep(i2c);
 
 	case FE_INIT:
-		return mt312_init(i2c, (long) fe->data);
+	//For the VP310 we should run at 60MHz when ever possible.
+	//It should be better to run the mt312 ar lower speed when ever possible, but tunning will be slower. ACCJr 09/29/03
+		if ((long)fe->data == ID_MT312)
+			return mt312_init(i2c, (long) fe->data, (u8) 90);
+		else
+			return mt312_init(i2c, (long) fe->data, (u8) 60);
 
 	case FE_RESET:
 		return mt312_reset(i2c, 0);
@@ -755,6 +807,11 @@
 module_init(mt312_module_init);
 module_exit(mt312_module_exit);
 
+#if MT312_DEBUG != 0
+MODULE_PARM(debug,"i");
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+#endif
+
 MODULE_DESCRIPTION("MT312 Satellite Channel Decoder Driver");
 MODULE_AUTHOR("Andreas Oberritter <obi@saftware.de>");
 MODULE_LICENSE("GPL");
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/nxt6000.c linux-2.6.0-p/drivers/media/dvb/frontends/nxt6000.c
--- linux-2.6.0/drivers/media/dvb/frontends/nxt6000.c	2003-12-18 03:59:06.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/nxt6000.c	2003-11-25 13:10:26.000000000 +0100
@@ -55,20 +52,10 @@
 	.symbol_rate_max = 9360000,	/* FIXME */
 	.symbol_rate_tolerance = 4000,
 	.notifier_delay = 0,
-	.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO,
-
+	.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
 };
 
-#pragma pack(1)
-
 struct nxt6000_config {
-
 	u8 demod_addr;
 	u8 tuner_addr;
 	u8 tuner_type;
@@ -73,16 +60,13 @@
 	u8 tuner_addr;
 	u8 tuner_type;
 	u8 clock_inversion;
-
 };
 
-#pragma pack()
-
 #define TUNER_TYPE_ALP510	0
 #define TUNER_TYPE_SP5659	1
 #define TUNER_TYPE_SP5730	2
 
-#define FE2NXT(fe) ((struct nxt6000_config *)&(fe->data))
+#define FE2NXT(fe) ((struct nxt6000_config *)((fe)->data))
 #define FREQ2DIV(freq) ((freq + 36166667) / 166667)
 
 #define dprintk if (debug) printk
@@ -116,8 +95,10 @@
 	int ret;
 	u8 b0[] = {reg};
 	u8 b1[] = {0};
-	struct i2c_msg msgs[] = {{.addr = addr >> 1, .flags = 0, .buf = b0, .len = 1},
-							{.addr = addr >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1}};
+	struct i2c_msg msgs[] = {
+		{.addr = addr >> 1,.flags = 0,.buf = b0,.len = 1},
+		{.addr = addr >> 1,.flags = I2C_M_RD,.buf = b1,.len = 1}
+	};
 
 	ret = i2c->xfer(i2c, msgs, 2);
 	
@@ -394,7 +333,7 @@
 	nxt6000_writereg(fe, OFDM_ITB_FREQ_1, 0x06);
 	nxt6000_writereg(fe, OFDM_ITB_FREQ_2, 0x31);
 	nxt6000_writereg(fe, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04);
-	nxt6000_writereg(fe, CAS_FREQ, 0xBB);	// CHECKME
+	nxt6000_writereg(fe, CAS_FREQ, 0xBB);	/* CHECKME */
 	nxt6000_writereg(fe, OFDM_SYR_CTL, 1 << 2);
 	nxt6000_writereg(fe, OFDM_PPM_CTL_1, PPM256);
 	nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_1, 0x49);
@@ -414,20 +352,20 @@
 
 static void nxt6000_dump_status(struct dvb_frontend *fe)
 {
-
 	u8 val;
 
-//	printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
-//	printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
-//	printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
-//	printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
-//	printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
-//	printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
-//	printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
-//	printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
-//	printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
-//	printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
-
+/*
+	printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
+	printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
+	printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
+	printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
+	printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
+	printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
+	printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
+	printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
+	printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
+	printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
+*/
 	printk("NXT6000 status:");
 
 	val = nxt6000_readreg(fe, RS_COR_STAT);
@@ -460,13 +392,11 @@
 			break;
 	
 		case 0x03: 
-		
 			printk(" VITERBI CODERATE: 5/6,");
+		break;
 
 		case 0x04: 
-		
 			printk(" VITERBI CODERATE: 7/8,");
-			
 			break;
 
 		default: 
@@ -503,13 +426,11 @@
 			break;
 	
 		case 0x04:
-		
 			printk(" CoreState: WAIT_PPM,");
+		break;
 
 		case 0x01:
-		
 			printk(" CoreState: WAIT_TRL,");
-			
 			break;
 
 		case 0x05:
@@ -586,13 +487,11 @@
 			break;
 	
 		case 0x03: 
-		
 			printk(" TPSLP: 5/6,");
+		break;
 
 		case 0x04: 
-		
 			printk(" TPSLP: 7/8,");
-			
 			break;
 
 		default: 
@@ -622,13 +514,11 @@
 			break;
 	
 		case 0x03: 
-		
 			printk(" TPSHP: 5/6,");
+		break;
 
 		case 0x04: 
-		
 			printk(" TPSHP: 7/8,");
-			
 			break;
 
 		default: 
@@ -669,7 +550,7 @@
 			
 	}
 	
-	// Strange magic required to gain access to RF_AGC_STATUS
+	/* Strange magic required to gain access to RF_AGC_STATUS */
 	nxt6000_readreg(fe, RF_AGC_VAL_1);
 	val = nxt6000_readreg(fe, RF_AGC_STATUS);
 	val = nxt6000_readreg(fe, RF_AGC_STATUS);
@@ -735,21 +611,23 @@
 	
 		case FE_READ_SIGNAL_STRENGTH:
 		{
-//			s16 *signal = (s16 *)arg;
-
-//		*signal=(((signed char)readreg(client, 0x16))+128)<<8;
-
+			s16 *signal = (s16 *) arg;
+/*
+			*signal=(((signed char)readreg(client, 0x16))+128)<<8;
+*/
+			*signal = 0;
 			return 0;
 			
 		}
 	
 		case FE_READ_SNR:
 		{
-//			s16 *snr = (s16 *)arg;
-
-//		*snr=readreg(client, 0x24)<<8;
-//		*snr|=readreg(client, 0x25);
-
+			s16 *snr = (s16 *) arg;
+/*
+			*snr=readreg(client, 0x24)<<8;
+			*snr|=readreg(client, 0x25);
+*/
+			*snr = 0;
 			break;
 		}
 	
@@ -831,70 +698,74 @@
 
 static int nxt6000_attach(struct dvb_i2c_bus *i2c, void **data)
 {
-
 	u8 addr_nr;
 	u8 fe_count = 0;
-	struct nxt6000_config nxt;
+	struct nxt6000_config *pnxt;
 
 	dprintk("nxt6000: attach\n");
 	
+	pnxt = kmalloc(sizeof(demod_addr_tbl)*sizeof(struct nxt6000_config), GFP_KERNEL);
+	if (NULL == pnxt) {
+		dprintk("nxt6000: no memory for private data.\n");
+		return -ENOMEM;
+	}
+	*data = pnxt;
+
 	for (addr_nr = 0; addr_nr < sizeof(demod_addr_tbl); addr_nr++) {
+		struct nxt6000_config *nxt = &pnxt[addr_nr];
 	
 		if (nxt6000_read(i2c, demod_addr_tbl[addr_nr], OFDM_MSC_REV) != NXT6000ASICDEVICE)
 			continue;
 
 		if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) {
+			nxt->tuner_addr = 0xC0;
+			nxt->tuner_type = TUNER_TYPE_ALP510;
+			nxt->clock_inversion = 1;
 	
-			nxt.tuner_addr = 0xC0;
-			nxt.tuner_type = TUNER_TYPE_ALP510;
-			nxt.clock_inversion = 1;
-			
-			dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt.tuner_addr);
+			dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt->tuner_addr);
 		
 		} else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC2, NULL, 0) == 0) {
+			nxt->tuner_addr = 0xC2;
+			nxt->tuner_type = TUNER_TYPE_SP5659;
+			nxt->clock_inversion = 0;
 
-			nxt.tuner_addr = 0xC2;
-			nxt.tuner_type = TUNER_TYPE_SP5659;
-			nxt.clock_inversion = 0;
-	
-			dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt.tuner_addr);
+			dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt->tuner_addr);
 		
 		} else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) {
+			nxt->tuner_addr = 0xC0;
+			nxt->tuner_type = TUNER_TYPE_SP5730;
+			nxt->clock_inversion = 0;
 
-			nxt.tuner_addr = 0xC0;
-			nxt.tuner_type = TUNER_TYPE_SP5730;
-			nxt.clock_inversion = 0;
-	
-			dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt.tuner_addr);
+			dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt->tuner_addr);
 		
 		} else {
-
 			printk("nxt6000: unable to detect tuner\n");
-
 			continue;	
-		
 		}
 		
-		nxt.demod_addr = demod_addr_tbl[addr_nr];
+		nxt->demod_addr = demod_addr_tbl[addr_nr];
 	  
 		dprintk("nxt6000: attached at %d:%d\n", i2c->adapter->num, i2c->id);
 	
-		dvb_register_frontend(nxt6000_ioctl, i2c, (void *)(*((u32 *)&nxt)), &nxt6000_info);
+		dvb_register_frontend(nxt6000_ioctl, i2c, (void *)nxt, &nxt6000_info);
 		
 		fe_count++;
 	}
 	
-	return (fe_count > 0) ? 0 : -ENODEV;
+	if (fe_count == 0) {
+		kfree(pnxt);
+		return -ENODEV;
+	}
 	
+	return 0;
 }
 
 static void nxt6000_detach(struct dvb_i2c_bus *i2c, void *data)
 {
-
+	struct nxt6000_config *pnxt = (struct nxt6000_config *)data;
 	dprintk("nxt6000: detach\n");
-
 	dvb_unregister_frontend(nxt6000_ioctl, i2c);
-	
+	kfree(pnxt);
 }
 
 static __init int nxt6000_init(void)
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/nxt6000.h linux-2.6.0.p/drivers/media/dvb/frontends/nxt6000.h
--- linux-2.6.0/drivers/media/dvb/frontends/nxt6000.h	2003-12-19 12:55:39.000000000 +0100
+++ linux-2.6.0.p/drivers/media/dvb/frontends/nxt6000.h	2003-11-12 15:12:54.000000000 +0100
@@ -1,45 +1,10 @@
-/**********************************************************************/
- * DRV6000reg.H
+/*
  * Public Include File for DRV6000 users
+ * (ie. NxtWave Communications - NXT6000 demodulator driver)
  *
  * Copyright (C) 2001 NxtWave Communications, Inc.
  *
- * $Log: nxt6000.h,v $
- * Revision 1.2  2003/01/27 12:32:42  fschirmer
- * Lots of bugfixes and new features
- *
- * Revision 1.1  2003/01/21 18:43:09  fschirmer
- * Nxt6000 based frontend driver
- *
- * Revision 1.1  2003/01/03 02:25:45  obi
- * alps tdme7 driver
- *
- * 
- *    Rev 1.10   Jun 12 2002 11:28:02   dkoeger
- * Updated for SA in GUi work
- * 
- *    Rev 1.9   Apr 01 2002 10:38:46   dkoeger
- * Updated for 1.0.31 GUI
- * 
- *    Rev 1.8   Mar 11 2002 10:04:56   dkoeger
- * Updated for 1.0.31 GUI version
- * 
- *    Rev 1.5   Dec 07 2001 14:40:40   dkoeger
- * Updated for 1.0.28 GUI
- * 
- *    Rev 1.4   Nov 13 2001 11:09:00   dkoeger
- * No change.
- * 
- *    Rev 1.3   Aug 23 2001 14:21:02   dkoeger
- * Updated for driver version 2.1.9
- * 
- *    Rev 1.2   Jul 09 2001 09:20:04   dkoeger
- * Updated for 1.0.18
- * 
- *    Rev 1.1   Jun 13 2001 16:14:24   dkoeger
- * Updated to reflect NXT6000 GUI BETA 1.0.11 6/13/2001
- **********************************************************************/
-
+ */
 
 /*  Nxt6000 Register Addresses and Bit Masks */
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/sp887x.c linux-2.6.0-p/drivers/media/dvb/frontends/sp887x.c
--- linux-2.6.0/drivers/media/dvb/frontends/sp887x.c	2003-12-18 03:59:17.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/sp887x.c	2003-12-08 16:19:00.000000000 +0100
@@ -1,8 +1,31 @@
+/*
+   Driver for the Microtune 7202D Frontend
+*/
+
+/*
+   This driver needs a copy of the Avermedia firmware. The version tested
+   is part of the Avermedia DVB-T 1.3.26.3 Application. If the software is
+   installed in Windows the file will be in the /Program Files/AVerTV DVB-T/
+   directory and is called sc_main.mc. Alternatively it can "extracted" from
+   the install cab files. Copy this file to /etc/dvb/sc_main.mc.
+   With this version of the file the first 10 bytes are discarded and the
+   next 0x4000 loaded. This may change in future versions.
+ */
 
+#define __KERNEL_SYSCALLS__
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/unistd.h>
+#include <linux/fcntl.h>
+#include <linux/errno.h>
 #include <linux/i2c.h>
 
+
 #include "dvb_frontend.h"
 #include "dvb_functions.h"
 
@@ -6,6 +29,11 @@
 #include "dvb_frontend.h"
 #include "dvb_functions.h"
 
+#ifndef DVB_SP887X_FIRMWARE_FILE
+#define DVB_SP887X_FIRMWARE_FILE "/etc/dvb/sc_main.mc"
+#endif
+
+static char *sp887x_firmware = DVB_SP887X_FIRMWARE_FILE;
 
 #if 0
 #define dprintk(x...) printk(x)
@@ -39,7 +67,7 @@
 		FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_RECOVER
 };
 
-
+static int errno;
 
 static
 int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len)
@@ -112,6 +140,7 @@
 static
 void sp887x_microcontroller_stop (struct dvb_frontend *fe)
 {
+	dprintk("%s\n", __FUNCTION__);
 	sp887x_writereg(fe, 0xf08, 0x000);
 	sp887x_writereg(fe, 0xf09, 0x000);		
 
@@ -123,6 +152,7 @@
 static
 void sp887x_microcontroller_start (struct dvb_frontend *fe)
 {
+	dprintk("%s\n", __FUNCTION__);
 	sp887x_writereg(fe, 0xf08, 0x000);
 	sp887x_writereg(fe, 0xf09, 0x000);		
 
@@ -135,6 +165,7 @@
 void sp887x_setup_agc (struct dvb_frontend *fe)
 {
 	/* setup AGC parameters */
+	dprintk("%s\n", __FUNCTION__);
 	sp887x_writereg(fe, 0x33c, 0x054);
 	sp887x_writereg(fe, 0x33b, 0x04c);
 	sp887x_writereg(fe, 0x328, 0x000);
@@ -152,8 +183,6 @@
 }
 
 
-#include "sp887x_firm.h"
-
 #define BLOCKSIZE 30
 
 /**
@@ -162,14 +191,63 @@
 static
 int sp887x_initial_setup (struct dvb_frontend *fe)
 {
-	u8 buf [BLOCKSIZE];
+	u8 buf [BLOCKSIZE+2];
+	unsigned char *firmware = NULL;
 	int i;
+	int fd;
+	int filesize;
+	int fw_size;
+	mm_segment_t fs;
+
+	dprintk("%s\n", __FUNCTION__);
 
 	/* soft reset */
 	sp887x_writereg(fe, 0xf1a, 0x000);
 
 	sp887x_microcontroller_stop (fe);
 
+	fs = get_fs();
+
+	// Load the firmware
+	set_fs(get_ds());
+	fd = open(sp887x_firmware, 0, 0);
+	if (fd < 0) {
+		printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__,
+		       sp887x_firmware);
+		return -EIO;
+	}
+	filesize = lseek(fd, 0L, 2);
+	if (filesize <= 0) {
+		printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__,
+		       sp887x_firmware);
+		sys_close(fd);
+		return -EIO;
+	}
+
+	fw_size = 0x4000;
+
+	// allocate buffer for it
+	firmware = vmalloc(fw_size);
+	if (firmware == NULL) {
+		printk(KERN_WARNING "%s: Out of memory loading firmware\n",
+		       __FUNCTION__);
+		sys_close(fd);
+		return -EIO;
+	}
+
+	// read it!
+	// read the first 16384 bytes from the file
+	// ignore the first 10 bytes
+	lseek(fd, 10, 0);
+	if (read(fd, firmware, fw_size) != fw_size) {
+		printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__);
+		vfree(firmware);
+		sys_close(fd);
+		return -EIO;
+	}
+	sys_close(fd);
+	set_fs(fs);
+
 	printk ("%s: firmware upload... ", __FUNCTION__);
 
 	/* setup write pointer to -1 (end of memory) */
@@ -179,12 +257,12 @@
 	/* dummy write (wrap around to start of memory) */
 	sp887x_writereg(fe, 0x8f0a, 0x0000);
 
-	for (i=0; i<sizeof(sp887x_firm); i+=BLOCKSIZE) {
+	for (i=0; i<fw_size; i+=BLOCKSIZE) {
 		int c = BLOCKSIZE;
 		int err;
 
-		if (i+c > sizeof(sp887x_firm))
-			c = sizeof(sp887x_firm) - i;
+		if (i+c > fw_size)
+			c = fw_size - i;
 
 		/* bit 0x8000 in address is set to enable 13bit mode */
 		/* bit 0x4000 enables multibyte read/write transfers */
@@ -192,15 +270,18 @@
 		buf[0] = 0xcf;
 		buf[1] = 0x0a;
 
-		memcpy(&buf[2], &sp887x_firm[i], c);
+		memcpy(&buf[2], firmware + i, c);
 
 		if ((err = i2c_writebytes (fe, 0x70, buf, c+2)) < 0) {
 			printk ("failed.\n");
 			printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
+			vfree(firmware);
 			return err;
 		}
 	}
 
+	vfree(firmware);
+
 	/* don't write RS bytes between packets */
 	sp887x_writereg(fe, 0xc13, 0x001);
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/stv0299.c linux-2.6.0-p/drivers/media/dvb/frontends/stv0299.c
--- linux-2.6.0/drivers/media/dvb/frontends/stv0299.c	2003-12-18 03:59:58.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/stv0299.c	2003-11-20 09:44:03.000000000 +0100
@@ -9,16 +9,23 @@
 	<holger@convergence.de>,
 	<js@convergence.de>
     
+
     Philips SU1278/SH
 
-    Copyright (C) 2002 by Peter Schildmann
-        <peter.schildmann@web.de>
+    Copyright (C) 2002 by Peter Schildmann <peter.schildmann@web.de>
+
 
     LG TDQF-S001F
 
     Copyright (C) 2002 Felix Domke <tmbinc@elitedvb.net>
                      & Andreas Oberritter <andreas@oberritter.de>
 
+
+    Support for Samsung TBMU24112IMB used on Technisat SkyStar2 rev. 2.6B
+
+    Copyright (C) 2003 Vadim Catana <skystar@moldova.cc>:
+
+
     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
@@ -39,6 +46,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/string.h>
+#include <asm/div64.h>
 
 #include "dvb_frontend.h"
 #include "dvb_functions.h"
@@ -49,6 +57,11 @@
 #define dprintk(x...)
 #endif
 
+static int stv0299_status = 0;
+
+#define STATUS_BER 0
+#define STATUS_UCBLOCKS 1
+
 
 /* frontend types */
 #define UNKNOWN_FRONTEND  -1
@@ -56,6 +69,7 @@
 #define ALPS_BSRU6         1
 #define LG_TDQF_S001F      2
 #define PHILIPS_SU1278     3
+#define SAMSUNG_TBMU24112IMB    4
 
 /* Master Clock = 88 MHz */
 #define M_CLK (88000000UL) 
@@ -142,6 +156,51 @@
 };
 
 
+static u8 init_tab_samsung [] = {
+	0x01, 0x15,
+	0x02, 0x00,
+	0x03, 0x00,
+	0x04, 0x7D,
+	0x05, 0x35,
+	0x06, 0x02,
+	0x07, 0x00,
+	0x08, 0xC3,
+	0x0C, 0x00,
+	0x0D, 0x81,
+	0x0E, 0x23,
+	0x0F, 0x12,
+	0x10, 0x7E,
+	0x11, 0x84,
+	0x12, 0xB9,
+	0x13, 0x88,
+	0x14, 0x89,
+	0x15, 0xC9,
+	0x16, 0x00,
+	0x17, 0x5C,
+	0x18, 0x00,
+	0x19, 0x00,
+	0x1A, 0x00,
+	0x1C, 0x00,
+	0x1D, 0x00,
+	0x1E, 0x00,
+	0x1F, 0x3A,
+	0x20, 0x2E,
+	0x21, 0x80,
+	0x22, 0xFF,
+	0x23, 0xC1,
+	0x28, 0x00,
+	0x29, 0x1E,
+	0x2A, 0x14,
+	0x2B, 0x0F,
+	0x2C, 0x09,
+	0x2D, 0x05,
+	0x31, 0x1F,
+	0x32, 0x19,
+	0x33, 0xFE,
+	0x34, 0x93
+};
+
+
 static int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
 {
 	int ret;
@@ -169,7 +228,8 @@
 	ret = i2c->xfer (i2c, msg, 2);
         
 	if (ret != 2) 
-		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+				__FUNCTION__, reg, ret);
 
 	return b1[0];
 }
@@ -193,18 +253,19 @@
 static int pll_write (struct dvb_i2c_bus *i2c, u8 addr, u8 *data, int len)
 {
 	int ret;
-	u8 rpt1 [] = { 0x05, 0xb5 };  /*  enable i2c repeater on stv0299  */
-	u8 rpt2 [] = { 0x05, 0x35 };  /*  disable i2c repeater on stv0299  */
-	struct i2c_msg msg [] = {{ .addr = 0x68, .flags = 0, .buf = rpt1, .len = 2 },
-			         { addr: addr, .flags = 0, .buf = data, .len = len },
-				 { .addr = 0x68, .flags = 0, .buf = rpt2, .len = 2 }};
+	struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = len };
 
-	ret = i2c->xfer (i2c, msg, 3);
 
-	if (ret != 3)
-		printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret);
+	stv0299_writereg(i2c, 0x05, 0xb5);	/*  enable i2c repeater on stv0299  */
+
+	ret =  i2c->xfer (i2c, &msg, 1);
+
+	stv0299_writereg(i2c, 0x05, 0x35);	/*  disable i2c repeater on stv0299  */
 
-	return (ret != 3) ? ret : 0;
+	if (ret != 1)
+		dprintk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret);
+
+	return (ret != 1) ? -1 : 0;
 }
 
 
@@ -213,23 +274,16 @@
 	u8 buf[4];
 	u32 div;
 
-	u32 ratios[] = { 2000, 1000, 500, 250, 125 };
-	u8 ratio;
+	div = freq / 125;
 
-	for (ratio = 4; ratio > 0; ratio--)
-		if ((freq / ratios[ratio]) <= 0x3fff)
-			break;
-
-	div = freq / ratios[ratio];
+	dprintk("%s : freq = %i, div = %i\n", __FUNCTION__, freq, div);
 
-	buf[0] = (freq >> 8) & 0x7f;
-	buf[1] = freq & 0xff;
-	buf[2] = 0x80 | ratio;
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0x84;	// 0xC4
+	buf[3] = 0x08;
 
-	if (freq < 1531000)
-		buf[3] = 0x10;
-	else
-		buf[3] = 0x00;
+	if (freq < 1500000) buf[3] |= 0x10;
 
 	return pll_write (i2c, 0x61, buf, sizeof(buf));
 }
@@ -238,21 +292,47 @@
  *   set up the downconverter frequency divisor for a 
  *   reference clock comparision frequency of 125 kHz.
  */
-static int tsa5059_set_tv_freq	(struct dvb_i2c_bus *i2c, u32 freq, int ftype)
+static int tsa5059_set_tv_freq	(struct dvb_i2c_bus *i2c, u32 freq, int ftype, int srate)
 {
-	u8 addr = (ftype == PHILIPS_SU1278SH) ? 0x60 : 0x61;
-        u32 div = freq / 125;
-	u8 buf[4] = { (div >> 8) & 0x7f, div & 0xff, 0x84 };
+	u8 addr;
+	u32 div;
+	u8 buf[4];
 
 	dprintk ("%s: freq %i, ftype %i\n", __FUNCTION__, freq, ftype);
 
-	if (ftype == PHILIPS_SU1278SH)
-		/* activate f_xtal/f_comp signal output */
-		/* charge pump current C0/C1 = 00 */
-		buf[3] = 0x20;
-	else
-		buf[3] = freq > 1530000 ? 0xc0 : 0xc4;
+	if ((freq < 950000) || (freq > 2150000)) return -EINVAL;
 
+	// setup frequency divisor
+	div = freq / 1000;
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0x81 | ((div & 0x18000) >> 10);
+	buf[3] = 0;
+
+	// tuner-specific settings
+	switch(ftype) {
+	case PHILIPS_SU1278SH:
+		addr = 0x60;
+		buf[3] |= 0x20;
+
+		if (srate < 4000000) buf[3] |= 1;
+	   
+		if (freq <= 1250000) buf[3] |= 0;
+		else if (freq <= 1550000) buf[3] |= 0x40;
+		else if (freq <= 2050000) buf[3] |= 0x80;
+		else if (freq <= 2150000) buf[3] |= 0xC0;
+		break;
+
+	case ALPS_BSRU6:
+		addr = 0x61;
+		buf[3] |= 0xC0;
+	 	break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// charge pump
 	return pll_write (i2c, addr, buf, sizeof(buf));
 }
 
@@ -385,12 +465,14 @@
 
 static int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, int srate)
 {
-	if (ftype == LG_TDQF_S001F)
+	if (ftype == SAMSUNG_TBMU24112IMB)
+		return sl1935_set_tv_freq(i2c, freq, ftype);
+	else if (ftype == LG_TDQF_S001F)
 		return sl1935_set_tv_freq(i2c, freq, ftype);
 	else if (ftype == PHILIPS_SU1278)
 		return tua6100_set_tv_freq(i2c, freq, ftype, srate);
 	else
-		return tsa5059_set_tv_freq(i2c, freq, ftype);
+		return tsa5059_set_tv_freq(i2c, freq, ftype, srate);
 }
 
 #if 0
@@ -421,6 +503,19 @@
 
 	dprintk("stv0299: init chip\n");
 
+	switch(ftype) {
+	case SAMSUNG_TBMU24112IMB:
+		dprintk("%s: init stv0299 chip for Samsung TBMU24112IMB\n", __FUNCTION__);
+
+		for (i=0; i<sizeof(init_tab_samsung); i+=2)
+		{
+			dprintk("%s: reg == 0x%02x, val == 0x%02x\n", __FUNCTION__, init_tab_samsung[i], init_tab_samsung[i+1]);
+
+			stv0299_writereg (i2c, init_tab_samsung[i], init_tab_samsung[i+1]);
+		}
+		break;
+
+	default:
 	stv0299_writereg (i2c, 0x01, 0x15);
 	stv0299_writereg (i2c, 0x02, ftype == PHILIPS_SU1278 ? 0x00 : 0x30);
 	stv0299_writereg (i2c, 0x03, 0x00);
@@ -430,11 +525,23 @@
 
         /* AGC1 reference register setup */
 	if (ftype == PHILIPS_SU1278SH)
-	  stv0299_writereg (i2c, 0x0f, 0xd2);  /* Iagc = Inverse, m1 = 18 */
+		  stv0299_writereg (i2c, 0x0f, 0x92);  /* Iagc = Inverse, m1 = 18 */
 	else if (ftype == PHILIPS_SU1278)
-	  stv0299_writereg (i2c, 0x0f, 0x94);  /* Iagc = Inverse, m1 = 18 */
+		  stv0299_writereg (i2c, 0x0f, 0x94);  /* Iagc = Inverse, m1 = 20 */
 	else
 	  stv0299_writereg (i2c, 0x0f, 0x52);  /* Iagc = Normal,  m1 = 18 */
+		break;
+	}
+	
+	switch(stv0299_status) {
+	case STATUS_BER:
+		stv0299_writereg(i2c, 0x34, 0x93);
+		break;
+	
+	case STATUS_UCBLOCKS:
+		stv0299_writereg(i2c, 0x34, 0xB3);
+		break;
+	}
 
 	return 0;
 }
@@ -448,6 +555,7 @@
 		dvb_delay(30);
 		if ((stv0299_readreg (i2c, 0x1b) & 0x98) != 0x98) {
 		u8 val = stv0299_readreg (i2c, 0x0c);
+			dprintk ("%s : changing inversion\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x0c, val ^ 0x01);
 	}
 	}
@@ -462,21 +570,42 @@
 
 	switch (fec) {
 	case FEC_AUTO:
+	{
+		dprintk ("%s : FEC_AUTO\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x31, 0x1f);
+	}
 	case FEC_1_2:
+	{
+		dprintk ("%s : FEC_1_2\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x31, 0x01);
+	}
 	case FEC_2_3:
+	{
+		dprintk ("%s : FEC_2_3\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x31, 0x02);
+	}
 	case FEC_3_4:
+	{
+		dprintk ("%s : FEC_3_4\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x31, 0x04);
+	}
 	case FEC_5_6:
+	{
+		dprintk ("%s : FEC_5_6\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x31, 0x08);
+	}
 	case FEC_7_8:
+	{
+		dprintk ("%s : FEC_7_8\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x31, 0x10);
+	}
 	default:
+	{
+		dprintk ("%s : FEC invalid\n", __FUNCTION__);
 		return -EINVAL;
 	}
 }
+}
 
 
 static fe_code_rate_t stv0299_get_fec (struct dvb_i2c_bus *i2c)
@@ -606,11 +735,20 @@
 
 	switch (tone) {
 	case SEC_TONE_ON:
+	{
+	    	dprintk("%s: TONE_ON\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x08, val | 0x3);
+	}	
 	case SEC_TONE_OFF:
+	{
+	    	dprintk("%s: TONE_OFF\n", __FUNCTION__);
 		return stv0299_writereg (i2c, 0x08, (val & ~0x3) | 0x02);
+	}
 	default:
+	{
+	    	dprintk("%s: TONE INVALID\n", __FUNCTION__);
 		return -EINVAL;
+	}
 	};
 }
 
@@ -651,39 +789,60 @@
 }
 
 
-static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate)
+static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner_type)
 {
+	u64 big = srate;
 	u32 ratio;
-	u32 tmp;
-	u8 aclk = 0xb4, bclk = 0x51;
+	u8 aclk = 0;
+	u8 bclk = 0;
+	u8 m1;
+
+	if ((srate < 1000000) || (srate > 45000000)) return -EINVAL;
+	switch(tuner_type) {
+	case PHILIPS_SU1278SH:
+		aclk = 0xb5;
+		if (srate < 2000000) bclk = 0x86;
+		else if (srate < 5000000) bclk = 0x89;
+		else if (srate < 15000000) bclk = 0x8f;
+		else if (srate < 45000000) bclk = 0x95;
+
+		m1 = 0x14;
+		if (srate < 4000000) m1 = 0x10;
+		break;
 
-	if (srate > M_CLK)
-		srate = M_CLK;
-        if (srate < 500000)
-		srate = 500000;
-
-	if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
-	if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
-	if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
-	if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
-	if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
-
-#define FIN (M_CLK >> 4)
+	case ALPS_BSRU6:
+	default:
+		if (srate <= 1500000) { aclk = 0xb7; bclk = 0x87; }
+		else if (srate <= 3000000) { aclk = 0xb7; bclk = 0x8b; }
+		else if (srate <= 7000000) { aclk = 0xb7; bclk = 0x8f; }
+		else if (srate <= 14000000) { aclk = 0xb7; bclk = 0x93; }
+		else if (srate <= 30000000) { aclk = 0xb6; bclk = 0x93; }
+		else if (srate <= 45000000) { aclk = 0xb4; bclk = 0x91; }
 
-	tmp = srate << 4;
-	ratio = tmp / FIN;
+		m1 = 0x12;
+		break;   
+	}
         
-	tmp = (tmp % FIN) << 8;
-	ratio = (ratio << 8) + tmp / FIN;
+	dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff),  (int) (big & 0xffffffff) );
         
-	tmp = (tmp % FIN) << 8;
-	ratio = (ratio << 8) + tmp / FIN;
+	big = big << 20;
+
+	dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff),  (int) (big & 0xffffffff) );
+
+	do_div(big, M_CLK);
+
+	dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff),  (int) (big & 0xffffffff) );
+
+	ratio = big << 4;
+
+	dprintk("%s : ratio = %i\n", __FUNCTION__, ratio);
   
 	stv0299_writereg (i2c, 0x13, aclk);
 	stv0299_writereg (i2c, 0x14, bclk);
 	stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff);
 	stv0299_writereg (i2c, 0x20, (ratio >>  8) & 0xff);
 	stv0299_writereg (i2c, 0x21, (ratio      ) & 0xf0);
+	stv0299_writereg (i2c, 0x0f, (stv0299_readreg(i2c, 0x0f) & 0xc0) | m1);
 
 	return 0;
 }
@@ -710,6 +869,9 @@
 	offset = (s32) rtf * (srate / 4096L);
 	offset /= 128;
 
+	dprintk ("%s : srate = %i\n", __FUNCTION__, srate);
+	dprintk ("%s : ofset = %i\n", __FUNCTION__, offset);
+
 	srate += offset;
 
 	srate += 1000;
@@ -725,6 +887,8 @@
         int tuner_type = (long) fe->data;
 	struct dvb_i2c_bus *i2c = fe->i2c;
 
+	dprintk ("%s\n", __FUNCTION__);
+
 	switch (cmd) {
 	case FE_GET_INFO:
 		memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info));
@@ -736,7 +900,7 @@
 		u8 signal = 0xff - stv0299_readreg (i2c, 0x18);
 		u8 sync = stv0299_readreg (i2c, 0x1b);
 
-		dprintk ("VSTATUS: 0x%02x\n", sync);
+		dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
 
 		*status = 0;
 
@@ -759,8 +923,12 @@
 	}
 
         case FE_READ_BER:
+		if (stv0299_status == STATUS_BER) {
 		*((u32*) arg) = (stv0299_readreg (i2c, 0x1d) << 8)
 			       | stv0299_readreg (i2c, 0x1e);
+		} else {
+			*((u32*) arg) = 0;
+		}
 		break;
 
 	case FE_READ_SIGNAL_STRENGTH:
@@ -768,7 +936,7 @@
 		s32 signal =  0xffff - ((stv0299_readreg (i2c, 0x18) << 8)
 			               | stv0299_readreg (i2c, 0x19));
 
-		dprintk ("AGC2I: 0x%02x%02x, signal=0x%04x\n",
+		dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
 			 stv0299_readreg (i2c, 0x18),
 			 stv0299_readreg (i2c, 0x19), (int) signal);
 
@@ -787,18 +955,25 @@
 		break;
 	}
 	case FE_READ_UNCORRECTED_BLOCKS: 
-		*((u32*) arg) = 0;    /* the stv0299 can't measure BER and */
-		return -EOPNOTSUPP;   /* errors at the same time.... */
+		if (stv0299_status == STATUS_UCBLOCKS) {
+			*((u32*) arg) = (stv0299_readreg (i2c, 0x1d) << 8)
+			               | stv0299_readreg (i2c, 0x1e);
+		} else {
+			*((u32*) arg) = 0;
+		}
+		break;
 
         case FE_SET_FRONTEND:
         {
 		struct dvb_frontend_parameters *p = arg;
 
+		dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
+
 		pll_set_tv_freq (i2c, p->frequency, tuner_type,
 				 p->u.qpsk.symbol_rate);
 
                 stv0299_set_FEC (i2c, p->u.qpsk.fec_inner);
-                stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate);
+                stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, tuner_type);
 		stv0299_writereg (i2c, 0x22, 0x00);
 		stv0299_writereg (i2c, 0x23, 0x00);
 		stv0299_readreg (i2c, 0x23);
@@ -859,6 +1034,8 @@
 
 static long probe_tuner (struct dvb_i2c_bus *i2c)
 {
+	struct dvb_adapter * adapter = (struct dvb_adapter *) i2c->adapter;
+
         /* read the status register of TSA5059 */
 	u8 rpt[] = { 0x05, 0xb5 };
         u8 stat [] = { 0 };
@@ -875,6 +1052,17 @@
 	stv0299_writereg (i2c, 0x02, 0x30);
 	stv0299_writereg (i2c, 0x03, 0x00);
 
+
+	printk ("%s: try to attach to %s\n", __FUNCTION__, adapter->name);
+
+	if ( strcmp(adapter->name, "Technisat SkyStar2 driver") == 0 )
+	{
+	    printk ("%s: setup for tuner Samsung TBMU24112IMB\n", __FILE__);
+
+    	    return SAMSUNG_TBMU24112IMB;
+	}
+
+
 	if ((ret = i2c->xfer(i2c, msg1, 2)) == 2) {
 		printk ("%s: setup for tuner SU1278/SH\n", __FILE__);
 		return PHILIPS_SU1278SH;
@@ -961,3 +1148,5 @@
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, Andreas Oberritter");
 MODULE_LICENSE("GPL");
 
+MODULE_PARM(stv0299_status, "i");
+MODULE_PARM_DESC(stv0299_status, "Which status value to support (0: BER, 1: UCBLOCKS)");
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/tda1004x.c linux-2.6.0-p/drivers/media/dvb/frontends/tda1004x.c
--- linux-2.6.0/drivers/media/dvb/frontends/tda1004x.c	2003-12-18 03:57:59.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/tda1004x.c	2003-11-12 12:34:57.000000000 +0100
@@ -108,7 +108,7 @@
 	.frequency_min = 51000000,
 	.frequency_max = 858000000,
 	.frequency_stepsize = 166667,
-	.caps = FE_CAN_INVERSION_AUTO |
+	.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_QAM_AUTO |
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/frontends/ves1820.c linux-2.6.0-p/drivers/media/dvb/frontends/ves1820.c
--- linux-2.6.0/drivers/media/dvb/frontends/ves1820.c	2003-12-18 03:58:50.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/frontends/ves1820.c	2003-12-08 16:19:00.000000000 +0100
@@ -19,6 +19,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */    
 
+#include <linux/config.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -70,7 +72,18 @@
 #define GET_TUNER(data) ((u8) (((long) data >> 16) & 0xff))
 #define GET_DEMOD_ADDR(data) ((u8) (((long) data >> 24) & 0xff))
 
+#if defined(CONFIG_DBOX2)
+#define XIN 69600000UL
+#define DISABLE_INVERSION(reg0)		do { reg0 &= ~0x20; } while (0)
+#define ENABLE_INVERSION(reg0)		do { reg0 |= 0x20; } while (0)
+#define HAS_INVERSION(reg0)		(reg0 & 0x20)
+#else	/* PCI cards */
 #define XIN 57840000UL
+#define DISABLE_INVERSION(reg0)		do { reg0 |= 0x20; } while (0)
+#define ENABLE_INVERSION(reg0)		do { reg0 &= ~0x20; } while (0)
+#define HAS_INVERSION(reg0)		(!(reg0 & 0x20))
+#endif
+
 #define FIN (XIN >> 4)
 
 
@@ -209,9 +222,9 @@
 	reg0 |= GET_REG0(fe->data) & 0x62;
 	
 	if (INVERSION_ON == inversion)
-		reg0 &= ~0x20;
+		ENABLE_INVERSION(reg0);
 	else if (INVERSION_OFF == inversion)
-		reg0 |= 0x20;
+		DISABLE_INVERSION(reg0);
 	
 	ves1820_writereg (fe, 0x00, reg0 & 0xfe);
         ves1820_writereg (fe, 0x00, reg0 | 0x01);
@@ -220,7 +233,7 @@
 	 *  check lock and toggle inversion bit if required...
 	 */
 	if (INVERSION_AUTO == inversion && !(ves1820_readreg (fe, 0x11) & 0x08)) {
-		dvb_delay(10);
+		mdelay(30);
 		if (!(ves1820_readreg (fe, 0x11) & 0x08)) {
 			reg0 ^= 0x20;
 			ves1820_writereg (fe, 0x00, reg0 & 0xfe);
@@ -242,6 +255,10 @@
 
         ves1820_writereg (fe, 0, 0);
 
+#if defined(CONFIG_DBOX2)
+	ves1820_inittab[2] &= ~0x08;
+#endif
+
 	for (i=0; i<53; i++)
                 ves1820_writereg (fe, i, ves1820_inittab[i]);
 
@@ -330,6 +347,10 @@
 
 	ves1820_setup_reg0 (fe, reg0x00[real_qam], p->inversion);
 
+	/* yes, this speeds things up: userspace reports lock in about 8 ms
+	   instead of 500 to 1200 ms after calling FE_SET_FRONTEND. */
+	mdelay(30);
+
 	return 0;
 }
 
@@ -419,14 +440,14 @@
 					fe->i2c->adapter->num, afc,
 				-((s32)(p->u.qam.symbol_rate >> 3) * afc >> 7));
 
-		p->inversion = reg0 & 0x20 ? INVERSION_OFF : INVERSION_ON;
+		p->inversion = HAS_INVERSION(reg0) ? INVERSION_ON : INVERSION_OFF;
 		p->u.qam.modulation = ((reg0 >> 2) & 7) + QAM_16;
 
 		p->u.qam.fec_inner = FEC_NONE;
 
 		p->frequency = ((p->frequency + 31250) / 62500) * 62500;
-		// To prevent overflow, shift symbol rate first a
-		// couple of bits.
+		/* To prevent overflow, shift symbol rate first a
+		   couple of bits. */
 		p->frequency -= (s32)(p->u.qam.symbol_rate >> 3) * afc >> 7;
 		break;
 	}
@@ -462,8 +483,6 @@
 		printk ("DVB: VES1820(%d): setup for tuner sp5659c\n", i2c->adapter->num);
 	} else {
 		type = -1;
-		printk ("DVB: VES1820(%d): unknown PLL, "
-			"please report to <linuxdvb@linuxtv.org>!!\n", i2c->adapter->num);
 	}
 
 	return type;
@@ -477,13 +496,11 @@
 	struct i2c_msg msg [] = { { .addr = 0x50, .flags = 0, .buf = &b, .len = 1 },
 			 { .addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1 } };
 
-	i2c->xfer (i2c, msg, 2);
+	if ((i2c->xfer(i2c, msg, 2) != 2) || (pwm == 0xff))
+		pwm = 0x48;
 
 	printk("DVB: VES1820(%d): pwm=0x%02x\n", i2c->adapter->num, pwm);
 
-	if (pwm == 0xff)
-		pwm = 0x48;
-
 	return pwm;
 }
 
@@ -516,8 +533,7 @@
 	if ((demod_addr = probe_demod_addr(i2c)) < 0)
 		return -ENODEV;
 
-	if ((tuner_type = probe_tuner(i2c)) < 0)
-		return -ENODEV;
+	tuner_type = probe_tuner(i2c);
 
 	if ((i2c->adapter->num < MAX_UNITS) && pwm[i2c->adapter->num] != -1) {
 		printk("DVB: VES1820(%d): pwm=0x%02x (user specified)\n",


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 8/12] Add firmware loading support to av7110 driver
  2003-12-19 12:28             ` [PATCH 7/12] Update av7110 driver Michael Hunold
@ 2003-12-19 12:28               ` Michael Hunold
  2003-12-19 12:28                 ` [PATCH 9/12] Update TTUSB DEC driver Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - use new firmware_class firmware loading facilities in dvb-ttpci/av7110 driver
--- linux-2.6.0-test11-bk8/drivers/media/dvb/ttpci/av7110.c.orig	2003-12-10 10:28:31.000000000 +0100
+++ linux-2.6.0-test11-bk8/drivers/media/dvb/ttpci/av7110.c	2003-12-11 12:06:18.000000000 +0100
@@ -60,6 +60,8 @@
 #include <linux/inetdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/firmware.h>
+#include <linux/crc32.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -1971,8 +1973,6 @@ static u8 bootcode[] = {
         0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00,
 };
 
-#include "av7110_firm.h"
-
 static int bootarm(struct av7110 *av7110)
 {
 	struct saa7146_dev *dev= av7110->dev;
@@ -2025,7 +2025,7 @@ static int bootarm(struct av7110 *av7110
         
         DEB_D(("bootarm: load dram code\n"));
 
-	if (load_dram(av7110, (u32 *)Root, sizeof(Root))<0)
+	if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root)<0)
 		return -1;
 
 	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
@@ -2033,7 +2033,7 @@ static int bootarm(struct av7110 *av7110
         
         DEB_D(("bootarm: load dpram code\n"));
 
-	mwdebi(av7110, DEBISWAB, DPRAM_BASE, Dpram, sizeof(Dpram));
+	mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
 
 	wait_for_debi_done(av7110);
 
@@ -4502,22 +4502,91 @@ static struct saa7146_ext_vv av7110_vv_d
 
 static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext)
 {
+	const struct firmware *fw;
 	struct av7110 *av7110 = NULL;
 	int ret = 0;
-	
+	u32 crc = 0, len = 0;
+	unsigned char *ptr;
+		
+	DEB_EE(("dev: %p, av7110: %p\n",dev,av7110));
+
+	/* request the av7110 firmware, this will block until someone uploads it */
+	ret = request_firmware(&fw, "dvb-ttpci-01.fw", &dev->pci->dev);
+	if ( 0 != ret ) {
+		printk("dvb-ttpci: cannot request firmware!\n");
+		return -EINVAL;
+	}
+
+	if (fw->size <= 200000) {
+		printk("dvb-ttpci: this firmware is way too small.\n");
+		return -EINVAL;
+	}
+
+	/* prepare the av7110 device struct */
 	if (!(av7110 = kmalloc (sizeof (struct av7110), GFP_KERNEL))) {
 		printk ("%s: out of memory!\n", __FUNCTION__);
 		return -ENOMEM;
 	}
-
 	memset(av7110, 0, sizeof(struct av7110));
+	
+	/* check if the firmware is available */
+	av7110->bin_fw = (unsigned char*)vmalloc(fw->size);
+	if (NULL == av7110->bin_fw) {
+		DEB_D(("out of memory\n"));
+		kfree(av7110);
+		return -ENOMEM;
+	}
+	memcpy(av7110->bin_fw, fw->data, fw->size);
+	av7110->size_fw = fw->size;
 
+	/* check for firmware magic */
+	ptr = av7110->bin_fw;
+	if (ptr[0] != 'A' || ptr[1] != 'V' || 
+	    ptr[2] != 'F' || ptr[3] != 'W') {
+		printk("dvb-ttpci: this is not an av7110 firmware\n");
+		goto fw_error;
+	}
+	ptr += 4;
+
+	/* check dpram file */
+	crc = ntohl(*(u32*)ptr);
+	ptr += 4;
+	len = ntohl(*(u32*)ptr);
+	ptr += 4;
+	if (len >= 512) {
+		printk("dvb-ttpci: dpram file is way to big.\n");
+		goto fw_error;
+	}
+	if( crc != crc32_le(0,ptr,len)) {
+		printk("dvb-ttpci: crc32 of dpram file does not match.\n");
+		goto fw_error;
+	}
+	av7110->bin_dpram = ptr;
+	av7110->size_dpram = len;
+	ptr += len;
+	
+	/* check root file */
+	crc = ntohl(*(u32*)ptr);
+	ptr += 4;
+	len = ntohl(*(u32*)ptr);
+	ptr += 4;
+	
+	if (len <= 200000 || len >= 300000 || len > ((av7110->bin_fw+av7110->size_fw)-ptr) ) {
+		printk("dvb-ttpci: root file has strange size (%d). aborting.\n",len);
+		goto fw_error;
+	}
+	if( crc != crc32_le(0,ptr,len)) {
+		printk("dvb-ttpci: crc32 of dpram file does not match.\n");
+		goto fw_error;
+	}
+	av7110->bin_root = ptr;
+	av7110->size_root = len;
+	
+	/* go on with regular device initialization */
 	av7110->card_name = (char*)pci_ext->ext_priv;
+	av7110->dev=(struct saa7146_dev *)dev;
 	(struct av7110*)dev->ext_priv = av7110;
 
-	DEB_EE(("dev: %p, av7110: %p\n",dev,av7110));
-
-	av7110->dev=(struct saa7146_dev *)dev;
 	dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name);
 
 	/* the Siemens DVB needs this if you want to have the i2c chips
@@ -4758,6 +4827,7 @@ static int av7110_attach (struct saa7146
 	}	
 
 	printk(KERN_INFO "av7110: found av7110-%d.\n",av7110_num);
+	av7110->device_initialized = 1;
 	av7110_num++;
         return 0;
 
@@ -4781,12 +4851,20 @@ err:
 	dvb_unregister_adapter (av7110->dvb_adapter);
 
 	return ret;
+fw_error:
+	vfree(av7110->bin_fw);
+	kfree(av7110);
+	return -EINVAL;
 }
 
 static int av7110_detach (struct saa7146_dev* saa)
 {
 	struct av7110 *av7110 = (struct av7110*)saa->ext_priv;
 	DEB_EE(("av7110: %p\n",av7110));
+	
+	if( 0 == av7110->device_initialized ) {
+		return 0;
+	}
 
 	saa7146_unregister_device(&av7110->v4l_dev, saa);
 	if (2 == av7110->has_analog_tuner) {
@@ -4817,11 +4895,13 @@ static int av7110_detach (struct saa7146
 	dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id);
 	dvb_unregister_adapter (av7110->dvb_adapter);
 
+	av7110_num--;
+	if (NULL != av7110->bin_fw ) {
+		vfree(av7110->bin_fw);
+	}
 	kfree (av7110);
-
 	saa->ext_priv = NULL;
-	av7110_num--;
-	
+
 	return 0;
 }
 
--- linux-2.6.0-test11-bk8/drivers/media/dvb/ttpci/av7110.h.orig	2003-10-15 13:18:08.000000000 +0200
+++ linux-2.6.0-test11-bk8/drivers/media/dvb/ttpci/av7110.h	2003-12-11 12:05:05.000000000 +0100
@@ -1,8 +1,6 @@
 #ifndef _AV7110_H_
 #define _AV7110_H_
 
-#define DVB_FIRM_PATH "/lib/DVB/"
-
 #include <linux/interrupt.h>
 #include <linux/socket.h>
 #include <linux/netdevice.h>
@@ -545,6 +543,18 @@ struct av7110 {
         int                 dsp_dev;
 
         u32                 ir_config;
+	
+	/* firmware stuff */
+	unsigned int device_initialized;
+
+	unsigned char *bin_fw;
+	unsigned long size_fw;
+
+	unsigned char *bin_dpram;
+	unsigned long size_dpram;
+
+	unsigned char *bin_root;
+	unsigned long size_root;
 };
 
 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 7/12] Update av7110 driver
  2003-12-19 12:28           ` [PATCH 6/12] Update DVB frontend drivers Michael Hunold
@ 2003-12-19 12:28             ` Michael Hunold
  2003-12-19 12:28               ` [PATCH 8/12] Add firmware loading support to " Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - av7110: follow changes in saa7146_core regarding saa7146_set_gpio() and saa7146_wait_for_debi_done() function
DVB: - av7110: increased I2C speed to 275 kHz,  follow introduction of SAA7146_I2C_SHORT_DELAY flag to speed up I2C access
DVB: - budget: make budget-ci use this gpio function and the new wait_...() function, this fixes BORROWED_FROM_AV7110_H_BUT_REALLY_BELONGS_IN_SAA7146_DEFS_H remark
DVB: - budget: use alternative values for BRS setup on budget cards (by Rober Schlabbach)
DVB: - budget: remote control table should be filled completely. at least populate the entries that come with the standard Hauppauge RC (Jamie Honan)
DVB: - ttpci-eeprom: add proper MODULE_LICENSE("GPL") so we don't taint the kernel anymore
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/ttpci/av7110.c linux-2.6.0-p/drivers/media/dvb/ttpci/av7110.c
--- linux-2.6.0/drivers/media/dvb/ttpci/av7110.c	2003-12-18 03:59:05.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/ttpci/av7110.c	2003-12-10 13:50:16.000000000 +0100
@@ -35,7 +35,6 @@
 
 #define __KERNEL_SYSCALLS__
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
@@ -43,7 +42,6 @@
 #include <linux/poll.h>
 #include <linux/unistd.h>
 #include <linux/byteorder/swabb.h>
-#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <stdarg.h>
 
@@ -55,10 +53,8 @@
 #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>
@@ -108,6 +105,7 @@
 static int pids_off;
 static int adac=DVB_ADAC_TI;
 static int hw_sections = 1;
+static int rgb_on = 0;
 
 int av7110_num = 0;
 
@@ -118,42 +116,12 @@
  * DEBI functions
  ****************************************************************************/
 
+#define wait_for_debi_done(x) \
+       saa7146_wait_for_debi_done(x->dev) \
+
 /* This DEBI code is based on the Stradis driver 
    by Nathan Laredo <laredo@gnu.org> */
 
-static int wait_for_debi_done(struct av7110 *av7110)
-{
-	struct saa7146_dev *dev = av7110->dev;
-	int start;
-
-	/* wait for registers to be programmed */
-	start = jiffies;
-	while (1) {
-                if (saa7146_read(dev, MC2) & 2)
-                        break;
-		if (jiffies-start > HZ/20) {
-			printk ("%s: timed out while waiting for registers "
-				"getting programmed\n", __FUNCTION__);
-			return -ETIMEDOUT;
-		}
-	}
-
-	/* wait for transfer to complete */
-	start = jiffies;
-	while (1) {
-		if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
-			break;
-		saa7146_read(dev, MC2);
-		if (jiffies-start > HZ/4) {
-			printk ("%s: timed out while waiting for transfer "
-				"completion\n", __FUNCTION__);
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
 static int debiwrite(struct av7110 *av7110, u32 config, 
                      int addr, u32 val, int count)
 {
@@ -375,7 +344,7 @@
 {
         struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) p2t->priv;
 
-	DEB_EE(("struct dvb_filter_pes2ts:%p\n",p2t));
+//	DEB_EE(("struct dvb_filter_pes2ts:%p\n",p2t));
 
         if (!(dvbdmxfeed->ts_type & TS_PACKET)) 
                 return 0;
@@ -385,14 +354,14 @@
                 return dvbdmxfeed->cb.ts(buf, len, 0, 0, 
                                          &dvbdmxfeed->feed.ts, DMX_OK); 
         else
-                return dvb_filter_pes2ts(p2t, buf, len);
+                return dvb_filter_pes2ts(p2t, buf, len, 1);
 }
 
 static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
 {
         struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) priv;
 
-	DEB_EE(("dvb_demux_feed:%p\n",dvbdmxfeed));
+//	DEB_EE(("dvb_demux_feed:%p\n",dvbdmxfeed));
         
         dvbdmxfeed->cb.ts(data, 188, 0, 0,
                           &dvbdmxfeed->feed.ts,
@@ -886,10 +855,10 @@
         txbuf=irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
         len=(av7110->debilen+3)&(~3);
 
-        DEB_D(("GPIO0 irq %d %d\n", av7110->debitype, av7110->debilen));
+//        DEB_D(("GPIO0 irq %d %d\n", av7110->debitype, av7110->debilen));
         print_time("gpio");
 
-        DEB_D(("GPIO0 irq %02x\n", av7110->debitype&0xff));        
+//       DEB_D(("GPIO0 irq %02x\n", av7110->debitype&0xff));        
         switch (av7110->debitype&0xff) {
 
         case DATA_TS_PLAY:
@@ -2706,9 +2675,9 @@
 	buf[1] = div & 0xff;
 	buf[2] = 0x8e;
 
-	if (freq < (u32) (16*168.25) ) 
+	if (freq < (u32) 16*168.25 )
 		config = 0xa0;
-	else if (freq < (u32) (16*447.25)) 
+	else if (freq < (u32) 16*447.25)
 		config = 0x90;
 	else
 		config = 0x30;
@@ -4294,8 +4263,10 @@
                         av7110->pids[DMX_PES_TELETEXT], 0, 
                         av7110->pids[DMX_PES_PCR]);
         	outcom(av7110, COMTYPE_PIDFILTER, Scan, 0);
-	} else 
+	} else {
 		SetPIDs(av7110, 0, 0, 0, 0, 0);
+        	outcom(av7110, COMTYPE_PIDFILTER, FlushTSQueue, 0);
+	}
 
         up(&av7110->pid_mutex);
 }
@@ -4553,7 +4524,7 @@
 	   get recognized before the main driver is fully loaded */
 	saa7146_write(dev, GPIO_CTRL, 0x500000);
 
-	saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200);
+	saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
 
 	av7110->i2c_bus = dvb_register_i2c_bus (master_xfer, dev,
 						av7110->dvb_adapter, 0);
@@ -4571,7 +4542,7 @@
 
 	/* set dd1 stream a & b */
       	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
-	saa7146_write(dev, DD1_INIT, 0x02000000);
+	saa7146_write(dev, DD1_INIT, 0x03000000);
 	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 
 	/* upload all */
@@ -4729,7 +4700,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, 0x02000700);
+		saa7146_write(dev, DD1_INIT, 0x03000700);
 		saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 	}
 	else if (dev->pci->subsystem_vendor == 0x110a) {
@@ -4747,7 +4718,8 @@
 		// switch DVB SCART on
 		outcom(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
 		outcom(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
-		//saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
+		if (rgb_on)
+			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
 		//saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
 	}
 	
@@ -4858,7 +4830,7 @@
 {
 	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
 
-	DEB_INT(("dev: %p, av7110: %p\n",dev,av7110));
+//	DEB_INT(("dev: %p, av7110: %p\n",dev,av7110));
 
 	if (*isr & MASK_19)
 		tasklet_schedule (&av7110->debi_tasklet);
@@ -4887,7 +4859,7 @@
 static struct saa7146_standard analog_standard[] = {
 	{
 		.name	= "PAL", 	.id		= V4L2_STD_PAL_BG,
-		.v_offset	= 0x18,	.v_field 	= 288,		.v_calc	= 576,
+		.v_offset	= 0x18 /* 0 */ ,	.v_field 	= 288,		.v_calc	= 576,
 		.h_offset	= 0x08,	.h_pixels 	= 708,		.h_calc	= 709,
 		.v_max_out	= 576,	.h_max_out	= 768,
 	}, {
@@ -4975,7 +4947,7 @@
 	.inputs		= 1,
 	.audios 	= 1,
 	.capabilities	= 0,
-	.flags		= SAA7146_EXT_SWAP_ODD_EVEN,
+	.flags		= 0, 
 
 	.stds		= &standard[0],
 	.num_stds	= sizeof(standard)/sizeof(struct saa7146_standard),
@@ -5002,6 +4974,7 @@
 
 static struct saa7146_extension av7110_extension = {
 	.name		= "dvb\0",
+	.flags		= SAA7146_I2C_SHORT_DELAY,
 
 	.module		= THIS_MODULE,
 	.pci_tbl	= &pci_tbl[0],
@@ -5054,4 +5027,6 @@
 MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
 MODULE_PARM(hw_sections, "i");
 MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
-
+MODULE_PARM(rgb_on, "i");
+MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
+		" signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/ttpci/av7110.h linux-2.6.0-p/drivers/media/dvb/ttpci/av7110.h
--- linux-2.6.0/drivers/media/dvb/ttpci/av7110.h	2003-12-18 03:58:03.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/ttpci/av7110.h	2003-10-14 10:00:23.000000000 +0200
@@ -169,7 +169,8 @@
 	DelPIDFilter,
 	Scan,
 	SetDescr,
-        SetIR
+        SetIR,
+        FlushTSQueue
 };
 			
 enum av7110_mpeg_command {
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/ttpci/budget-ci.c linux-2.6.0-p/drivers/media/dvb/ttpci/budget-ci.c
--- linux-2.6.0/drivers/media/dvb/ttpci/budget-ci.c	2003-12-18 03:58:15.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/ttpci/budget-ci.c	2003-11-20 11:17:51.000000000 +0100
@@ -35,81 +35,26 @@
 #include <linux/interrupt.h>
 #include <linux/input.h>
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include "input_fake.h"
+#endif
+
+
+
 struct budget_ci {
 	struct budget budget;
 	struct input_dev input_dev;
 	struct tasklet_struct msp430_irq_tasklet;
 };
 
-
-
-#ifndef BORROWED_FROM_AV7110_H_BUT_REALLY_BELONGS_IN_SAA7146_DEFS_H
-
-#define DEBINOSWAP 0x000e0000
-#define GPIO_IRQHI 0x10
-#define GPIO_INPUT 0x00
-
-void gpio_set(struct saa7146_dev* saa, u8 pin, u8 data)
-{
-        u32 value = 0;
-
-        /* sanity check */
-        if(pin > 3)
-                return;
-
-        /* read old register contents */
-        value = saa7146_read(saa, GPIO_CTRL );
-
-        value &= ~(0xff << (8*pin));
-        value |= (data << (8*pin));
-
-        saa7146_write(saa, GPIO_CTRL, value);
-}
-
-
-
-static int wait_for_debi_done(struct saa7146_dev *saa)
-{
-	int start = jiffies;
-
-	/* wait for registers to be programmed */
-	while (1) {
-		if (saa7146_read(saa, MC2) & 2)
-			break;
-		if (jiffies - start > HZ / 20) {
-			printk ("DVB (%s): timed out while waiting"
-				" for registers getting programmed\n",
-				__FUNCTION__);
-			return -ETIMEDOUT;
-		}
-	}
-
-	/* wait for transfer to complete */
-	start = jiffies;
-	while (1) {
-		if (!(saa7146_read(saa, PSR) & SPCI_DEBI_S))
-			break;
-		saa7146_read(saa, MC2);
-		if (jiffies - start > HZ / 4) {
-			printk ("DVB (%s): timed out while waiting"
-				" for transfer completion\n",
-				__FUNCTION__);
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
-
-static u32 debiread (struct saa7146_dev *saa, u32 config, int addr, int count)
+static u32 budget_debiread4 (struct saa7146_dev *saa, u32 config, int addr, int count)
 {
 	u32 result = 0;
 
 	if (count > 4 || count <= 0)
 		return 0;
 
-	if (wait_for_debi_done(saa) < 0)
+	if (saa7146_wait_for_debi_done(saa) < 0)
 		return 0;
 
 	saa7146_write (saa, DEBI_COMMAND,
@@ -118,7 +63,7 @@
 	saa7146_write(saa, DEBI_CONFIG, config);
 	saa7146_write(saa, MC2, (2 << 16) | 2);
 
-	wait_for_debi_done(saa);
+	saa7146_wait_for_debi_done(saa);
 
 	result = saa7146_read(saa, DEBI_AD);
 	result &= (0xffffffffUL >> ((4 - count) * 8));
@@ -126,20 +71,6 @@
 	return result;
 }
 
-
-
-/* DEBI during interrupt */
-static inline u32 irdebi(struct saa7146_dev *saa, u32 config, int addr, u32 val, int count)
-{
-	u32 res;
-	res = debiread(saa, config, addr, count);
-	return res;
-}
-#endif
-
-
-
-
 /* from reading the following remotes:
    Zenith Universal 7 / TV Mode 807 / VCR Mode 837
    Hauppauge (from NOVA-CI-s box product)
@@ -150,7 +81,7 @@
 	KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
 	KEY_9,
 	KEY_ENTER,
-	0,
+	KEY_RED,
 	KEY_POWER,              /* RADIO on Hauppauge */
 	KEY_MUTE,
 	0,
@@ -162,11 +93,11 @@
 	0, 0, 0, 0, 0, 0, 0,
 	KEY_UP, KEY_DOWN,
 	KEY_OPTION,             /* RESERVED on Hauppauge */
-	0,
+	KEY_BREAK,
 	/* 0x2X */
 	KEY_CHANNELUP, KEY_CHANNELDOWN,
 	KEY_PREVIOUS,           /* Prev. Ch on Zenith, SOURCE on Hauppauge */
-	0, 0, 0,
+	0, KEY_RESTART, KEY_OK,
 	KEY_CYCLEWINDOWS,       /* MINIMIZE on Hauppauge */
 	0,
 	KEY_ENTER,              /* VCR mode on Zenith */
@@ -177,7 +108,7 @@
 	KEY_MENU,               /* FULL SCREEN on Hauppauge */
 	0,
 	/* 0x3X */
-	0,
+	KEY_SLOW,
 	KEY_PREVIOUS,           /* VCR mode on Zenith */
 	KEY_REWIND,
 	0,
@@ -189,7 +120,7 @@
 	KEY_C,
 	0,
 	KEY_EXIT,
-	0,
+	KEY_POWER2,
 	KEY_TUNER,              /* VCR mode on Zenith */
 	0,
 };
@@ -217,7 +148,7 @@
 	struct budget_ci *budget_ci = (struct budget_ci*) data;
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	struct input_dev *dev = &budget_ci->input_dev;
-	unsigned int code = irdebi(saa, DEBINOSWAP, 0x1234, 0, 2) >> 8;
+	unsigned int code = budget_debiread4(saa, DEBINOSWAP, 0x1234, 2) >> 8;
 
 	if (code & 0x40) {
 	        code &= 0x3f;
@@ -271,7 +202,7 @@
 
 	saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
 
-	gpio_set(saa, 3, GPIO_IRQHI);
+	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); 
 
 	return 0;
 }
@@ -283,8 +214,8 @@
 	struct input_dev *dev = &budget_ci->input_dev;
 
 	saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
-	gpio_set(saa, 3, GPIO_INPUT);
-	gpio_set(saa, 2, GPIO_INPUT);
+	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
+	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
 
 	if (del_timer(&dev->timer))
 		input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/ttpci/budget.h linux-2.6.0-p/drivers/media/dvb/ttpci/budget.h
--- linux-2.6.0/drivers/media/dvb/ttpci/budget.h	2003-12-18 03:58:57.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/ttpci/budget.h	2003-11-03 20:08:11.000000000 +0100
@@ -64,8 +64,8 @@
 	.ext_priv = &x_var ## _info, \
 	.ext = &budget_extension };
 
-#define TS_WIDTH  (4*188)
-#define TS_HEIGHT (1024/4)
+#define TS_WIDTH  (376)
+#define TS_HEIGHT (512)
 #define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
 #define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
 
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/ttpci/ttpci-eeprom.c linux-2.6.0-p/drivers/media/dvb/ttpci/ttpci-eeprom.c
--- linux-2.6.0/drivers/media/dvb/ttpci/ttpci-eeprom.c	2003-12-18 03:59:05.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/ttpci/ttpci-eeprom.c	2003-11-05 16:42:47.000000000 +0100
@@ -142,3 +142,9 @@
 }
 
 EXPORT_SYMBOL(ttpci_eeprom_parse_mac);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
+MODULE_DESCRIPTION("Decode dvb_net MAC address from EEPROM of PCI DVB cards "
+		"made by Siemens, Technotrend, Hauppauge");
+


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 9/12] Update TTUSB DEC driver
  2003-12-19 12:28               ` [PATCH 8/12] Add firmware loading support to " Michael Hunold
@ 2003-12-19 12:28                 ` Michael Hunold
  2003-12-19 12:28                   ` [PATCH 10/12] Cleanup patch to remove 2.4 crud Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - add support for the DEC3000-s (Alex Woods)
DVB: - use the hotplug firmware loader for 2.6 kernels instead of compiling the firmware into the module (Alex Woods)
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/ttusb-dec/Kconfig linux-2.6.0-p/drivers/media/dvb/ttusb-dec/Kconfig
--- linux-2.6.0/drivers/media/dvb/ttusb-dec/Kconfig	2003-12-18 03:58:17.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/ttusb-dec/Kconfig	2003-12-08 16:19:01.000000000 +0100
@@ -1,24 +1,26 @@
 config DVB_TTUSB_DEC
-	tristate "Technotrend/Hauppauge USB DEC2000-T devices"
-	depends on DVB_CORE && USB && !STANDALONE
+	tristate "Technotrend/Hauppauge USB DEC devices"
+	depends on DVB_CORE && USB && FW_LOADER
 	help
 	  Support for external USB adapters designed by Technotrend and
-	  produced by Hauppauge, shipped under the brand name 'DEC2000-T'.
+	  produced by Hauppauge, shipped under the brand name 'DEC2000-t'
+	  and 'DEC3000-s'.
 
           Even if these devices have a MPEG decoder built in, they transmit
 	  only compressed MPEG data over the USB bus, so you need
 	  an external software decoder to watch TV on your computer.	  
 
-	  Say Y if you own such a device and want to use it.
+	  The DEC devices require firmware in order to boot into a mode in
+	  which they are slaves to the PC.  See
+	  linux/Documentation/dvb/FIRMWARE for details.
+
+	  The firmware can be obtained and put into the default
+	  locations as follows:
 
-config DVB_TTUSB_DEC_FIRMWARE_FILE
-	string "Full pathname of dec2000t.bin firmware file"
-	depends on DVB_TTUSB_DEC
-	default "/etc/dvb/dec2000t.bin"
-	help
-	  The DEC2000-T requires a firmware in order to boot into a mode in
-	  which it is a slave to the PC.  The firmware file can obtained as
-	  follows:
 	    wget http://hauppauge.lightpath.net/de/dec215a.exe
 	    unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_T.bin
-	    mv STB_PC_T.bin /etc/dvb/dec2000t.bin
+	    mv STB_PC_T.bin /usr/lib/hotplug/firmware/dec2000t.bin
+	    unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_S.bin
+	    mv STB_PC_S.bin /usr/lib/hotplug/firmware/dec3000s.bin
+
+	  Say Y if you own such a device and want to use it.
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/ttusb-dec/Makefile linux-2.6.0-p/drivers/media/dvb/ttusb-dec/Makefile
--- linux-2.6.0/drivers/media/dvb/ttusb-dec/Makefile	2003-12-18 03:58:56.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/ttusb-dec/Makefile	2003-12-08 16:19:01.000000000 +0100
@@ -1,11 +1,3 @@
-
-obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o dec2000_frontend.o
+obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
-
-host-progs	:= fdump
-
-$(obj)/ttusb_dec.o: $(obj)/dsp_dec2000.h
-
-$(obj)/dsp_dec2000.h: $(patsubst "%", %, $(CONFIG_DVB_TTUSB_DEC_FIRMWARE_FILE)) $(obj)/fdump
-	$(obj)/fdump $< dsp_dec2000 > $@
diff -uNrwB --new-file linux-2.6.0/drivers/media/dvb/ttusb-dec/ttusb_dec.c linux-2.6.0-p/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- linux-2.6.0/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2003-12-18 03:59:37.000000000 +0100
+++ linux-2.6.0-p/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2003-12-10 13:50:16.000000000 +0100
@@ -19,19 +19,137 @@
  *
  */
 
-#include <linux/version.h>
+#include <asm/semaphore.h>
+#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <linux/usb.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/firmware.h>
+#endif
 
-#include "ttusb_dec.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_i2c.h"
+#include "dvb_filter.h"
 #include "dvb_frontend.h"
+#include "dvb_net.h"
 
 static int debug = 0;
 
 #define dprintk	if (debug) printk
 
+#define DRIVER_NAME		"TechnoTrend/Hauppauge DEC USB"
+
+#define COMMAND_PIPE		0x03
+#define RESULT_PIPE		0x84
+#define STREAM_PIPE		0x88
+
+#define COMMAND_PACKET_SIZE	0x3c
+#define ARM_PACKET_SIZE		0x1000
+
+#define ISO_BUF_COUNT		0x04
+#define FRAMES_PER_ISO_BUF	0x04
+#define ISO_FRAME_SIZE		0x0380
+
+#define	MAX_AV_PES_LENGTH	6144
+
+#define LOF_HI			10600000
+#define LOF_LO			9750000
+
+enum ttusb_model {
+	TTUSB_DEC2000T,
+	TTUSB_DEC3000S
+};
+
+struct ttusb_dec {
+	enum ttusb_model		model;
+	char				*model_name;
+	char				*firmware_name;
+
+	/* DVB bits */
+	struct dvb_adapter		*adapter;
+	struct dmxdev			dmxdev;
+	struct dvb_demux		demux;
+	struct dmx_frontend		frontend;
+	struct dvb_i2c_bus		i2c_bus;
+	struct dvb_net			dvb_net;
+	struct dvb_frontend_info	*frontend_info;
+	int (*frontend_ioctl) (struct dvb_frontend *, unsigned int, void *);
+
+	u16			pid[DMX_PES_OTHER];
+	int			hi_band;
+
+	/* USB bits */
+	struct usb_device	*udev;
+	u8			trans_count;
+	unsigned int		command_pipe;
+	unsigned int		result_pipe;
+	unsigned int		stream_pipe;
+	int			interface;
+	struct semaphore	usb_sem;
+
+	void			*iso_buffer;
+	dma_addr_t		iso_dma_handle;
+	struct urb		*iso_urb[ISO_BUF_COUNT];
+	int			iso_stream_count;
+	struct semaphore	iso_sem;
+
+	u8			av_pes[MAX_AV_PES_LENGTH + 4];
+	int			av_pes_state;
+	int			av_pes_length;
+	int			av_pes_payload_length;
+
+	struct dvb_filter_pes2ts	a_pes2ts;
+	struct dvb_filter_pes2ts	v_pes2ts;
+
+	u8			v_pes[16 + MAX_AV_PES_LENGTH];
+	int			v_pes_length;
+	int			v_pes_postbytes;
+
+	struct list_head	urb_frame_list;
+	struct tasklet_struct	urb_tasklet;
+	spinlock_t		urb_frame_list_lock;
+
+	int			active; /* Loaded successfully */
+};
+
+struct urb_frame {
+	u8			data[ISO_FRAME_SIZE];
+	int			length;
+	struct list_head	urb_frame_list;
+};
+
+static struct dvb_frontend_info dec2000t_frontend_info = {
+	.name			= "TechnoTrend/Hauppauge DEC2000-t Frontend",
+	.type			= FE_OFDM,
+	.frequency_min		= 51000000,
+	.frequency_max		= 858000000,
+	.frequency_stepsize	= 62500,
+	.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_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+		FE_CAN_HIERARCHY_AUTO,
+};
+
+static struct dvb_frontend_info dec3000s_frontend_info = {
+	.name			= "TechnoTrend/Hauppauge DEC3000-s Frontend",
+	.type			= FE_QPSK,
+	.frequency_min		= 950000,
+	.frequency_max		= 2150000,
+	.frequency_stepsize	= 125,
+	.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_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+		FE_CAN_HIERARCHY_AUTO,
+};
+
 static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
 				  int param_length, const u8 params[],
 				  int *result_length, u8 cmd_result[])
@@ -129,22 +247,8 @@
 				       ttusb_dec_av_pes2ts_cb, dec->demux.feed);
 		dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
 				       ttusb_dec_av_pes2ts_cb, dec->demux.feed);
-}
-
-static int ttusb_dec_i2c_master_xfer(struct dvb_i2c_bus *i2c,
-				     const struct i2c_msg msgs[], int num)
-{
-	int result, i;
-
-	dprintk("%s\n", __FUNCTION__);
-
-	for (i = 0; i < num; i++)
-		if ((result = ttusb_dec_send_command(i2c->data, msgs[i].addr,
-						     msgs[i].len, msgs[i].buf,
-						     NULL, NULL)))
-			return result;
-
-	return 0;
+	dec->v_pes_length = 0;
+	dec->v_pes_postbytes = 0;
 }
 
 static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes,
@@ -194,7 +298,8 @@
 				       &av_pes[12], prebytes);
 
 				dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
-						  dec->v_pes_length + prebytes);
+						  dec->v_pes_length + prebytes,
+						  1);
 			}
 
 			if (av_pes[5] & 0x10) {
@@ -239,13 +344,14 @@
 
 			if (postbytes == 0)
 				dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
-							  dec->v_pes_length);
+						  dec->v_pes_length, 1);
 
 			break;
 		}
 
 	case 0x02:		/* MainAudioStream */
-		dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 12);
+		dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 12,
+				  av_pes[5] & 0x10);
 		break;
 
 	default:
@@ -379,7 +485,11 @@
 		int i;
 
 		for (i = 0; i < FRAMES_PER_ISO_BUF; i++) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+			struct iso_packet_descriptor *d;
+#else
 			struct usb_iso_packet_descriptor *d;
+#endif
 			u8 *b;
 			int length;
 			struct urb_frame *frame;
@@ -432,9 +542,11 @@
 		urb->context = dec;
 		urb->complete = ttusb_dec_process_urb;
 		urb->pipe = dec->stream_pipe;
-		urb->transfer_flags = URB_ISO_ASAP;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+		urb->transfer_flags = URB_ISO_ASAP;
 		urb->interval = 1;
+#else
+		urb->transfer_flags = USB_ISO_ASAP;
 #endif
 		urb->number_of_packets = FRAMES_PER_ISO_BUF;
 		urb->transfer_buffer_length = ISO_FRAME_SIZE *
@@ -502,8 +614,12 @@
 		ttusb_dec_setup_urbs(dec);
 
 		for (i = 0; i < ISO_BUF_COUNT; i++) {
-			if ((result = usb_submit_urb(dec->iso_urb[i]
-						    , GFP_KERNEL))) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+			if ((result = usb_submit_urb(dec->iso_urb[i],
+						     GFP_ATOMIC))) {
+#else
+			if ((result = usb_submit_urb(dec->iso_urb[i]))) {
+#endif
 				printk("%s: failed urb submission %d: "
 				       "error %d\n", __FUNCTION__, i, result);
 
@@ -659,7 +775,11 @@
 	for (i = 0; i < ISO_BUF_COUNT; i++) {
 		struct urb *urb;
 
-		if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_KERNEL))) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+		if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) {
+#else
+		if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF))) {
+#endif
 			ttusb_dec_free_iso_urbs(dec);
 			return -ENOMEM;
 		}
@@ -711,20 +831,61 @@
 	ttusb_dec_alloc_iso_urbs(dec);
 }
 
-#include "dsp_dec2000.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include "dsp_dec2000t.h"
+#include "dsp_dec3000s.h"
+#endif
 
 static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 {
 	int i, j, actual_len, result, size, trans_count;
-	u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xc8, 0x61,
+	u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		    0x00 };
 	u8 b1[] = { 0x61 };
 	u8 b[ARM_PACKET_SIZE];
-	u32 dsp_length = htonl(sizeof(dsp_dec2000));
+	u8 *firmware = NULL;
+	size_t firmware_size = 0;
+	u32 firmware_csum = 0;
+	u32 firmware_size_nl;
+	u32 firmware_csum_nl;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	const struct firmware *fw_entry = NULL;
+#endif
 
 	dprintk("%s\n", __FUNCTION__);
 
-	memcpy(b0, &dsp_length, 4);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
+		printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
+		       __FUNCTION__, dec->firmware_name);
+		return 1;
+	}
+
+	firmware = fw_entry->data;
+	firmware_size = fw_entry->size;
+#endif
+	switch (dec->model) {
+		case TTUSB_DEC2000T:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+			firmware = &dsp_dec2000t[0];
+			firmware_size = sizeof(dsp_dec2000t);
+#endif
+			firmware_csum = 0x1bc86100;
+			break;
+
+		case TTUSB_DEC3000S:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+			firmware = &dsp_dec3000s[0];
+			firmware_size = sizeof(dsp_dec3000s);
+#endif
+			firmware_csum = 0x00000000;
+			break;
+	}
+
+	firmware_size_nl = htonl(firmware_size);
+	memcpy(b0, &firmware_size_nl, 4);
+	firmware_csum_nl = htonl(firmware_csum);
+	memcpy(&b0[6], &firmware_csum_nl, 4);
 
 	result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
 
@@ -734,8 +895,8 @@
 	trans_count = 0;
 	j = 0;
 
-	for (i = 0; i < sizeof(dsp_dec2000); i += COMMAND_PACKET_SIZE) {
-		size = sizeof(dsp_dec2000) - i;
+	for (i = 0; i < firmware_size; i += COMMAND_PACKET_SIZE) {
+		size = firmware_size - i;
 		if (size > COMMAND_PACKET_SIZE)
 			size = COMMAND_PACKET_SIZE;
 
@@ -743,7 +904,7 @@
 		b[j + 1] = trans_count++;
 		b[j + 2] = 0xf0;
 		b[j + 3] = size;
-		memcpy(&b[j + 4], &dsp_dec2000[i], size);
+		memcpy(&b[j + 4], &firmware[i], size);
 
 		j += COMMAND_PACKET_SIZE + 4;
 
@@ -764,7 +925,7 @@
 	return result;
 }
 
-static void ttusb_dec_init_stb(struct ttusb_dec *dec)
+static int ttusb_dec_init_stb(struct ttusb_dec *dec)
 {
 	u8 c[COMMAND_PACKET_SIZE];
 	int c_length;
@@ -774,9 +935,14 @@
 
 	result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
 
-	if (!result)
+	if (!result) {
 		if (c_length != 0x0c || (c_length == 0x0c && c[9] != 0x63))
-			ttusb_dec_boot_dsp(dec);
+			return ttusb_dec_boot_dsp(dec);
+		else
+			return 0;
+	}
+	else
+		return result;
 }
 
 static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
@@ -785,22 +951,13 @@
 
 	dprintk("%s\n", __FUNCTION__);
 
-	if ((result = dvb_register_adapter(&dec->adapter, "dec2000")) < 0) {
+	if ((result = dvb_register_adapter(&dec->adapter, dec->model_name)) < 0) {
 		printk("%s: dvb_register_adapter failed: error %d\n",
 		       __FUNCTION__, result);
 
 		return result;
 	}
 
-	if (!(dec->i2c_bus = dvb_register_i2c_bus(ttusb_dec_i2c_master_xfer,
-						  dec, dec->adapter, 0))) {
-		printk("%s: dvb_register_i2c_bus failed\n", __FUNCTION__);
-
-		dvb_unregister_adapter(dec->adapter);
-
-		return -ENOMEM;
-	}
-
 	dec->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
 
 	dec->demux.priv = (void *)dec;
@@ -814,8 +971,6 @@
 		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
 		       result);
 
-		dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
-				       0);
 		dvb_unregister_adapter(dec->adapter);
 
 		return result;
@@ -830,8 +985,6 @@
 		       __FUNCTION__, result);
 
 		dvb_dmx_release(&dec->demux);
-		dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
-				       0);
 		dvb_unregister_adapter(dec->adapter);
 
 		return result;
@@ -846,8 +999,6 @@
 
 		dvb_dmxdev_release(&dec->dmxdev);
 		dvb_dmx_release(&dec->demux);
-		dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
-				       0);
 		dvb_unregister_adapter(dec->adapter);
 
 		return result;
@@ -861,8 +1012,6 @@
 		dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
 		dvb_dmxdev_release(&dec->dmxdev);
 		dvb_dmx_release(&dec->demux);
-		dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
-				       0);
 		dvb_unregister_adapter(dec->adapter);
 
 		return result;
@@ -882,7 +1031,6 @@
 	dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
 	dvb_dmxdev_release(&dec->dmxdev);
 	dvb_dmx_release(&dec->demux);
-	dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter, 0);
 	dvb_unregister_adapter(dec->adapter);
 }
 
@@ -914,6 +1062,257 @@
 	}
 }
 
+static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
+				  void *arg)
+{
+	struct ttusb_dec *dec = fe->data;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	switch (cmd) {
+
+	case FE_GET_INFO:
+		dprintk("%s: FE_GET_INFO\n", __FUNCTION__);
+		memcpy(arg, dec->frontend_info,
+		       sizeof (struct dvb_frontend_info));
+		break;
+
+	case FE_READ_STATUS: {
+			fe_status_t *status = (fe_status_t *)arg;
+			dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);
+			*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+				  FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+			break;
+		}
+
+	case FE_READ_BER: {
+			u32 *ber = (u32 *)arg;
+			dprintk("%s: FE_READ_BER\n", __FUNCTION__);
+			*ber = 0;
+			return -ENOSYS;
+			break;
+		}
+
+	case FE_READ_SIGNAL_STRENGTH: {
+			dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);
+			*(s32 *)arg = 0xFF;
+			return -ENOSYS;
+			break;
+		}
+
+	case FE_READ_SNR:
+		dprintk("%s: FE_READ_SNR\n", __FUNCTION__);
+		*(s32 *)arg = 0;
+		return -ENOSYS;
+		break;
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);
+		*(u32 *)arg = 0;
+		return -ENOSYS;
+		break;
+
+	case FE_SET_FRONTEND: {
+			struct dvb_frontend_parameters *p =
+				(struct dvb_frontend_parameters *)arg;
+			u8 b[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+				   0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+				   0x00, 0xff, 0x00, 0x00, 0x00, 0xff };
+			u32 freq;
+
+			dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);
+
+			dprintk("            frequency->%d\n", p->frequency);
+			dprintk("            symbol_rate->%d\n",
+				p->u.qam.symbol_rate);
+			dprintk("            inversion->%d\n", p->inversion);
+
+			freq = htonl(p->frequency / 1000);
+			memcpy(&b[4], &freq, sizeof (u32));
+			ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL);
+
+			break;
+		}
+
+	case FE_GET_FRONTEND:
+		dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);
+		break;
+
+	case FE_SLEEP:
+		dprintk("%s: FE_SLEEP\n", __FUNCTION__);
+		return -ENOSYS;
+		break;
+
+	case FE_INIT:
+		dprintk("%s: FE_INIT\n", __FUNCTION__);
+		break;
+
+	case FE_RESET:
+		dprintk("%s: FE_RESET\n", __FUNCTION__);
+		break;
+
+	default:
+		dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);
+		return -EINVAL;
+
+	}
+
+	return 0;
+}
+
+static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
+				  void *arg)
+{
+	struct ttusb_dec *dec = fe->data;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	switch (cmd) {
+
+	case FE_GET_INFO:
+		dprintk("%s: FE_GET_INFO\n", __FUNCTION__);
+		memcpy(arg, dec->frontend_info,
+		       sizeof (struct dvb_frontend_info));
+		break;
+
+	case FE_READ_STATUS: {
+			fe_status_t *status = (fe_status_t *)arg;
+			dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);
+			*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+				  FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+			break;
+		}
+
+	case FE_READ_BER: {
+			u32 *ber = (u32 *)arg;
+			dprintk("%s: FE_READ_BER\n", __FUNCTION__);
+			*ber = 0;
+			return -ENOSYS;
+			break;
+		}
+
+	case FE_READ_SIGNAL_STRENGTH: {
+			dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);
+			*(s32 *)arg = 0xFF;
+			return -ENOSYS;
+			break;
+		}
+
+	case FE_READ_SNR:
+		dprintk("%s: FE_READ_SNR\n", __FUNCTION__);
+		*(s32 *)arg = 0;
+		return -ENOSYS;
+		break;
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);
+		*(u32 *)arg = 0;
+		return -ENOSYS;
+		break;
+
+	case FE_SET_FRONTEND: {
+			struct dvb_frontend_parameters *p =
+				(struct dvb_frontend_parameters *)arg;
+			u8 b[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+				   0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+				   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				   0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+				   0x00, 0x00, 0x00, 0x00, 0x00 };
+			u32 freq;
+			u32 sym_rate;
+			u32 band;
+
+
+			dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);
+
+			dprintk("            frequency->%d\n", p->frequency);
+			dprintk("            symbol_rate->%d\n",
+				p->u.qam.symbol_rate);
+			dprintk("            inversion->%d\n", p->inversion);
+
+			freq = htonl(p->frequency * 1000 + (dec->hi_band ? LOF_HI : LOF_LO));
+			memcpy(&b[4], &freq, sizeof(u32));
+			sym_rate = htonl(p->u.qam.symbol_rate);
+			memcpy(&b[12], &sym_rate, sizeof(u32));
+			band = htonl(dec->hi_band ? LOF_HI : LOF_LO);
+			memcpy(&b[24], &band, sizeof(u32));
+
+			ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL);
+
+			break;
+		}
+
+	case FE_GET_FRONTEND:
+		dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);
+		break;
+
+	case FE_SLEEP:
+		dprintk("%s: FE_SLEEP\n", __FUNCTION__);
+		return -ENOSYS;
+		break;
+
+	case FE_INIT:
+		dprintk("%s: FE_INIT\n", __FUNCTION__);
+		break;
+
+	case FE_RESET:
+		dprintk("%s: FE_RESET\n", __FUNCTION__);
+		break;
+
+	case FE_DISEQC_SEND_MASTER_CMD:
+		dprintk("%s: FE_DISEQC_SEND_MASTER_CMD\n", __FUNCTION__);
+		break;
+
+	case FE_DISEQC_SEND_BURST:
+		dprintk("%s: FE_DISEQC_SEND_BURST\n", __FUNCTION__);
+		break;
+
+	case FE_SET_TONE: {
+			fe_sec_tone_mode_t tone = (fe_sec_tone_mode_t)arg;
+			dprintk("%s: FE_SET_TONE\n", __FUNCTION__);
+			dec->hi_band = (SEC_TONE_ON == tone);
+			break;
+		}
+
+	case FE_SET_VOLTAGE:
+		dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
+		break;
+
+	default:
+		dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);
+		return -EINVAL;
+
+	}
+
+	return 0;
+}
+
+static void ttusb_dec_init_frontend(struct ttusb_dec *dec)
+{
+	dec->i2c_bus.adapter = dec->adapter;
+
+	switch (dec->model) {
+		case TTUSB_DEC2000T:
+			dec->frontend_info = &dec2000t_frontend_info;
+			dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;
+			break;
+
+		case TTUSB_DEC3000S:
+			dec->frontend_info = &dec3000s_frontend_info;
+			dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl;
+			break;
+	}
+
+	dvb_register_frontend(dec->frontend_ioctl, &dec->i2c_bus, (void *)dec,
+			      dec->frontend_info);
+}
+
+static void ttusb_dec_exit_frontend(struct ttusb_dec *dec)
+{
+	dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus);
+}
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum,
 			     const struct usb_device_id *id)
@@ -929,19 +1328,6 @@
 		printk("%s: couldn't allocate memory.\n", __FUNCTION__);
 		return NULL;
 	}
-
-	memset(dec, 0, sizeof(struct ttusb_dec));
-
-	dec->udev = udev;
-
-	ttusb_dec_init_usb(dec);
-	ttusb_dec_init_stb(dec);
-	ttusb_dec_init_dvb(dec);
-	ttusb_dec_init_v_pes(dec);
-	ttusb_dec_init_tasklet(dec);
-
-	return (void *)dec;
-}
 #else
 static int ttusb_dec_probe(struct usb_interface *intf,
 			   const struct usb_device_id *id)
@@ -958,22 +1344,47 @@
 		return -ENOMEM;
 	}
 
+	usb_set_intfdata(intf, (void *)dec);
+#endif
+
 	memset(dec, 0, sizeof(struct ttusb_dec));
 
+	switch (id->idProduct) {
+		case 0x1006:
+			dec->model = TTUSB_DEC3000S;
+			dec->model_name = "DEC3000-s";
+			dec->firmware_name = "dec3000s.bin";
+			break;
+
+		case 0x1008:
+			dec->model = TTUSB_DEC2000T;
+			dec->model_name = "DEC2000-t";
+			dec->firmware_name = "dec2000t.bin";
+			break;
+	}
+
 	dec->udev = udev;
 
 	ttusb_dec_init_usb(dec);
-	ttusb_dec_init_stb(dec);
+	if (ttusb_dec_init_stb(dec)) {
+		ttusb_dec_exit_usb(dec);
+		return 0;
+	}
 	ttusb_dec_init_dvb(dec);
+	ttusb_dec_init_frontend(dec);
 	ttusb_dec_init_v_pes(dec);
 	ttusb_dec_init_tasklet(dec);
 
-	usb_set_intfdata(intf, (void *)dec);
+	dec->active = 1;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	return (void *)dec;
+#else
 	ttusb_dec_set_streaming_interface(dec);
 
 	return 0;
-}
 #endif
+}
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static void ttusb_dec_disconnect(struct usb_device *udev, void *data)
@@ -989,17 +1400,20 @@
 
 	dprintk("%s\n", __FUNCTION__);
 
+	if (dec->active) {
 	ttusb_dec_exit_tasklet(dec);
 	ttusb_dec_exit_usb(dec);
+		ttusb_dec_exit_frontend(dec);
 	ttusb_dec_exit_dvb(dec);
+	}
 
 	kfree(dec);
 }
 
 static struct usb_device_id ttusb_dec_table[] = {
-	{USB_DEVICE(0x0b48, 0x1006)},	/* Unconfirmed */
-	{USB_DEVICE(0x0b48, 0x1007)},	/* Unconfirmed */
-	{USB_DEVICE(0x0b48, 0x1008)},	/* DEC 2000 t */
+	{USB_DEVICE(0x0b48, 0x1006)},	/* DEC3000-s */
+	/*{USB_DEVICE(0x0b48, 0x1007)},	   Unconfirmed */
+	{USB_DEVICE(0x0b48, 0x1008)},	/* DEC2000-t */
 	{}
 };
 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 10/12] Cleanup patch to remove 2.4 crud
  2003-12-19 12:28                 ` [PATCH 9/12] Update TTUSB DEC driver Michael Hunold
@ 2003-12-19 12:28                   ` Michael Hunold
  2003-12-19 12:28                     ` [PATCH 11/12] Firmware_class update Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - cleanup patch
 - remove various LINUX_VERSION_CODE code paths
 - fix compile bug in new bt8xx/Makefile
diff -uNrwB --new-file linux-2.6.0-p2/drivers/media/dvb/bt8xx/bt878.c linux-2.6.0-p3/drivers/media/dvb/bt8xx/bt878.c
--- linux-2.6.0-p2/drivers/media/dvb/bt8xx/bt878.c	2003-12-18 15:10:41.000000000 +0100
+++ linux-2.6.0-p3/drivers/media/dvb/bt8xx/bt878.c	2003-12-18 15:43:01.000000000 +0100
@@ -44,11 +44,7 @@
 #include "dmxdev.h"
 #include "dvbdev.h"
 #include "bt878.h"
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
 #include "dst-bt878.h"
-#else
-#include "../frontends/dst-bt878.h"
-#endif
 
 #include "dvb_functions.h"
 
diff -uNrwB --new-file linux-2.6.0-p2/drivers/media/dvb/ttpci/budget-ci.c linux-2.6.0-p3/drivers/media/dvb/ttpci/budget-ci.c
--- linux-2.6.0-p2/drivers/media/dvb/ttpci/budget-ci.c	2003-12-18 15:10:40.000000000 +0100
+++ linux-2.6.0-p3/drivers/media/dvb/ttpci/budget-ci.c	2003-12-18 15:43:12.000000000 +0100
@@ -35,12 +35,6 @@
 #include <linux/interrupt.h>
 #include <linux/input.h>
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include "input_fake.h"
-#endif
-
-
-
 struct budget_ci {
 	struct budget budget;
 	struct input_dev input_dev;
diff -uNrwB --new-file linux-2.6.0-p2/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c linux-2.6.0-p3/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
--- linux-2.6.0-p2/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c	2003-12-18 15:10:40.000000000 +0100
+++ linux-2.6.0-p3/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c	2003-12-18 15:43:27.000000000 +0100
@@ -742,11 +742,7 @@
 	}
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static void ttusb_iso_irq(struct urb *urb)
-#else
 static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs)
-#endif
 {
 	struct ttusb *ttusb = urb->context;
 
@@ -787,9 +783,7 @@
 			ttusb_process_frame(ttusb, data, len);
 		}
 	}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	usb_submit_urb(urb, GFP_ATOMIC);
-#endif
 }
 
 static void ttusb_free_iso_urbs(struct ttusb *ttusb)
@@ -879,13 +873,6 @@
 		}
 	}
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	for (i = 0; i < ISO_BUF_COUNT; i++) {
-		int next = (i + 1) % ISO_BUF_COUNT;
-		ttusb->iso_urb[i]->next = ttusb->iso_urb[next];
-	}
-#endif
-
 	for (i = 0; i < ISO_BUF_COUNT; i++) {
 		if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_KERNEL))) {
 			ttusb_stop_iso_xfer(ttusb);
@@ -1076,22 +1063,6 @@
 };
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static void *ttusb_probe(struct usb_device *udev, unsigned int ifnum,
-		  const struct usb_device_id *id)
-{
-	struct ttusb *ttusb;
-	int result, channel;
-
-	if (ifnum != 0)
-		return NULL;
-
-	dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
-
-	if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL)))
-		return NULL;
-
-#else
 static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *udev;
@@ -1105,8 +1076,6 @@
 	if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL)))
 		return -ENOMEM;
 
-#endif
-
 	memset(ttusb, 0, sizeof(struct ttusb));
 
 	for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel) {
@@ -1180,35 +1149,22 @@
 			   S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
 			   | S_IROTH | S_IWOTH, &stc_fops, ttusb);
 #endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	return (void *) ttusb;
-#else
+
 	usb_set_intfdata(intf, (void *) ttusb);
 
 	return 0;
-#endif
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static void ttusb_disconnect(struct usb_device *udev, void *data)
-{
-	struct ttusb *ttusb = data;
-#else
 static void ttusb_disconnect(struct usb_interface *intf)
 {
 	struct ttusb *ttusb = usb_get_intfdata(intf);
 
 	usb_set_intfdata(intf, NULL);
-#endif
 
 	ttusb->disconnecting = 1;
 
 	ttusb_stop_iso_xfer(ttusb);
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69))
-#undef devfs_remove
-#define devfs_remove(x)	devfs_unregister(ttusb->stc_devfs_handle);
-#endif
 #if 0
 	devfs_remove(TTUSB_BUDGET_NAME);
 #endif
diff -uNrwB --new-file linux-2.6.0-p2/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.mod.c linux-2.6.0-p3/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.mod.c
--- linux-2.6.0-p2/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.mod.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p3/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.mod.c	2003-12-18 15:43:27.000000000 +0100
@@ -0,0 +1,14 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+static const char __module_depends[]
+__attribute_used__
+__attribute__((section(".modinfo"))) =
+"depends=dvb-core";
+
+MODULE_ALIAS("usb:v0B48p1003dl*dh*dc*dsc*dp*ic*isc*ip*");
+MODULE_ALIAS("usb:v0B48p1004dl*dh*dc*dsc*dp*ic*isc*ip*");
+MODULE_ALIAS("usb:v0B48p1005dl*dh*dc*dsc*dp*ic*isc*ip*");
diff -uNrwB --new-file linux-2.6.0-p2/drivers/media/dvb/ttusb-dec/ttusb_dec.c linux-2.6.0-p3/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- linux-2.6.0-p2/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2003-12-18 15:10:40.000000000 +0100
+++ linux-2.6.0-p3/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2003-12-18 15:43:33.000000000 +0100
@@ -28,9 +28,7 @@
 #include <linux/usb.h>
 #include <linux/version.h>
 #include <linux/interrupt.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 #include <linux/firmware.h>
-#endif
 
 #include "dmxdev.h"
 #include "dvb_demux.h"
@@ -473,11 +471,7 @@
 	}
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static void ttusb_dec_process_urb(struct urb *urb)
-#else
 static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs)
-#endif
 {
 	struct ttusb_dec *dec = urb->context;
 
@@ -485,11 +479,8 @@
 		int i;
 
 		for (i = 0; i < FRAMES_PER_ISO_BUF; i++) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-			struct iso_packet_descriptor *d;
-#else
 			struct usb_iso_packet_descriptor *d;
-#endif
+
 			u8 *b;
 			int length;
 			struct urb_frame *frame;
@@ -522,10 +513,8 @@
 				urb->status);
 	}
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	if (dec->iso_stream_count)
 		usb_submit_urb(urb, GFP_ATOMIC);
-#endif
 }
 
 static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
@@ -542,12 +531,9 @@
 		urb->context = dec;
 		urb->complete = ttusb_dec_process_urb;
 		urb->pipe = dec->stream_pipe;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 		urb->transfer_flags = URB_ISO_ASAP;
 		urb->interval = 1;
-#else
-		urb->transfer_flags = USB_ISO_ASAP;
-#endif
+
 		urb->number_of_packets = FRAMES_PER_ISO_BUF;
 		urb->transfer_buffer_length = ISO_FRAME_SIZE *
 					      FRAMES_PER_ISO_BUF;
@@ -614,12 +600,8 @@
 		ttusb_dec_setup_urbs(dec);
 
 		for (i = 0; i < ISO_BUF_COUNT; i++) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 			if ((result = usb_submit_urb(dec->iso_urb[i],
 						     GFP_ATOMIC))) {
-#else
-			if ((result = usb_submit_urb(dec->iso_urb[i]))) {
-#endif
 				printk("%s: failed urb submission %d: "
 				       "error %d\n", __FUNCTION__, i, result);
 
@@ -641,10 +623,6 @@
 
 	up(&dec->iso_sem);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	ttusb_dec_set_streaming_interface(dec);
-#endif
-
 	return 0;
 }
 
@@ -775,11 +753,7 @@
 	for (i = 0; i < ISO_BUF_COUNT; i++) {
 		struct urb *urb;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 		if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) {
-#else
-		if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF))) {
-#endif
 			ttusb_dec_free_iso_urbs(dec);
 			return -ENOMEM;
 		}
@@ -789,13 +763,6 @@
 
 	ttusb_dec_setup_urbs(dec);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	for (i = 0; i < ISO_BUF_COUNT; i++) {
-		int next = (i + 1) % ISO_BUF_COUNT;
-		dec->iso_urb[i]->next = dec->iso_urb[next];
-	}
-#endif
-
 	return 0;
 }
 
@@ -831,11 +798,6 @@
 	ttusb_dec_alloc_iso_urbs(dec);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "dsp_dec2000t.h"
-#include "dsp_dec3000s.h"
-#endif
-
 static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 {
 	int i, j, actual_len, result, size, trans_count;
@@ -848,13 +810,10 @@
 	u32 firmware_csum = 0;
 	u32 firmware_size_nl;
 	u32 firmware_csum_nl;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	const struct firmware *fw_entry = NULL;
-#endif
 
 	dprintk("%s\n", __FUNCTION__);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
 		printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
 		       __FUNCTION__, dec->firmware_name);
@@ -863,21 +822,13 @@
 
 	firmware = fw_entry->data;
 	firmware_size = fw_entry->size;
-#endif
+
 	switch (dec->model) {
 		case TTUSB_DEC2000T:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-			firmware = &dsp_dec2000t[0];
-			firmware_size = sizeof(dsp_dec2000t);
-#endif
 			firmware_csum = 0x1bc86100;
 			break;
 
 		case TTUSB_DEC3000S:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-			firmware = &dsp_dec3000s[0];
-			firmware_size = sizeof(dsp_dec3000s);
-#endif
 			firmware_csum = 0x00000000;
 			break;
 	}
@@ -1313,22 +1264,6 @@
 	dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum,
-			     const struct usb_device_id *id)
-{
-	struct ttusb_dec *dec;
-
-	dprintk("%s\n", __FUNCTION__);
-
-	if (ifnum != 0)
-		return NULL;
-
-	if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
-		printk("%s: couldn't allocate memory.\n", __FUNCTION__);
-		return NULL;
-	}
-#else
 static int ttusb_dec_probe(struct usb_interface *intf,
 			   const struct usb_device_id *id)
 {
@@ -1345,7 +1280,6 @@
 	}
 
 	usb_set_intfdata(intf, (void *)dec);
-#endif
 
 	memset(dec, 0, sizeof(struct ttusb_dec));
 
@@ -1377,26 +1311,16 @@
 
 	dec->active = 1;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	return (void *)dec;
-#else
 	ttusb_dec_set_streaming_interface(dec);
 
 	return 0;
-#endif
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static void ttusb_dec_disconnect(struct usb_device *udev, void *data)
-{
-	struct ttusb_dec *dec = data;
-#else
 static void ttusb_dec_disconnect(struct usb_interface *intf)
 {
 	struct ttusb_dec *dec = usb_get_intfdata(intf);
 
 	usb_set_intfdata(intf, NULL);
-#endif
 
 	dprintk("%s\n", __FUNCTION__);
 
diff -uNrwB --new-file linux-2.6.0-p2/drivers/media/dvb/ttusb-dec/ttusb_dec.mod.c linux-2.6.0-p3/drivers/media/dvb/ttusb-dec/ttusb_dec.mod.c
--- linux-2.6.0-p2/drivers/media/dvb/ttusb-dec/ttusb_dec.mod.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-p3/drivers/media/dvb/ttusb-dec/ttusb_dec.mod.c	2003-12-18 15:43:33.000000000 +0100
@@ -0,0 +1,13 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+static const char __module_depends[]
+__attribute_used__
+__attribute__((section(".modinfo"))) =
+"depends=dvb-core";
+
+MODULE_ALIAS("usb:v0B48p1006dl*dh*dc*dsc*dp*ic*isc*ip*");
+MODULE_ALIAS("usb:v0B48p1008dl*dh*dc*dsc*dp*ic*isc*ip*");
diff -uNrwB --new-file linux-2.6.0.p/drivers/media/dvb/bt8xx/dvb-bt8xx.c linux-2.6.0.p2/drivers/media/dvb/bt8xx/dvb-bt8xx.c
--- linux-2.6.0.p/drivers/media/dvb/bt8xx/dvb-bt8xx.c	2003-12-18 19:56:34.000000000 +0100
+++ linux-2.6.0.p2/drivers/media/dvb/bt8xx/dvb-bt8xx.c	2003-12-18 19:58:46.000000000 +0100
@@ -179,40 +179,6 @@
 	return 0;
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-/* with 2.6.x not needed thanks to the driver model + sysfs */
-
-extern struct i2c_adapter *bttv_get_i2c_adap(unsigned int card);
-
-static void __init dvb_bt8xx_get_adaps(void)
-{
-	struct dvb_bt8xx_card *card;
-	struct list_head *entry, *entry_safe;
-
-	list_for_each_safe(entry, entry_safe, &card_list) {
-		card = list_entry(entry, struct dvb_bt8xx_card, list);
-		card->i2c_adapter =  bttv_get_i2c_adap(card->bttv_nr);
-		if (!card->i2c_adapter) {
-			printk("dvb_bt8xx: unable to determine i2c adaptor of card %d, deleting\n", card->bttv_nr);
-
-			list_del(&card->list);
-			kfree(card);
-		}
-	}
-}
-
-static void dvb_bt8xx_i2c_adap_free(struct i2c_adapter *adap)
-{
-}
-
-static void __exit dvb_bt8xx_exit_adaps(void)
-{
-}
-
-#else
-
-/* More complicated. but cleaner better */
-
 static struct dvb_bt8xx_card *dvb_bt8xx_find_by_i2c_adap(struct i2c_adapter *adap)
 {
 	struct dvb_bt8xx_card *card;
@@ -308,7 +274,6 @@
 {
 	i2c_del_driver(&dvb_bt8xx_driver);
 }
-#endif
 
 static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card)
 {
diff -uNrwB --new-file linux-2.6.0.p/drivers/media/dvb/frontends/dst-bt878.h linux-2.6.0.p2/drivers/media/dvb/frontends/dst-bt878.h
--- linux-2.6.0.p/drivers/media/dvb/frontends/dst-bt878.h	2003-12-18 19:56:34.000000000 +0100
+++ linux-2.6.0.p2/drivers/media/dvb/frontends/dst-bt878.h	2003-12-18 19:59:02.000000000 +0100
@@ -1,3 +1,8 @@
+/*
+ * dst-bt878.h: part of the DST driver for the TwinHan DST Frontend
+ *
+ * Copyright (C) 2003 Jamie Honan
+ */
 
 struct dst_gpio_enable {
 	u32	mask;
@@ -27,7 +32,6 @@
 
 struct bt878 ;
 
-int
-bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
+int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
 
 struct bt878 *bt878_find_by_dvb_adap(struct dvb_adapter *adap);
diff -ura linux-2.6.0/drivers/media/dvb/bt8xx/Makefile linux-2.6.0.p/drivers/media/dvb/bt8xx/Makefile
--- linux-2.6.0/drivers/media/dvb/bt8xx/Makefile	2003-12-19 10:57:46.000000000 +0100
+++ linux-2.6.0.p/drivers/media/dvb/bt8xx/Makefile	2003-12-19 10:57:31.000000000 +0100
@@ -1,5 +1,5 @@
 
 obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o
 
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends
 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 11/12] Firmware_class update
  2003-12-19 12:28                   ` [PATCH 10/12] Cleanup patch to remove 2.4 crud Michael Hunold
@ 2003-12-19 12:28                     ` Michael Hunold
  2003-12-19 12:28                       ` [PATCH 12/12] Add DVB documentation Michael Hunold
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

- use a kernel thread instead of schedule_work() when waiting for the firmware upload to happen
--- linux-2.5/drivers/base/firmware_class.c	(revision 14117)
+++ linux-2.5/drivers/base/firmware_class.c	(working copy)
@@ -415,18 +415,22 @@
 	void (*cont)(const struct firmware *fw, void *context);
 };
 
-static void
+static int
 request_firmware_work_func(void *arg)
 {
 	struct firmware_work *fw_work = arg;
 	const struct firmware *fw;
-	if (!arg)
-		return;
+	if (!arg) {
+		WARN_ON(1);
+		return 0;
+	}
+	daemonize("%s/%s", "firmware", fw_work->name);
 	request_firmware(&fw, fw_work->name, fw_work->device);
 	fw_work->cont(fw, fw_work->context);
 	release_firmware(fw);
 	module_put(fw_work->module);
 	kfree(fw_work);
+	return 0;
 }
 
 /**
@@ -451,6 +455,8 @@
 {
 	struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
 						GFP_ATOMIC);
+	int ret;
+
 	if (!fw_work)
 		return -ENOMEM;
 	if (!try_module_get(module)) {
@@ -465,9 +471,14 @@
 		.context = context,
 		.cont = cont,
 	};
-	INIT_WORK(&fw_work->work, request_firmware_work_func, fw_work);
 
-	schedule_work(&fw_work->work);
+	ret = kernel_thread(request_firmware_work_func, fw_work,
+			    CLONE_FS | CLONE_FILES);
+	
+	if (ret < 0) {
+		fw_work->cont(NULL, fw_work->context);
+		return ret;
+	}
 	return 0;
 }
 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 12/12] Add DVB documentation
  2003-12-19 12:28                     ` [PATCH 11/12] Firmware_class update Michael Hunold
@ 2003-12-19 12:28                       ` Michael Hunold
  0 siblings, 0 replies; 13+ messages in thread
From: Michael Hunold @ 2003-12-19 12:28 UTC (permalink / raw)
  To: akpm, torvalds, linux-kernel

DVB: - add some valuable documentation about the DVB subsystem, the supported cards, a faq, ...
diff -uNrwB --new-file xx-linux-2.6.0/Documentation/dvb/cards.txt linux-2.6.0.p2/Documentation/dvb/cards.txt
--- xx-linux-2.6.0/Documentation/dvb/cards.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0.p2/Documentation/dvb/cards.txt	2003-12-19 11:54:08.000000000 +0100
@@ -0,0 +1,63 @@
+Hardware supported by the linuxtv.org DVB drivers
+=================================================
+
+  Generally, the DVB hardware manufacturers frequently change the
+  frontends (i.e. tuner / demodulator units) used, usually without
+  changing the product name, revision number or specs. Some cards
+  are also available in versions with different frontends for
+  DVB-S/DVB-C/DVB-T. Thus the frontend drivers are listed seperately.
+
+  Note 1: There is no guarantee that every frontend driver works
+  out-of-the box with every card, because of different wiring.
+
+  Note 2: The demodulator chips can be used with a variety of
+  tuner/PLL chips, and not all combinations are supported. Often
+  the demodulator and tuner/PLL chip are inside a metal box for
+  shielding, and the whole metal box has its own part number.
+
+
+o Frontends drivers: 
+  - dvb_dummy_fe: for testing...
+  DVB-S:
+   - alps_bsrv2		: Alps BSRV2 (ves1893 demodulator)
+   - cx24110		: Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL)
+   - grundig_29504-491	: Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL
+   - mt312		: Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL
+   - stv0299		: Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL),
+   			  LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL), 
+			  Philips SU1278SH (tsa5059 PLL)
+  DVB-C:
+   - ves1820		: various (ves1820 demodulator, sp5659c or spXXXX PLL)
+   - at76c651		: Atmel AT76c651(B) with DAT7021 PLL
+  DVB-T:
+   - alps_tdlb7		: Alps TDLB7 (sp8870 demodulator, sp5659 PLL)
+   - alps_tdmb7		: Alps TDMB7 (cx22700 demodulator)
+   - grundig_29504-401	: Grundig 29504-401 (LSI L64781 demodulator), tsa5060 PLL
+   - tda1004x		: Philips tda10045h (td1344 or tdm1316l PLL)
+   - nxt6000 		: Alps TDME7 (MITEL SP5659 PLL), Alps TDED4 (TI ALP510 PLL),
+               		  Comtech DVBT-6k07 (SP5730 PLL)
+               		  (NxtWave Communications NXT6000 demodulator)
+
+
+o Cards based on the Phillips saa7146 multimedia PCI bridge chip:
+  - TI AV7110 based cards (i.e. with hardware MPEG decoder):
+    - Siemens/Technotrend/Hauppauge PCI DVB card revision 1.1, 1.3, 1.5, 1.6, 2.1
+      (aka Hauppauge Nexus)
+  - "budget" cards (i.e. without hardware MPEG decoder):
+    - Technotrend Budget / Hauppauge WinTV-Nova PCI Cards
+    - SATELCO Multimedia PCI
+    - KNC1 DVB-S
+
+o Cards based on the B2C2 Inc. FlexCopII:
+  - Technisat SkyStar2 PCI DVB
+
+o Cards based on the Conexant Bt8xx PCI bridge:
+  - Pinnacle PCTV Sat DVB
+  - Nebula Electronics DigiTV
+
+o Technotrend / Hauppauge DVB USB devices:
+  - Nova USB
+  - DEC 2000-T
+
+o Preliminary support for the analog module of the Siemens DVB-C PCI card
+
diff -uNrwB --new-file xx-linux-2.6.0/Documentation/dvb/contributors.txt linux-2.6.0.p2/Documentation/dvb/contributors.txt
--- xx-linux-2.6.0/Documentation/dvb/contributors.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0.p2/Documentation/dvb/contributors.txt	2003-12-19 11:54:08.000000000 +0100
@@ -0,0 +1,54 @@
+Thanks go to the following people for patches and contributions:
+
+Michael Hunold <m.hunold@gmx.de>
+  for the initial saa7146 driver and it's recent overhaul
+
+Christian Theiss
+  for his work on the initial Linux DVB driver
+
+Marcus Metzler <mocm@metzlerbros.de>
+Ralph Metzler <rjkm@metzlerbros.de>
+  for their contining work on the DVB driver
+
+Michael Holzt <kju@debian.org>
+  for his contributions to the dvb-net driver
+
+Diego Picciani <d.picciani@novacomp.it>
+  for CyberLogin for Linux which allows logging onto EON
+  (in case you are wondering where CyberLogin is, EON changed its login 
+  procedure and CyberLogin is no longer used.)
+
+Martin Schaller <martin@smurf.franken.de>
+  for patching the cable card decoder driver
+
+Klaus Schmidinger <Klaus.Schmidinger@cadsoft.de>
+  for various fixes regarding tuning, OSD and CI stuff and his work on VDR
+
+Steve Brown <sbrown@cortland.com>
+  for his AFC kernel thread
+
+Christoph Martin <martin@uni-mainz.de>
+  for his LIRC infrared handler
+
+Andreas Oberritter <andreas@oberritter.de>
+Florian Schirmer <jolt@tuxbox.org>
+...and all the other dBox2 people
+  for many bugfixes in the generic DVB Core and their work on the 
+  dBox2 port of the DVB driver
+
+Oliver Endriss <o.endriss@gmx.de>
+  for many bugfixes
+
+Andrew de Quincey <adq_dvb@lidskialf.net>
+  for the tda1004x frontend driver, and various bugfixes
+
+Peter Schildmann <peter.schildmann@web.de>
+  for the driver for the Technisat SkyStar2 PCI DVB card
+
+Vadim Catana <skystar@moldova.cc>
+Roberto Ragusa <r.ragusa@libero.it>
+Augusto Cardoso <augusto@carhil.net>
+  for all the work for the FlexCopII chipset by B2C2,Inc.
+
+(If you think you should be in this list, but you are not, drop a
+ line to the DVB mailing list)
diff -uNrwB --new-file xx-linux-2.6.0/Documentation/dvb/faq.txt linux-2.6.0.p2/Documentation/dvb/faq.txt
--- xx-linux-2.6.0/Documentation/dvb/faq.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0.p2/Documentation/dvb/faq.txt	2003-12-19 11:54:08.000000000 +0100
@@ -0,0 +1,109 @@
+Some very frequently asked questions about linuxtv-dvb
+
+1. The signal seems to die a few seconds after tuning.
+
+	It's not a bug, it's a feature. Because the frontends have
+	significant power requirements (and hence get very hot), they
+	are powered down if they are unused (i.e. if the frontend device
+	is closed). The dvb-core.o module paramter "dvb_shutdown_timeout"
+	allow you to change the timeout (default 5 seconds). Setting the
+	timeout to 0 disables the timeout feature.
+
+2. How can I watch TV?
+
+	The driver distribution includes some simple utilities which
+	are mainly intended for testing and to demonstrate how the
+	DVB API works.
+
+	Depending on whether you have a DVB-S, DVB-C or DVB-T card, use
+	apps/szap/szap, czap or tzap. You must supply a channel list
+	in ~/.[sct]zap/channels.conf. If you are lucky you can just copy
+	one of the supplied channel lists, or you can create a new one
+	by running apps/scan/scan. If you run scan on an unknown network
+	you might have to supply some start data in apps/scan/initial.h.
+
+	If you have a card with a built-in hardware MPEG-decoder the
+	drivers create a video4linux device (/dev/v4l/video0) which
+	you can use to watch TV with any v4l application. xawtv is known
+	to work. Note that you cannot change channels with xawtv, you
+	have to zap using [sct]zap. If you want a nice application for
+	TV watching and record/playback, have a look at VDR.
+
+	If your card does not have a hardware MPEG decoder you need
+	a software MPEG decoder. Mplayer or xine are known to work.
+	Newsflash: MythTV also has DVB support now.
+	Note: Only very recent versions of Mplayer and xine can decode.
+	MPEG2 transport streams (TS) directly. Then, run
+	'[sct]zap channelname -r' in one xterm, and keep it running,
+	and start 'mplayer - < /dev/dvb/adapter0/dvr0' or 
+	'xine stdin://mpeg2 < /dev/dvb/adapter0/dvr0' in a second xterm.
+	That's all far from perfect, but it seems no one has written
+	a nice DVB application which includes a builtin software MPEG
+	decoder yet.
+
+	Newsflash: Newest xine directly supports DVB. Just copy your
+	channels.conf to ~/.xine and start 'xine dvb://', or select
+	the DVB button in the xine GUI. Channel switching works using the
+	numpad pgup/pgdown (NP9 / NP3) keys to scroll through the channel osd
+	menu and pressing numpad-enter to switch to the selected channel.
+
+	Note: Older versions of xine and mplayer understand MPEG program
+	streams (PS) only, and can be used in conjunction with the
+	ts2ps tool from the Metzler Brother's dvb-mpegtools package.
+
+3. Which other DVB applications exist?
+
+	http://www.cadsoft.de/people/kls/vdr/
+		Klaus Schmidinger's Video Disk Recorder
+
+	http://www.metzlerbros.org/dvb/
+		Metzler Bros. DVB development; alternate drivers and
+		DVB utilities, include dvb-mpegtools and tuxzap.
+
+	http://www.linuxstb.org/
+	http://sourceforge.net/projects/dvbtools/
+		Dave Chapman's dvbtools package, including
+		dvbstream and dvbtune
+
+	http://www.linuxdvb.tv/
+		Henning Holtschneider's site with many interesting
+		links and docs
+
+	http://www.dbox2.info/
+		LinuxDVB on the dBox2
+
+	http://www.tuxbox.org/
+	http://cvs.tuxbox.org/
+		the TuxBox CVS many interesting DVB applications and the dBox2
+		DVB source
+
+	http://sourceforge.net/projects/dvbsak/
+		DVB Swiss Army Knife library and utilities
+
+	http://www.nenie.org/misc/mpsys/
+		MPSYS: a MPEG2 system library and tools
+
+	http://mplayerhq.hu/
+		mplayer
+
+	http://xine.sourceforge.net/
+	http://xinehq.de/
+		xine
+
+	http://www.mythtv.org/
+		MythTV - analog TV PVR, but now with DVB support, too
+		(with software MPEG decode)
+
+4. Can't get a signal tuned correctly
+
+	If you are using a Technotrend/Hauppauge DVB-C card *without* analog
+	module, you might have to use module parameter adac=-1 (dvb-ttpci.o).
+
+5. The dvb_net device doesn't give me any multicast packets
+
+	Check your routes if they include the multicast address range.
+	Additionally make sure that "source validation by reversed path
+	lookup" is disabled:
+	  $ "echo 0 > /proc/sys/net/ipv4/conf/dvb0/rp_filter"
+
+eof
diff -uNrwB --new-file xx-linux-2.6.0/Documentation/dvb/firmware.txt linux-2.6.0.p2/Documentation/dvb/firmware.txt
--- xx-linux-2.6.0/Documentation/dvb/firmware.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0.p2/Documentation/dvb/firmware.txt	2003-12-19 11:54:08.000000000 +0100
@@ -0,0 +1,116 @@
+Some DVB cards and many newer frontends require proprietary,
+binary-only firmware.
+
+The DVB drivers will be converted to use the request_firmware()
+hotplug interface (see linux/Documentation/firmware_class/).
+(CONFIG_FW_LOADER)
+
+The firmware can be loaded automatically via the hotplug manager
+or manually with the steps described below.
+
+Currently the drivers still use various different methods
+to load their firmwares, so here's just a short list of the
+current state:
+
+- dvb-ttpci: driver uses firmware hotplug interface
+- ttusb-budget: firmware is compiled in (dvb-ttusb-dspbootcode.h)
+- sp887x: firmware is compiled in (sp887x_firm.h)
+- alps_tdlb7: firmware is loaded from path specified by
+		"mcfile" module parameter; the binary must be
+		extracted from the Windows driver (Sc_main.mc).
+- tda1004x: firmware is loaded from path specified in
+		DVB_TDA1004X_FIRMWARE_FILE kernel config
+		variable (default /etc/dvb/tda1004x.bin); the
+		firmware binary must be extracted from the windows
+		driver
+- ttusb-dec: see "ttusb-dec.txt" for details
+
+1) Automatic firmware loading
+
+You need to install recent hotplug scripts if your distribution did not do it
+for you already, especially the  /etc/hotplug/firmware.agent.
+http://linux-hotplug.sourceforge.net/ (Call /sbin/hotplug without arguments
+to find out if the firmware agent is installed.)
+
+The firmware.agent script expects firmware binaries in
+/usr/lib/hotplug/firmware/. To avoid naming and versioning
+conflicts we propose the following naming scheme:
+
+  /usr/lib/hotplug/firmware/dvb-{driver}-{ver}.fw	for MPEG decoders etc.
+  /usr/lib/hotplug/firmware/dvb-fe-{driver}-{ver}.fw	for frontends
+
+  {driver} name is the basename of the driver kernel module (e.g. dvb-ttpci)
+  {ver} is a version number/name that should change only when the
+  driver/firmware internal API changes (so users are free to install the
+  latest firmware compatible with the driver).
+
+2) Manually loading the firmware into a driver
+   (currently only the dvb-ttpci / av7110 driver supports this)
+   
+Step a) Mount sysfs-filesystem.
+
+Sysfs provides a means to export kernel data structures, their attributes,
+and the linkages between them to userspace. 
+
+For detailed informations have a look at Documentation/filesystems/sysfs.txt 
+All you need to know at the moment is that firmware loading only works through
+sysfs.
+
+> mkdir /sys
+> mount -t sysfs sysfs /sys
+
+Step b) Exploring the firmware loading facilities
+
+Firmware_class support is located in
+/sys/class/firmware
+
+> dir /sys/class/firmware
+
+The "timeout" values specifies the amount of time that is waited before the
+firmware upload  process is cancelled. The default values is 10 seconds. If
+you use a hotplug script for the firmware upload, this is sufficient. If
+you want to upload the firmware by hand, however, this might be too fast.
+
+> echo "180" > /sys/class/firmware/timeout
+
+Step c) Getting a usable firmware file for the dvb-ttpci driver/av7110 card.
+
+You can download the firmware files from
+http://www.linuxtv.org/download/dvb/
+
+Please note that in case of the dvb-ttpci driver this is *not* the "Root"
+file you probably know from the 2.4 DVB releases driver.
+
+> wget http://www.linuxtv.org/download/dvb/dvb-ttpci-01.fw
+gets you the version 01 of the firmware fot the ttpci driver.
+
+Step d) Loading the dvb-ttpci driver and loading the firmware
+
+"modprobe" will take care that every needed module will be loaded
+automatically (except the frontend driver)
+
+> modprobe dvb-ttpci
+
+The "modprobe" process will hang until
+a) you upload the firmware or
+b) the timeout occurs.
+
+Change to another terminal and have a look at 
+
+> dir /sys/class/firmware/
+
+total 0
+drwxr-xr-x    2 root     root            0 Jul 29 11:00 0000:03:05.0
+-rw-r--r--    1 root     root            0 Jul 29 10:41 timeout
+
+"0000:03:05.0" is the id for my dvb-c card. It depends on the pci slot,
+so it changes if you plug the card to different slots.
+
+You can upload the firmware like that:
+
+> export DEVDIR=/sys/class/firmware/0000\:03\:05.0
+> echo 1 > $DEVDIR/loading
+> cat dvb-ttpci-01.fw > $DEVDIR/data
+> echo 0 > $DEVDIR/loading
+
+That's it. The driver should be up and running now.
diff -uNrwB --new-file xx-linux-2.6.0/Documentation/dvb/readme.txt linux-2.6.0.p2/Documentation/dvb/readme.txt
--- xx-linux-2.6.0/Documentation/dvb/readme.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0.p2/Documentation/dvb/readme.txt	2003-12-19 11:54:08.000000000 +0100
@@ -0,0 +1,39 @@
+Linux Digital Video Broadcast (DVB) subsystem
+=============================================
+
+The main development site and CVS repository for these
+drivers is http://linuxtv.org/.
+
+The developer mailing list linux-dvb is also hosted there,
+see http://linuxtv.org/mailinglists.xml. Please check
+the archive http://linuxtv.org/mailinglists/linux-dvb/
+before asking newbie questions on the list.
+
+API documentation, utilities and test/example programs
+are available as part of the old driver package for Linux 2.4
+(linuxtv-dvb-1.0.x.tar.gz), or from CVS (module DVB).
+We plan to split this into separate packages, but it's not
+been done yet.
+
+http://linuxtv.org/download/dvb/
+
+What's inside this directory:
+
+"cards.txt" 
+contains a list of supported hardware.
+
+"contributors.txt"
+is the who-is-who of DVB development
+
+"faq.txt"
+contains frequently asked questions and their answers.
+
+"firmware.txt" 
+contains informations for required external firmware
+files and where to get them.
+
+"ttusb-dec.txt"
+contains detailed informations about the
+TT DEC2000/DEC3000 USB DVB hardware.
+
+Good luck and have fun!
diff -uNrwB --new-file xx-linux-2.6.0/Documentation/dvb/ttusb-dec.txt linux-2.6.0.p2/Documentation/dvb/ttusb-dec.txt
--- xx-linux-2.6.0/Documentation/dvb/ttusb-dec.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0.p2/Documentation/dvb/ttusb-dec.txt	2003-12-19 11:54:08.000000000 +0100
@@ -0,0 +1,52 @@
+TechnoTrend/Hauppauge DEC USB Driver
+====================================
+
+Driver Status
+-------------
+
+Supported:
+	DEC2000-t
+	Linux Kernels 2.4 and 2.6
+	Video Streaming
+	Audio Streaming
+	Channel Zapping
+	Hotplug firmware loader under 2.6 kernels
+
+In Progress:
+	DEC3000-s
+
+To Do:
+	Section data
+	Teletext streams
+	Tuner status information
+	DVB network interface
+	Streaming video PC->DEC
+
+Note:	Since section data can not be retreived yet, scan apps will not work.
+
+Getting the Firmware
+--------------------
+Currently, the driver only works with v2.15a of the firmware.  The firmwares
+can be obtained in this way:
+
+wget http://hauppauge.lightpath.net/de/dec215a.exe
+unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_T.bin
+unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_S.bin
+
+
+Compilation Notes for 2.4 kernels
+---------------------------------
+For 2.4 kernels the firmware for the DECs is compiled into the driver itself.
+The firmwares are expected to be in /etc/dvb at compilation time.
+
+mv STB_PC_T.bin /etc/dvb/dec2000t.bin
+mv STB_PC_S.bin /etc/dvb/dec3000s.bin
+
+
+Hotplug Firmware Loading for 2.6 kernels
+----------------------------------------
+For 2.6 kernels the firmware is loaded at the point that the driver module is
+loaded.  See linux/Documentation/dvb/FIRMWARE for more information.
+
+mv STB_PC_T.bin /usr/lib/hotplug/firmware/dec2000t.bin
+mv STB_PC_S.bin /usr/lib/hotplug/firmware/dec3000s.bin


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2003-12-19 12:55 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-12-19 12:28 [PATCH 0/12] LinuxTV.org DVB+V4L fixes Michael Hunold
2003-12-19 12:28 ` [PATCH 1/12] Remove firmware of av7110 driver Michael Hunold
2003-12-19 12:28   ` [PATCH 2/12] Update saa7146 capture core Michael Hunold
2003-12-19 12:28     ` [PATCH 3/12] Add new DVB driver Michael Hunold
2003-12-19 12:28       ` [PATCH 4/12] Update Skystar2 " Michael Hunold
2003-12-19 12:28         ` [PATCH 5/12] Update DVB core Michael Hunold
2003-12-19 12:28           ` [PATCH 6/12] Update DVB frontend drivers Michael Hunold
2003-12-19 12:28             ` [PATCH 7/12] Update av7110 driver Michael Hunold
2003-12-19 12:28               ` [PATCH 8/12] Add firmware loading support to " Michael Hunold
2003-12-19 12:28                 ` [PATCH 9/12] Update TTUSB DEC driver Michael Hunold
2003-12-19 12:28                   ` [PATCH 10/12] Cleanup patch to remove 2.4 crud Michael Hunold
2003-12-19 12:28                     ` [PATCH 11/12] Firmware_class update Michael Hunold
2003-12-19 12:28                       ` [PATCH 12/12] Add DVB documentation Michael Hunold

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox