public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] LinuxTV.org DVB update
@ 2004-01-18 18:35 Michael Hunold
  2004-01-18 18:35 ` [PATCH 1/5] Update DVB documentation Michael Hunold
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Hunold @ 2004-01-18 18:35 UTC (permalink / raw)
  To: torvalds, akpm, linux-kernel, hunold

Hello Linus, Andrew,

I'm about to send you a set of 5 patches that sync the
LinuxTV.org CVS with latest linux-2.6.1/linux-2.6.1-mm4.

As usual, detailed informations about what changed can be 
found at the top of each file.

The patch "04-DVB-av7110-driver-splitup.diff" is bzip2'ed,
because it removes the av7110 DVB driver source and replaces
it with a modularized version. Sorry for the inconvenience!

Please apply! 

CU
Michael.



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

* [PATCH 1/5] Update DVB documentation
  2004-01-18 18:35 [PATCH 0/5] LinuxTV.org DVB update Michael Hunold
@ 2004-01-18 18:35 ` Michael Hunold
  2004-01-18 18:35   ` [PATCH 2/5] Update saa7146 driver Michael Hunold
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Hunold @ 2004-01-18 18:35 UTC (permalink / raw)
  To: torvalds, akpm, linux-kernel, hunold

- [DVB] update contributors
- [DVB] documentation update for recent DVB TTUSB driver changes
diff -uraNbBw xx-linux-2.6.1-mm4/Documentation/dvb/contributors.txt linux-2.6.1-mm4.patched/Documentation/dvb/contributors.txt
--- xx-linux-2.6.1-mm4/Documentation/dvb/contributors.txt	2004-01-16 19:49:27.000000000 +0100
+++ linux-2.6.1-mm4.patched/Documentation/dvb/contributors.txt	2004-01-09 20:27:26.000000000 +0100
@@ -8,7 +8,7 @@
 
 Marcus Metzler <mocm@metzlerbros.de>
 Ralph Metzler <rjkm@metzlerbros.de>
-  for their contining work on the DVB driver
+  for their continuing work on the DVB driver
 
 Michael Holzt <kju@debian.org>
   for his contributions to the dvb-net driver
@@ -58,5 +58,9 @@
   for his work on the budget drivers, the demux code,
   the module unloading problems, ...
   
+Hans-Frieder Vogt <hfvogt@arcor.de>
+  for his work on calculating and checking the crc's for the
+  TechnoTrend/Hauppauge DEC driver firmware
+
 (If you think you should be in this list, but you are not, drop a
  line to the DVB mailing list)
diff -uraNbBw xx-linux-2.6.1-mm4/Documentation/dvb/ttusb-dec.txt linux-2.6.1-mm4.patched/Documentation/dvb/ttusb-dec.txt
--- xx-linux-2.6.1-mm4/Documentation/dvb/ttusb-dec.txt	2004-01-16 19:49:27.000000000 +0100
+++ linux-2.6.1-mm4.patched/Documentation/dvb/ttusb-dec.txt	2004-01-16 18:21:55.000000000 +0100
@@ -14,6 +14,7 @@
 	Hotplug firmware loader under 2.6 kernels
 
 In Progress:
+	DEC2540-t
 	DEC3000-s
 
 To Do:
@@ -23,21 +24,34 @@
 
 Getting the Firmware
 --------------------
-Currently, the driver only works with v2.15a of the firmware.  The firmwares
-can be obtained in this way:
+The firmware can be found in the software update zip files on this page:
+http://www.hauppauge.de/sw_dec.htm
 
-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
+The firmwares are named as follows:
+DEC2000-t:	STB_PC_T.bin
+DEC2540-t:	STB_PC_X.bin
+DEC3000-s:	STB_PC_S.bin
+
+Note that firmwares since version 2.16 beta2 for the DEC2000-t give the device
+the USB ID of the DEC3000-s.  The driver copes with this.
+
+Instructions follow for retrieving version 2.16 of the firmware:
+
+wget http://hauppauge.lightpath.net/de/dec216.exe
+unzip -j dec216.exe software/OEM/STB/App/Boot/STB_PC_T.bin
+unzip -j dec216.exe software/OEM/STB/App/Boot/STB_PC_X.bin
+unzip -j dec216.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.
+The firmwares are expected to be in the build-2.4 directory at compilation
+time.
 
-mv STB_PC_T.bin /etc/dvb/dec2000t.bin
-mv STB_PC_S.bin /etc/dvb/dec3000s.bin
+mv STB_PC_T.bin build-2.4/dvb-ttusb-dec-2000t.fw
+mv STB_PC_X.bin build-2.4/dvb-ttusb-dec-2540t.fw
+mv STB_PC_S.bin build-2.4/dvb-ttusb-dec-3000s.fw
 
 
 Hotplug Firmware Loading for 2.6 kernels
@@ -45,5 +59,6 @@
 For 2.6 kernels the firmware is loaded at the point that the driver module is
 loaded.  See linux/Documentation/dvb/firmware.txt for more information.
 
-mv STB_PC_T.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2000t-2.15a.fw
-mv STB_PC_S.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-3000s-2.15a.fw
+mv STB_PC_T.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2000t.fw
+mv STB_PC_X.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2540t.fw
+mv STB_PC_S.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-3000s.fw



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

* [PATCH 2/5] Update saa7146 driver
  2004-01-18 18:35 ` [PATCH 1/5] Update DVB documentation Michael Hunold
@ 2004-01-18 18:35   ` Michael Hunold
  2004-01-18 18:35     ` [PATCH 3/5] Update DVB core Michael Hunold
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Hunold @ 2004-01-18 18:35 UTC (permalink / raw)
  To: torvalds, akpm, linux-kernel, hunold

- [DVB] fix memory leak in page table handling
- [DVB] minor coding style changes
- [DVB] add simple resource management for video dmas (borrowed from saa7134)
- [DVB] use resource management to lock video and vbi access which sometimes share the same video dmas
- [DVB] honour return codes of extension functions in various places, when resources could not be locked
- [DVB] remove remains of dead code which were commented out anyway 
- [DVB] add new flag FORMAT_IS_PLANAR to indicate planar capture formats, needed for resource allocation
diff -uraNbBw xx-linux-2.6.1-mm4/include/media/saa7146.h linux-2.6.1-mm4.patched/include/media/saa7146.h
--- xx-linux-2.6.1-mm4/include/media/saa7146.h	2004-01-16 19:49:14.000000000 +0100
+++ linux-2.6.1-mm4.patched/include/media/saa7146.h	2004-01-03 23:30:38.000000000 +0100
@@ -67,6 +67,8 @@
 	dma_addr_t	dma;
 	/* used for offsets for u,v planes for planar capture modes */
 	unsigned long	offset;
+	/* used for custom pagetables (used for example by budget dvb cards) */
+	struct scatterlist *slist;
 };
 
 struct saa7146_pci_extension_data {
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/common/saa7146_core.c linux-2.6.1-mm4.patched/drivers/media/common/saa7146_core.c
--- xx-linux-2.6.1-mm4/drivers/media/common/saa7146_core.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/common/saa7146_core.c	2004-01-09 20:27:26.000000000 +0100
@@ -137,7 +137,6 @@
 
 char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
 {
-	struct scatterlist *slist = NULL;
 	int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
 	char *mem = vmalloc_32(length);
 	int slen = 0;
@@ -146,35 +145,36 @@
 		return NULL;
 	}
 
-	if (!(slist = vmalloc_to_sg(mem, pages))) {
+	if (!(pt->slist = vmalloc_to_sg(mem, pages))) {
 		vfree(mem);
 		return NULL;
 	}
 
 	if (saa7146_pgtable_alloc(pci, pt)) {
-		kfree(slist);
+		kfree(pt->slist);
+		pt->slist = NULL;
 		vfree(mem);
 		return NULL;
 	}
 	
-	slen = pci_map_sg(pci,slist,pages,PCI_DMA_FROMDEVICE);
-	if (0 != saa7146_pgtable_build_single(pci, pt, slist, slen)) {
+	slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE);
+	if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) {
 		return NULL;
 	}
 
-	/* fixme: here's a memory leak: slist never gets freed by any other
-	   function ...*/
 	return mem;
 }
 
 void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
 {
-//fm	DEB_EE(("pci:%p, pt:%p\n",pci,pt));
-
 	if (NULL == pt->cpu)
 		return;
 	pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
 	pt->cpu = NULL;
+	if (NULL != pt->slist) {
+		kfree(pt->slist);
+		pt->slist = NULL;
+	}
 }
 
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
@@ -182,11 +182,8 @@
         u32          *cpu;
         dma_addr_t   dma_addr;
 
-//fm	DEB_EE(("pci:%p, pt:%p\n",pci,pt));
-
 	cpu = pci_alloc_consistent(pci, SAA7146_PGTABLE_SIZE, &dma_addr);
 	if (NULL == cpu) {
-//fm		ERR(("pci_alloc_consistent() failed."));
 		return -ENOMEM;
 	}
 	pt->size = SAA7146_PGTABLE_SIZE;
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/common/saa7146_fops.c linux-2.6.1-mm4.patched/drivers/media/common/saa7146_fops.c
--- xx-linux-2.6.1-mm4/drivers/media/common/saa7146_fops.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/common/saa7146_fops.c	2004-01-03 22:59:11.000000000 +0100
@@ -2,6 +2,65 @@
 
 #define BOARD_CAN_DO_VBI(dev)   (dev->revision != 0 && dev->vv_data->vbi_minor != -1) 
 
+/****************************************************************************/
+/* resource management functions, shamelessly stolen from saa7134 driver */
+
+int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	
+	if (fh->resources & bit)
+		/* have it already allocated */
+		return 1;
+
+	/* is it free? */
+	DEB_D(("getting lock...\n"));
+	down(&dev->lock);
+	DEB_D(("got lock\n"));
+	if (vv->resources & bit) {
+		DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
+		/* no, someone else uses it */
+		up(&dev->lock);
+		return 0;
+	}
+	/* it's free, grab it */
+	fh->resources  |= bit;
+	vv->resources |= bit;
+	DEB_D(("res: get %d\n",bit));
+	up(&dev->lock);
+	return 1;
+}
+
+int saa7146_res_check(struct saa7146_fh *fh, unsigned int bit)
+{
+	return (fh->resources & bit);
+}
+
+int saa7146_res_locked(struct saa7146_dev *dev, unsigned int bit)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	return (vv->resources & bit);
+}
+
+void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	if ((fh->resources & bits) != bits)
+		BUG();
+
+	DEB_D(("getting lock...\n"));
+	down(&dev->lock);
+	DEB_D(("got lock\n"));
+	fh->resources  &= ~bits;
+	vv->resources &= ~bits;
+	DEB_D(("res: put %d\n",bits));
+	up(&dev->lock);
+}
+
+
 /********************************************************************************/
 /* common dma functions */
 
@@ -216,29 +275,32 @@
 	}
 	memset(fh,0,sizeof(*fh));
 	
-	// FIXME: do we need to increase *our* usage count?
-
-	if( 0 == try_module_get(dev->ext->module)) {
-		result = -EINVAL;
-		goto out;
-	}
-
 	file->private_data = fh;
 	fh->dev = dev;
 	fh->type = type;
 
 	if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
 		DEB_S(("initializing vbi...\n"));
-		saa7146_vbi_uops.open(dev,file);
+		result = saa7146_vbi_uops.open(dev,file);
 	} else {
 		DEB_S(("initializing video...\n"));
-		saa7146_video_uops.open(dev,file);
+		result = saa7146_video_uops.open(dev,file);
+	}
+	
+	if (0 != result) {
+		goto out;
+	}
+
+	if( 0 == try_module_get(dev->ext->module)) {
+		result = -EINVAL;
+		goto out;
 	}
 
 	result = 0;
 out:
 	if( fh != 0 && result != 0 ) {
 		kfree(fh);
+		file->private_data = NULL;
 	}
 	up(&saa7146_devices_lock);
         return result;
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/common/saa7146_hlp.c linux-2.6.1-mm4.patched/drivers/media/common/saa7146_hlp.c
--- xx-linux-2.6.1-mm4/drivers/media/common/saa7146_hlp.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/common/saa7146_hlp.c	2004-01-04 17:20:31.000000000 +0100
@@ -152,8 +152,7 @@
 	if( 1 == xpsc ) {
 		xacm = 1;
 		dcgx = 0;
-	}
-	else {
+	} else {
 		xacm = 0;
 		/* get best match in the table of attenuations
 		   for horizontal scaling */
@@ -268,8 +267,7 @@
 		ype = ysci / 16;
 		ypo = ype + (ysci / 64);
 		
-	}
-	else {
+	} else {
 		yacm = 1;	
 
 		/* calculate scaling increment */
@@ -285,8 +283,7 @@
 						... */
 		if ( ysci < 512) {
 			yacl = 0;
-		}
-		else {
+		} else {
 			yacl = ( ysci / (1024 - ysci) );
 		}
 
@@ -488,33 +485,31 @@
  	saa7146_write(dev, MC2, (MASK_05 | MASK_21));
  
  	/* disable video dma2 */
-	saa7146_write(dev, MC1, (MASK_21));
+	saa7146_write(dev, MC1, MASK_21);
 }
 
-static void saa7146_set_clipping_rect(struct saa7146_dev *dev, struct saa7146_fh *fh)
+static void saa7146_set_clipping_rect(struct saa7146_fh *fh)
 {
+	struct saa7146_dev *dev = fh->dev;
 	enum v4l2_field field = fh->ov.win.field;
-	int clipcount = fh->ov.nclips;
-	
 	struct	saa7146_video_dma vdma2;
-
-	u32 clip_format	= saa7146_read(dev, CLIP_FORMAT_CTRL);
-	u32 arbtr_ctrl	= saa7146_read(dev, PCI_BT_V1);
-
-	// fixme: is this used at all? SAA7146_CLIPPING_RECT_INVERTED;
-	u32 type = SAA7146_CLIPPING_RECT;
+	u32 clip_format;
+	u32 arbtr_ctrl;
 
 	/* check clipcount, disable clipping if clipcount == 0*/
-	if( clipcount == 0 ) {
+	if( fh->ov.nclips == 0 ) {
 		saa7146_disable_clipping(dev);
 		return;
 	}
 
+	clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
+	arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
+
 	calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field);
 
 	/* set clipping format */
 	clip_format &= 0xffff0008;
-	clip_format |= (type << 4);
+	clip_format |= (SAA7146_CLIPPING_RECT << 4);
 
 	/* prepare video dma2 */
 	saa7146_write(dev, BASE_EVEN2,		vdma2.base_even);
@@ -660,25 +655,28 @@
 	vv->current_hps_sync = sync;
 } 
 
-/* reprogram hps, enable(1) / disable(0) video */
-void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v)
+int saa7146_enable_overlay(struct saa7146_fh *fh)
 {
+	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 
-	/* enable ? */
-	if( 0 == v) {
-		/* disable video dma1 */
-      		saa7146_write(dev, MC1, MASK_22);
-		return;
-	}
-
 	saa7146_set_window(dev, fh->ov.win.w.width, fh->ov.win.w.height, fh->ov.win.field);
 	saa7146_set_position(dev, fh->ov.win.w.left, fh->ov.win.w.top, fh->ov.win.w.height, fh->ov.win.field);
 	saa7146_set_output_format(dev, vv->ov_fmt->trans);
-	saa7146_set_clipping_rect(dev, fh);
+	saa7146_set_clipping_rect(fh);
 
 	/* enable video dma1 */
 	saa7146_write(dev, MC1, (MASK_06 | MASK_22));
+	return 0;
+}		
+
+void saa7146_disable_overlay(struct saa7146_fh *fh)
+{
+	struct saa7146_dev *dev = fh->dev;
+
+	/* disable clipping + video dma1 */
+ 	saa7146_disable_clipping(dev);
+	saa7146_write(dev, MC1, MASK_22);
 }		
 
 void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma) 
@@ -692,15 +690,8 @@
 	/* 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);
@@ -937,7 +928,7 @@
 	}	
 
 	saa7146_write_out_dma(dev, 1, &vdma1);
-	if( sfmt->swap != 0 ) {
+	if( (sfmt->flags & FORMAT_BYTE_SWAP) != 0 ) {
 		saa7146_write_out_dma(dev, 3, &vdma2);
 		saa7146_write_out_dma(dev, 2, &vdma3);
 	} else {
@@ -955,13 +946,6 @@
 	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);
@@ -1038,7 +1022,6 @@
 
 	saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field);
 	saa7146_set_output_format(dev, sfmt->trans);
-	saa7146_disable_clipping(dev);
 
 	if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
 	} else if ( vv->last_field == V4L2_FIELD_TOP ) {
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/common/saa7146_vbi.c linux-2.6.1-mm4.patched/drivers/media/common/saa7146_vbi.c
--- xx-linux-2.6.1-mm4/drivers/media/common/saa7146_vbi.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/common/saa7146_vbi.c	2004-01-03 22:15:07.000000000 +0100
@@ -366,7 +367,7 @@
 	init_waitqueue_head(&vv->vbi_wq);
 }
 
-static void vbi_open(struct saa7146_dev *dev, struct file *file)
+static int vbi_open(struct saa7146_dev *dev, struct file *file)
 {
 	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
 	
@@ -375,6 +376,12 @@
 	
 	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
 
+	ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
+	if (0 == ret) {
+		DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n"));
+		return -EBUSY;
+	}
+
 	/* adjust arbitrition control for video dma 3 */
 	arbtr_ctrl &= ~0x1f0000;
 	arbtr_ctrl |=  0x1d0000;
@@ -419,6 +426,7 @@
 
 	/* upload brs register */
 	saa7146_write(dev, MC2, (MASK_08|MASK_24));		
+	return 0;		
 }
 
 static void vbi_close(struct saa7146_dev *dev, struct file *file)
@@ -430,6 +438,7 @@
 	if( fh == vv->vbi_streaming ) {
 		vbi_stop(fh, file);
 	}
+	saa7146_res_free(fh, RESOURCE_DMA3_BRS);
 }
 
 static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/common/saa7146_video.c linux-2.6.1-mm4.patched/drivers/media/common/saa7146_video.c
--- xx-linux-2.6.1-mm4/drivers/media/common/saa7146_video.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/common/saa7146_video.c	2004-01-16 18:21:55.000000000 +0100
@@ -12,48 +12,55 @@
 		.pixelformat	= V4L2_PIX_FMT_RGB332,
 		.trans 		= RGB08_COMPOSED,
 		.depth		= 8,
+		.flags		= 0,
 	}, {
-		.name 		= "RGB-16 (5/B-6/G-5/R)", 	/* really? */
+		.name 		= "RGB-16 (5/B-6/G-5/R)",
 		.pixelformat	= V4L2_PIX_FMT_RGB565,
 		.trans 		= RGB16_COMPOSED,
 		.depth		= 16,
+		.flags		= 0,
 	}, {
 		.name 		= "RGB-24 (B-G-R)",
 		.pixelformat	= V4L2_PIX_FMT_BGR24,
 		.trans 		= RGB24_COMPOSED,
 		.depth		= 24,
+		.flags		= 0,
 	}, {
 		.name 		= "RGB-32 (B-G-R)",
 		.pixelformat	= V4L2_PIX_FMT_BGR32,
 		.trans 		= RGB32_COMPOSED,
 		.depth		= 32,
+		.flags		= 0,
 	}, {
 		.name 		= "Greyscale-8",
 		.pixelformat	= V4L2_PIX_FMT_GREY,
 		.trans 		= Y8,
 		.depth		= 8,
+		.flags		= 0,
 	}, {
 		.name 		= "YUV 4:2:2 planar (Y-Cb-Cr)",
 		.pixelformat	= V4L2_PIX_FMT_YUV422P,
 		.trans 		= YUV422_DECOMPOSED,
 		.depth		= 16,
-		.swap		= 1,
+		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
 	}, {
 		.name 		= "YVU 4:2:0 planar (Y-Cb-Cr)",
 		.pixelformat	= V4L2_PIX_FMT_YVU420,
 		.trans 		= YUV420_DECOMPOSED,
 		.depth		= 12,
-		.swap		= 1,
+		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
 	}, {
 		.name 		= "YUV 4:2:0 planar (Y-Cb-Cr)",
 		.pixelformat	= V4L2_PIX_FMT_YUV420,
 		.trans 		= YUV420_DECOMPOSED,
 		.depth		= 12,
+		.flags		= FORMAT_IS_PLANAR,
 	}, {
 		.name 		= "YUV 4:2:2 (U-Y-V-Y)",
 		.pixelformat	= V4L2_PIX_FMT_UYVY,
 		.trans 		= YUV422_COMPOSED,
 		.depth		= 16,
+		.flags		= 0,
 	}
 };
 
@@ -243,13 +250,13 @@
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
-	int err = 0;
+	int ret = 0, err = 0;
 
 	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
 
 	/* check if we have overlay informations */
 	if( NULL == fh->ov.fh ) {
-		DEB_D(("not overlay data available. try S_FMT first.\n"));
+		DEB_D(("no overlay data available. try S_FMT first.\n"));
 		return -EAGAIN;
 	}
 
@@ -280,7 +287,11 @@
 		fh->ov.win.w.left,fh->ov.win.w.top,
 		vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
 	
-	saa7146_set_overlay(dev, fh, 1);
+	if (0 != (ret = saa7146_enable_overlay(fh))) {
+		vv->ov_data = NULL;
+		DEB_D(("enabling overlay failed: %d\n",ret));
+		return ret;
+	}
 
 	return 0;
 }
@@ -290,7 +301,7 @@
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 
-	DEB_EE(("saa7146.o: saa7146_stop_preview()\n"));
+	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
 
 	/* check if overlay is running */
 	if( 0 == vv->ov_data ) {
@@ -300,11 +311,11 @@
 
 	if( fh != vv->ov_data->fh ) {
 		DEB_D(("overlay is active, but for another open.\n"));
-		return -EBUSY;
+		return 0;
 	}
 
-	saa7146_set_overlay(dev, fh, 0);
 	vv->ov_data = NULL;
+	saa7146_disable_overlay(fh);
 	
 	return 0;
 }
@@ -675,21 +686,37 @@
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_format *fmt = NULL;
 	unsigned long flags;
+	unsigned int resource;
+	int ret = 0;
 
 	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
 
 	if( fh == vv->streaming ) {
 		DEB_S(("already capturing.\n"));
-		return 0;
+		return -EBUSY;
 	}
 	if( vv->streaming != 0 ) {
 		DEB_S(("already capturing, but in another open.\n"));
 		return -EBUSY;
 	}
 
-	/* fixme: check for planar formats here, if we will interfere with
-	   vbi capture for example */	
+	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+	/* we need to have a valid format set here */
+	BUG_ON(NULL == fmt);
+
+	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
+	} else {
+		resource = RESOURCE_DMA1_HPS;
+	}
+
+	ret = saa7146_res_get(fh, resource);
+	if (0 == ret) {
+		DEB_S(("cannot get capture resource %d\n",resource));
+		return -EBUSY;
+	}
 
 	spin_lock_irqsave(&dev->slock,flags);
 
@@ -708,8 +735,10 @@
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_format *fmt = NULL;
 	unsigned long flags;
-	
+	unsigned int resource;
+	u32 dmas = 0;
 	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
 
 	if( vv->streaming != fh ) {
@@ -717,6 +746,19 @@
 		return -EINVAL;
 	}
 
+	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+	/* we need to have a valid format set here */
+	BUG_ON(NULL == fmt);
+
+	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
+		dmas = MASK_22 | MASK_21 | MASK_20;
+	} else {
+		resource = RESOURCE_DMA1_HPS;
+		dmas = MASK_20;
+	}
+	saa7146_res_free(fh, resource);
+
 	spin_lock_irqsave(&dev->slock,flags);
 
 	/* disable rps0  */
@@ -725,14 +767,8 @@
 	/* disable rps0 irqs */
 	IER_DISABLE(dev, MASK_27);
 
-	// fixme: only used formats here!
-	/* fixme: look at planar formats here, especially at the
-	   shutdown of planar formats! */
-
 	/* shut down all used video dma transfers */
-	/* fixme: what about the budget-dvb cards? they use
-	   video-dma3, but video_end should not get called anyway ...*/
-	saa7146_write(dev, MC1, 0x00700000);
+	saa7146_write(dev, MC1, dmas);
 
 	vv->streaming = NULL;
 
@@ -849,8 +883,12 @@
 			return -EINVAL;
 		}
 		
-		down(&dev->lock);
+		/* planar formats are not allowed for overlay video, clipping and video dma would clash */
+		if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+			DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat));
+		}
 
+		down(&dev->lock);
 		if( vv->ov_data != NULL ) {
 			ov_fh = vv->ov_data->fh;
 			saa7146_stop_preview(ov_fh);
@@ -1002,7 +1044,9 @@
 			return -EBUSY;
 		}
 
+		DEB_D(("before getting lock...\n"));
 		down(&dev->lock);
+		DEB_D(("got lock\n"));
 
 		if( vv->ov_data != NULL ) {
 			ov_fh = vv->ov_data->fh;
@@ -1047,22 +1095,33 @@
 		if( 0 != on ) {
 			if( vv->ov_data != NULL ) {
 				if( fh != vv->ov_data->fh) {
+					DEB_D(("overlay already active in another open\n"));
 					return -EAGAIN;
 				}
 			}
+
+			if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
+				DEB_D(("cannot get overlay resources\n"));
+				return -EBUSY;
+			}
+
 			spin_lock_irqsave(&dev->slock,flags);
 			err = saa7146_start_preview(fh);
 			spin_unlock_irqrestore(&dev->slock,flags);
-		} else {
+			return err;
+		}
+		
 			if( vv->ov_data != NULL ) {
 				if( fh != vv->ov_data->fh) {
+				DEB_D(("overlay is active, but in another open\n"));
 					return -EAGAIN;
 				}
 			}
 			spin_lock_irqsave(&dev->slock,flags);
 			err = saa7146_stop_preview(fh);
 			spin_unlock_irqrestore(&dev->slock,flags);
-		}
+		/* free resources */
+		saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
 		return err;
 	}
 	case VIDIOC_REQBUFS: {
@@ -1093,7 +1152,13 @@
 		int *type = arg;
 		DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
 
-		if( 0 != (err = video_begin(fh))) {
+		if( fh == vv->streaming ) {
+			DEB_D(("already capturing.\n"));
+			return 0;
+		}
+
+		err = video_begin(fh);
+		if( 0 != err) {
 				return err;
 			}
 		err = videobuf_streamon(file,q);
@@ -1103,6 +1168,12 @@
 		int *type = arg;
 
 		DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
+
+		if( fh != vv->streaming ) {
+			DEB_D(("this open is not capturing.\n"));
+			return -EINVAL;
+		}
+
 		err = videobuf_streamoff(file,q);
 		video_end(fh, file);
 		return err;
@@ -1309,7 +1380,7 @@
 }
 
 
-static void video_open(struct saa7146_dev *dev, struct file *file)
+static int video_open(struct saa7146_dev *dev, struct file *file)
 {
 	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
 	struct saa7146_format *sfmt;
@@ -1329,6 +1400,8 @@
 			    sizeof(struct saa7146_buf));
 
 	init_MUTEX(&fh->video_q.lock);
+
+	return 0;
 }
 
 
@@ -1381,15 +1454,25 @@
 
 	DEB_EE(("called.\n"));
 
+	/* fixme: should we allow read() captures while streaming capture? */
+	if( 0 != vv->streaming ) {
+		DEB_S(("already capturing.\n"));
+		return -EBUSY;
+	}
+
+	/* stop any active overlay */
 	if( vv->ov_data != NULL ) {
 		ov_fh = vv->ov_data->fh;
 		saa7146_stop_preview(ov_fh);
+		saa7146_res_free(ov_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
 		restart_overlay = 1;
 	}
 
-	if( 0 != video_begin(fh)) {
-		return -EAGAIN;
+	ret = video_begin(fh);
+	if( 0 != ret) {
+		goto out;
 	}
+
 	ret = videobuf_read_one(file,&fh->video_q , data, count, ppos);
 	video_end(fh, file);
 
@@ -1393,8 +1476,13 @@
 	ret = videobuf_read_one(file,&fh->video_q , data, count, ppos);
 	video_end(fh, file);
 
+out:
 	/* restart overlay if it was active before */
 	if( 0 != restart_overlay ) {
+		if (0 == saa7146_res_get(ov_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
+			DEB_D(("cannot get overlay resources again!\n"));
+			BUG();
+		}
 		saa7146_start_preview(ov_fh);
 	}
 	
diff -uraNbBw xx-linux-2.6.1-mm4/include/media/saa7146_vv.h linux-2.6.1-mm4.patched/include/media/saa7146_vv.h
--- xx-linux-2.6.1-mm4/include/media/saa7146_vv.h	2004-01-16 19:49:14.000000000 +0100
+++ linux-2.6.1-mm4.patched/include/media/saa7146_vv.h	2004-01-09 20:27:29.000000000 +0100
@@ -26,12 +26,15 @@
 	u32 num_line_byte;
 };
 
+#define FORMAT_BYTE_SWAP	0x1
+#define FORMAT_IS_PLANAR	0x2
+
 struct saa7146_format {
 	char	*name;
-	int   	pixelformat;
+	u32   	pixelformat;
 	u32	trans;
 	u8	depth;
-	int	swap;
+	u8	flags;
 };
 
 struct saa7146_standard
@@ -97,6 +100,8 @@
 	struct videobuf_queue	vbi_q;
 	struct v4l2_vbi_format	vbi_fmt;
 	struct timer_list	vbi_read_timeout;
+
+	unsigned int resources;	/* resource management for device open */
 };
 
 struct saa7146_vv
@@ -136,6 +141,8 @@
 	int 	current_hps_sync;
 
 	struct saa7146_dma	d_clipping;	/* pointer to clipping memory */
+
+	unsigned int resources;	/* resource management for device */
 };
 
 #define SAA7146_EXCLUSIVE	0x1
@@ -149,7 +156,6 @@
 };
 
 /* flags */
-// #define SAA7146_EXT_SWAP_ODD_EVEN	0x1     /* needs odd/even fields swapped */
 #define SAA7146_USE_PORT_B_FOR_VBI	0x2     /* use input port b for vbi hardware bug workaround */
 
 struct saa7146_ext_vv
@@ -171,7 +177,7 @@
 
 struct saa7146_use_ops  {
         void (*init)(struct saa7146_dev *, struct saa7146_vv *);
-        void(*open)(struct saa7146_dev *, struct file *);
+        int(*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 *);
@@ -189,9 +195,10 @@
 int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv);
 int saa7146_vv_release(struct saa7146_dev* dev);
 
-
 /* from saa7146_hlp.c */
-void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v);
+int saa7146_enable_overlay(struct saa7146_fh *fh);
+void saa7146_disable_overlay(struct saa7146_fh *fh);
+
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next);
 void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma) ;
 void saa7146_set_hps_source_and_sync(struct saa7146_dev *saa, int source, int sync);
@@ -205,6 +212,16 @@
 /* from saa7146_vbi.c */
 extern struct saa7146_use_ops saa7146_vbi_uops;
 
+/* resource management functions */
+int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit);
+int saa7146_res_check(struct saa7146_fh *fh, unsigned int bit);
+int saa7146_res_locked(struct saa7146_dev *dev, unsigned int bit);
+void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits);
+
+#define RESOURCE_DMA1_HPS	0x1
+#define RESOURCE_DMA2_CLP	0x2
+#define RESOURCE_DMA3_BRS	0x4
+
 /* saa7146 source inputs */
 #define SAA7146_HPS_SOURCE_PORT_A	0x00
 #define SAA7146_HPS_SOURCE_PORT_B	0x01



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

* [PATCH 4/5] av7110 DVB driver splitup
  2004-01-18 18:35     ` [PATCH 3/5] Update DVB core Michael Hunold
@ 2004-01-18 18:35       ` Michael Hunold
  2004-01-18 18:35         ` [PATCH 5/5] TTUSB DVB driver update Michael Hunold
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Hunold @ 2004-01-18 18:35 UTC (permalink / raw)
  To: torvalds, akpm, linux-kernel, hunold

[-- Attachment #1: Type: text/plain, Size: 780 bytes --]

- [DVB] after the firmware removal, split av7110.c into separate modules:
        - av7110.c: initialization and demux stuff
        - av7110_hw.c: lowlevel hardware access and firmware interface
        - av7110_ca.c: CI and ECD
        - av7110_av.c: audio/video MPEG decoder and remuxing stuff
        - av7110_v4l.c: v4l interface
- [DVB] av7110 fixes that were notcies during splitup
        - rename some non-static functions to enhance readability
        - lots of coding style & whitespace fixes
        - return -ERESTARTSYS from ci_ll_read/write() if interrupted
        - use time_after() for timeouts
        - added some comments about firmware interface
        - removed some unused fields from struct av7110, retabbing
- [DVB] follow driver splitup in Makefile	


[-- Attachment #2: 04-DVB-av7110-driver-splitup.diff.bz2 --]
[-- Type: application/octet-stream, Size: 45460 bytes --]

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

* [PATCH 3/5] Update DVB core
  2004-01-18 18:35   ` [PATCH 2/5] Update saa7146 driver Michael Hunold
@ 2004-01-18 18:35     ` Michael Hunold
  2004-01-18 18:35       ` [PATCH 4/5] av7110 DVB driver splitup Michael Hunold
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Hunold @ 2004-01-18 18:35 UTC (permalink / raw)
  To: torvalds, akpm, linux-kernel, hunold

- [DVB] demux: fix nasty bug where setting multiple filters resulted in ts packet duplication
- [DVB] frontend: merge frontend improvements from 2.4 DVB tree:
         - schedule_timeout(1) in dvb_frontend.c after setting frontend and before waking up frontend thread
         - do FE_RESET in each iteration of frontend thread if !FE_HAS_LOCK
         - use aquire_signal flag to call FE_RESET only after tuning until FE_HAS_LOCK has been signalled, and not when FE_HAS_LOCK drops out for short periods of time later
- [DVB] - follow frontend changes in ves1x93 driver
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/dvb/dvb-core/dvb_demux.c linux-2.6.1-mm4.patched/drivers/media/dvb/dvb-core/dvb_demux.c
--- xx-linux-2.6.1-mm4/drivers/media/dvb/dvb-core/dvb_demux.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/dvb/dvb-core/dvb_demux.c	2004-01-16 18:21:56.000000000 +0100
@@ -395,17 +397,35 @@
 	}
 }
 
+#define DVR_FEED(f)							\
+	(((f)->type == DMX_TYPE_TS) &&					\
+	((f)->feed.ts.is_filtering) &&					\
+	(((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET))
 
 void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 {
 	struct dvb_demux_feed *feed;
 	struct list_head *pos, *head=&demux->feed_list;
 	u16 pid = ts_pid(buf);
+	int dvr_done = 0;
 
 	list_for_each(pos, head) {
 		feed = list_entry(pos, struct dvb_demux_feed, list_head);
-		if (feed->pid == pid)
+
+		if ((feed->pid != pid) && (feed->pid != 0x2000))
+			continue;
+
+		/* copy each packet only once to the dvr device, even
+		 * if a PID is in multiple filters (e.g. video + PCR) */
+		if ((DVR_FEED(feed)) && (dvr_done++))
+			continue;
+
+		if (feed->pid == pid) {
 			dvb_dmx_swfilter_packet_type (feed, buf);
+			if (DVR_FEED(feed))
+				continue;
+		}
+
 		if (feed->pid == 0x2000)
 			feed->cb.ts(buf, 188, 0, 0, &feed->feed.ts, DMX_OK);
 	}
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/dvb/dvb-core/dvb_frontend.c linux-2.6.1-mm4.patched/drivers/media/dvb/dvb-core/dvb_frontend.c
--- xx-linux-2.6.1-mm4/drivers/media/dvb/dvb-core/dvb_frontend.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/dvb/dvb-core/dvb_frontend.c	2004-01-16 18:21:56.000000000 +0100
@@ -67,6 +67,7 @@
 	pid_t thread_pid;
 	unsigned long release_jiffies;
 	unsigned long lost_sync_jiffies;
+	int aquire_signal;
 	int bending;
 	int lnb_drift;
 	int timeout_count;
@@ -305,6 +306,7 @@
 		fe->lost_sync_count = 0;
 		fe->lost_sync_jiffies = jiffies;
 		fe->lnb_drift = 0;
+		fe->aquire_signal = 1;
 		if (fe->status & ~FE_TIMEDOUT)
 			dvb_frontend_add_event (fe, 0);
 		memcpy (&fe->parameters, param,
@@ -364,6 +366,9 @@
  */
 static void dvb_frontend_recover (struct dvb_frontend_data *fe)
 {
+	int j = fe->lost_sync_count;
+	int stepsize;
+
 	dprintk ("%s\n", __FUNCTION__);
 
 #if 0
@@ -383,10 +388,6 @@
 	/**
 	 *  let's start a zigzag scan to compensate LNB drift...
 	 */
-	{
-		int j = fe->lost_sync_count;
-		int stepsize;
-		
 		if (fe->info->type == FE_QPSK)
 			stepsize = fe->parameters.u.qpsk.symbol_rate / 16000;
 		else if (fe->info->type == FE_QAM)
@@ -403,7 +404,6 @@
 		}
 
 		dvb_frontend_set_parameters (fe, &fe->parameters, 0);
-	}
 
 	dvb_frontend_internal_ioctl (&fe->frontend, FE_RESET, NULL);
 }
@@ -467,13 +467,19 @@
 		if (s & FE_HAS_LOCK) {
 			fe->timeout_count = 0;
 			fe->lost_sync_count = 0;
+			fe->aquire_signal = 0;
 		} else {
 			fe->lost_sync_count++;
 			if (!(fe->info->caps & FE_CAN_RECOVER)) {
 				if (!(fe->info->caps & FE_CAN_CLEAN_SETUP)) {
-					if (fe->lost_sync_count < 10)
+					if (fe->lost_sync_count < 10) {
+						if (fe->aquire_signal)
+							dvb_frontend_internal_ioctl(
+									&fe->frontend,
+									FE_RESET, NULL);
 						continue;
 				}
+				}
 				dvb_frontend_recover (fe);
 				delay = HZ/5;
 			}
@@ -589,6 +611,9 @@
 		break;
 	case FE_SET_FRONTEND:
 		err = dvb_frontend_set_parameters (fe, parg, 1);
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(1);
+		wake_up_interruptible(&fe->wait_queue);
 		break;
 	case FE_GET_EVENT:
 		err = dvb_frontend_get_event (fe, parg, file->f_flags);
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/dvb/frontends/ves1x93.c linux-2.6.1-mm4.patched/drivers/media/dvb/frontends/ves1x93.c
--- xx-linux-2.6.1-mm4/drivers/media/dvb/frontends/ves1x93.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/dvb/frontends/ves1x93.c	2004-01-16 18:21:56.000000000 +0100
@@ -395,9 +395,6 @@
 	else
 		ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] & 0x7f);
 
-	ves1x93_writereg (i2c, 0x00, 0x00);
-	ves1x93_writereg (i2c, 0x00, 0x01);
-
 	/* ves1993 hates this, will lose lock */
 	if (demod_type != DEMOD_VES1993)
 		ves1x93_clr_bit (i2c);



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

* [PATCH 5/5] TTUSB DVB driver update
  2004-01-18 18:35       ` [PATCH 4/5] av7110 DVB driver splitup Michael Hunold
@ 2004-01-18 18:35         ` Michael Hunold
  0 siblings, 0 replies; 6+ messages in thread
From: Michael Hunold @ 2004-01-18 18:35 UTC (permalink / raw)
  To: torvalds, akpm, linux-kernel, hunold

- [DVB] TTUSB-DEC update by Alex Woods:
        - fix USB timeout bug under 2.6
        - change some variable names to make it clearer what we are dealing with (PVA).
	- support DEC2540-t and add info on it to the ttusb-dec docs.
	- add model number returned from DEC2540-t firmware.
	- add a module option to get the raw AVPES packets from the dvr device.
	- send audio packets to their filter rather than the videos.
	- handle the new empty packets that appear with the 2.16 firmware.
	- extra error checks.
	- handle the new firmwares that change the devices' USB IDs.
	- tidy up the STB initialisation process a little.
	- apply Hans-Frieder Vogt's patch for calculating firmware CRCs.
- [DVB] make TTUSB budget card depend on USB subsystem
diff -uraNbBw xx-linux-2.6.1-mm4/drivers/media/dvb/ttusb-budget/Kconfig linux-2.6.1-mm4.patched/drivers/media/dvb/ttusb-budget/Kconfig
--- xx-linux-2.6.1-mm4/drivers/media/dvb/ttusb-budget/Kconfig	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.patched/drivers/media/dvb/ttusb-budget/Kconfig	2004-01-09 20:27:29.000000000 +0100
@@ -1,6 +1,6 @@
 config DVB_TTUSB_BUDGET
 	tristate "Technotrend/Hauppauge Nova-USB devices"
-	depends on DVB_CORE
+	depends on DVB_CORE && USB
 	help
 	  Support for external USB adapters designed by Technotrend and
 	  produced by Hauppauge, shipped under the brand name 'Nova-USB'.
diff -urabBw xx-linux-2.6.1-mm4/drivers/media/dvb/ttusb-dec/ttusb_dec.c linux-2.6.1-mm4.usb/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- xx-linux-2.6.1-mm4/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-01-16 19:48:22.000000000 +0100
+++ linux-2.6.1-mm4.usb/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-01-18 15:32:39.000000000 +0100
@@ -20,9 +20,9 @@
  */
 
 #include <asm/semaphore.h>
+#include <linux/crc32.h>
 #include <linux/list.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -39,6 +39,7 @@
 #include "dvb_net.h"
 
 static int debug = 0;
+static int output_pva = 0;
 
 #define dprintk	if (debug) printk
 
@@ -46,34 +47,44 @@
 
 #define COMMAND_PIPE		0x03
 #define RESULT_PIPE		0x84
-#define STREAM_PIPE		0x88
+#define IN_PIPE			0x88
+#define OUT_PIPE		0x07
 
 #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 ISO_FRAME_SIZE		0x03FF
 
-#define	MAX_AV_PES_LENGTH	6144
+#define	MAX_PVA_LENGTH		6144
 
 #define LOF_HI			10600000
 #define LOF_LO			9750000
 
 enum ttusb_dec_model {
 	TTUSB_DEC2000T,
+	TTUSB_DEC2540T,
 	TTUSB_DEC3000S
 };
 
 enum ttusb_dec_packet_type {
-	PACKET_AV_PES,
-	PACKET_SECTION
+	TTUSB_DEC_PACKET_PVA,
+	TTUSB_DEC_PACKET_SECTION,
+	TTUSB_DEC_PACKET_EMPTY
+};
+
+enum ttusb_dec_interface {
+	TTUSB_DEC_INTERFACE_INITIAL,
+	TTUSB_DEC_INTERFACE_IN,
+	TTUSB_DEC_INTERFACE_OUT
 };
 
 struct ttusb_dec {
 	enum ttusb_dec_model		model;
 	char				*model_name;
 	char				*firmware_name;
+	int				can_playback;
 
 	/* DVB bits */
 	struct dvb_adapter		*adapter;
@@ -93,8 +104,9 @@
 	u8			trans_count;
 	unsigned int		command_pipe;
 	unsigned int		result_pipe;
-	unsigned int		stream_pipe;
-	int			interface;
+	unsigned int			in_pipe;
+	unsigned int			out_pipe;
+	enum ttusb_dec_interface	interface;
 	struct semaphore	usb_sem;
 
 	void			*iso_buffer;
@@ -103,19 +115,20 @@
 	int			iso_stream_count;
 	struct semaphore	iso_sem;
 
-	u8				packet[MAX_AV_PES_LENGTH + 4];
+	u8				packet[MAX_PVA_LENGTH + 4];
 	enum ttusb_dec_packet_type	packet_type;
 	int				packet_state;
 	int				packet_length;
 	int				packet_payload_length;
+	u16				next_packet_id;
 
-	int				av_pes_stream_count;
+	int				pva_stream_count;
 	int				filter_stream_count;
 
 	struct dvb_filter_pes2ts	a_pes2ts;
 	struct dvb_filter_pes2ts	v_pes2ts;
 
-	u8			v_pes[16 + MAX_AV_PES_LENGTH];
+	u8			v_pes[16 + MAX_PVA_LENGTH];
 	int			v_pes_length;
 	int			v_pes_postbytes;
 
@@ -123,6 +136,8 @@
 	struct tasklet_struct	urb_tasklet;
 	spinlock_t		urb_frame_list_lock;
 
+	struct dvb_demux_filter	*audio_filter;
+	struct dvb_demux_filter	*video_filter;
 	struct list_head	filter_info_list;
 	spinlock_t		filter_info_list_lock;
 
@@ -167,6 +182,22 @@
 		FE_CAN_HIERARCHY_AUTO,
 };
 
+static void ttusb_dec_set_model(struct ttusb_dec *dec,
+				enum ttusb_dec_model model);
+
+static u16 crc16(u16 crc, const u8 *buf, size_t len)
+{
+	u16 tmp;
+
+	while (len--) {
+		crc ^= *buf++;
+		crc ^= (u8)crc >> 4;
+		tmp = (u8)crc;
+		crc ^= (tmp ^ (tmp << 1)) << 4;
+	}
+	return crc;
+}
+
 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[])
@@ -234,11 +265,57 @@
 	}
 }
 
-static int ttusb_dec_av_pes2ts_cb(void *priv, unsigned char *data)
+static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
+				    unsigned int *model, unsigned int *version)
+{
+	u8 c[COMMAND_PACKET_SIZE];
+	int c_length;
+	int result;
+	unsigned int tmp;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
+	if (result)
+		return result;
+
+	if (c_length >= 0x0c) {
+		if (mode != NULL) {
+			memcpy(&tmp, c, 4);
+			*mode = ntohl(tmp);
+		}
+		if (model != NULL) {
+			memcpy(&tmp, &c[4], 4);
+			*model = ntohl(tmp);
+		}
+		if (version != NULL) {
+			memcpy(&tmp, &c[8], 4);
+			*version = ntohl(tmp);
+		}
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
 {
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)priv;
+	struct ttusb_dec *dec = (struct ttusb_dec *)priv;
 
-	dvbdmxfeed->cb.ts(data, 188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK);
+	dec->audio_filter->feed->cb.ts(data, 188, 0, 0,
+				       &dec->audio_filter->feed->feed.ts,
+				       DMX_OK);
+
+	return 0;
+}
+
+static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
+{
+	struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+
+	dec->video_filter->feed->cb.ts(data, 188, 0, 0,
+				       &dec->video_filter->feed->feed.ts,
+				       DMX_OK);
 
 	return 0;
 }
@@ -262,64 +339,69 @@
 	ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL);
 
 		dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO],
-				       ttusb_dec_av_pes2ts_cb, dec->demux.feed);
+			       ttusb_dec_audio_pes2ts_cb, dec);
 		dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
-				       ttusb_dec_av_pes2ts_cb, dec->demux.feed);
+			       ttusb_dec_video_pes2ts_cb, dec);
 	dec->v_pes_length = 0;
 	dec->v_pes_postbytes = 0;
 }
 
-static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes,
-				     int length)
+static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
 {
 	if (length < 8) {
 		printk("%s: packet too short - discarding\n", __FUNCTION__);
 		return;
 	}
 
-	if (length > 8 + MAX_AV_PES_LENGTH) {
+	if (length > 8 + MAX_PVA_LENGTH) {
 		printk("%s: packet too long - discarding\n", __FUNCTION__);
 		return;
 	}
 
-	switch (av_pes[2]) {
+	switch (pva[2]) {
 
 	case 0x01: {		/* VideoStream */
-			int prebytes = av_pes[5] & 0x03;
-			int postbytes = (av_pes[5] & 0x0c) >> 2;
+		int prebytes = pva[5] & 0x03;
+		int postbytes = (pva[5] & 0x0c) >> 2;
 			u16 v_pes_payload_length;
 
+		if (output_pva) {
+			dec->video_filter->feed->cb.ts(pva, length, 0, 0,
+				&dec->video_filter->feed->feed.ts, DMX_OK);
+			return;
+		}
+
 			if (dec->v_pes_postbytes > 0 &&
 			    dec->v_pes_postbytes == prebytes) {
 				memcpy(&dec->v_pes[dec->v_pes_length],
-				       &av_pes[12], prebytes);
+			       &pva[12], prebytes);
 
 				dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
 					  dec->v_pes_length + prebytes, 1);
 			}
 
-			if (av_pes[5] & 0x10) {
+		if (pva[5] & 0x10) {
 				dec->v_pes[7] = 0x80;
 				dec->v_pes[8] = 0x05;
 
-			dec->v_pes[9] = 0x21 | ((av_pes[8] & 0xc0) >> 5);
-				dec->v_pes[10] = ((av_pes[8] & 0x3f) << 2) |
-						 ((av_pes[9] & 0xc0) >> 6);
+			dec->v_pes[9] = 0x21 | ((pva[8] & 0xc0) >> 5);
+			dec->v_pes[10] = ((pva[8] & 0x3f) << 2) |
+					 ((pva[9] & 0xc0) >> 6);
 				dec->v_pes[11] = 0x01 |
-						 ((av_pes[9] & 0x3f) << 2) |
-						 ((av_pes[10] & 0x80) >> 6);
-				dec->v_pes[12] = ((av_pes[10] & 0x7f) << 1) |
-						 ((av_pes[11] & 0xc0) >> 7);
-			dec->v_pes[13] = 0x01 | ((av_pes[11] & 0x7f) << 1);
+					 ((pva[9] & 0x3f) << 2) |
+					 ((pva[10] & 0x80) >> 6);
+			dec->v_pes[12] = ((pva[10] & 0x7f) << 1) |
+					 ((pva[11] & 0xc0) >> 7);
+			dec->v_pes[13] = 0x01 | ((pva[11] & 0x7f) << 1);
 
-				memcpy(&dec->v_pes[14], &av_pes[12 + prebytes],
+			memcpy(&dec->v_pes[14], &pva[12 + prebytes],
 			       length - 12 - prebytes);
 			dec->v_pes_length = 14 + length - 12 - prebytes;
 			} else {
 				dec->v_pes[7] = 0x00;
 				dec->v_pes[8] = 0x00;
 
-			memcpy(&dec->v_pes[9], &av_pes[8], length - 8);
+			memcpy(&dec->v_pes[9], &pva[8], length - 8);
 			dec->v_pes_length = 9 + length - 8;
 			}
 
@@ -344,13 +426,19 @@
 		}
 
 	case 0x02:		/* MainAudioStream */
-		dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 8,
-				  av_pes[5] & 0x10);
+		if (output_pva) {
+			dec->audio_filter->feed->cb.ts(pva, length, 0, 0,
+				&dec->audio_filter->feed->feed.ts, DMX_OK);
+			return;
+		}
+
+		dvb_filter_pes2ts(&dec->a_pes2ts, &pva[8], length - 8,
+				  pva[5] & 0x10);
 		break;
 
 	default:
-		printk("%s: unknown AV_PES type: %02x.\n", __FUNCTION__,
-		       av_pes[2]);
+		printk("%s: unknown PVA type: %02x.\n", __FUNCTION__,
+		       pva[2]);
 		break;
 	}
 }
@@ -385,6 +473,7 @@
 {
 	int i;
 	u16 csum = 0;
+	u16 packet_id;
 
 	if (dec->packet_length % 2) {
 		printk("%s: odd sized packet - discarding\n", __FUNCTION__);
@@ -399,18 +488,34 @@
 		return;
 	}
 
+	packet_id = dec->packet[dec->packet_length - 4] << 8;
+	packet_id += dec->packet[dec->packet_length - 3];
+
+	if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
+		printk("%s: warning: lost packets between %u and %u\n",
+		       __FUNCTION__, dec->next_packet_id - 1, packet_id);
+	}
+
+	if (packet_id == 0xffff)
+		dec->next_packet_id = 0x8000;
+	else
+		dec->next_packet_id = packet_id + 1;
+
 	switch (dec->packet_type) {
-	case PACKET_AV_PES:
-		if (dec->av_pes_stream_count)
-			ttusb_dec_process_av_pes(dec, dec->packet,
+	case TTUSB_DEC_PACKET_PVA:
+		if (dec->pva_stream_count)
+			ttusb_dec_process_pva(dec, dec->packet,
 						 dec->packet_payload_length);
 		break;
 
-	case PACKET_SECTION:
+	case TTUSB_DEC_PACKET_SECTION:
 		if (dec->filter_stream_count)
 			ttusb_dec_process_filter(dec, dec->packet,
 						 dec->packet_payload_length);
 		break;
+
+	case TTUSB_DEC_PACKET_EMPTY:
+		break;
 	}
 }
 
@@ -459,15 +564,25 @@
 		case 4:
 			dec->packet[dec->packet_length++] = *b++;
 
-			if (dec->packet_length == 3) {
+			if (dec->packet_length == 2) {
 				if (dec->packet[0] == 'A' &&
 				    dec->packet[1] == 'V') {
-					dec->packet_type = PACKET_AV_PES;
+					dec->packet_type =
+						TTUSB_DEC_PACKET_PVA;
 					dec->packet_state++;
 				} else if (dec->packet[0] == 'S') {
-					dec->packet_type = PACKET_SECTION;
+					dec->packet_type =
+						TTUSB_DEC_PACKET_SECTION;
 					dec->packet_state++;
+				} else if (dec->packet[0] == 0x00) {
+					dec->packet_type =
+						TTUSB_DEC_PACKET_EMPTY;
+					dec->packet_payload_length = 2;
+					dec->packet_state = 7;
 			} else {
+					printk("%s: unknown packet type: "
+					       "%02x%02x\n", __FUNCTION__,
+					       dec->packet[0], dec->packet[1]);
 					dec->packet_state = 0;
 				}
 			}
@@ -478,13 +593,14 @@
 		case 5:
 			dec->packet[dec->packet_length++] = *b++;
 
-			if (dec->packet_type == PACKET_AV_PES &&
+			if (dec->packet_type == TTUSB_DEC_PACKET_PVA &&
 			    dec->packet_length == 8) {
 				dec->packet_state++;
 				dec->packet_payload_length = 8 +
 					(dec->packet[6] << 8) +
 					dec->packet[7];
-			} else if (dec->packet_type == PACKET_SECTION &&
+			} else if (dec->packet_type ==
+					TTUSB_DEC_PACKET_SECTION &&
 				   dec->packet_length == 5) {
 				dec->packet_state++;
 				dec->packet_payload_length = 5 +
@@ -521,7 +637,7 @@
 
 			dec->packet[dec->packet_length++] = *b++;
 
-			if (dec->packet_type == PACKET_SECTION &&
+			if (dec->packet_type == TTUSB_DEC_PACKET_SECTION &&
 			    dec->packet_payload_length % 2)
 				tail++;
 
@@ -627,10 +742,9 @@
 		urb->dev = dec->udev;
 		urb->context = dec;
 		urb->complete = ttusb_dec_process_urb;
-		urb->pipe = dec->stream_pipe;
+		urb->pipe = dec->in_pipe;
 		urb->transfer_flags = URB_ISO_ASAP;
 		urb->interval = 1;
-
 		urb->number_of_packets = FRAMES_PER_ISO_BUF;
 		urb->transfer_buffer_length = ISO_FRAME_SIZE *
 					      FRAMES_PER_ISO_BUF;
@@ -668,12 +782,36 @@
  * for a short period, so it's important not to call this function just before
  * trying to talk to it.
  */
-static void ttusb_dec_set_streaming_interface(struct ttusb_dec *dec)
+static int ttusb_dec_set_interface(struct ttusb_dec *dec,
+				   enum ttusb_dec_interface interface)
 {
-	if (!dec->interface) {
-		usb_set_interface(dec->udev, 0, 8);
-		dec->interface = 8;
+	int result = 0;
+	u8 b[] = { 0x05 };
+
+	if (interface != dec->interface) {
+		switch (interface) {
+		case TTUSB_DEC_INTERFACE_INITIAL:
+			result = usb_set_interface(dec->udev, 0, 0);
+			break;
+		case TTUSB_DEC_INTERFACE_IN:
+			result = ttusb_dec_send_command(dec, 0x80, sizeof(b),
+							b, NULL, NULL);
+			if (result)
+				return result;
+			result = usb_set_interface(dec->udev, 0, 7);
+			break;
+		case TTUSB_DEC_INTERFACE_OUT:
+			result = usb_set_interface(dec->udev, 0, 1);
+			break;
+		}
+
+		if (result)
+			return result;
+
+		dec->interface = interface;
 	}
+
+	return 0;
 }
 
 static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
@@ -688,6 +826,10 @@
 	if (!dec->iso_stream_count) {
 		ttusb_dec_setup_urbs(dec);
 
+		dec->packet_state = 0;
+		dec->v_pes_postbytes = 0;
+		dec->next_packet_id = 0;
+
 		for (i = 0; i < ISO_BUF_COUNT; i++) {
 			if ((result = usb_submit_urb(dec->iso_urb[i],
 						     GFP_ATOMIC))) {
@@ -703,9 +845,6 @@
 				return result;
 			}
 		}
-
-		dec->packet_state = 0;
-		dec->v_pes_postbytes = 0;
 	}
 
 	dec->iso_stream_count++;
@@ -720,6 +859,7 @@
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct ttusb_dec *dec = dvbdmx->priv;
 	u8 b0[] = { 0x05 };
+	int result = 0;
 
 	dprintk("%s\n", __FUNCTION__);
 
@@ -742,12 +882,14 @@
 		dprintk("  pes_type: DMX_TS_PES_VIDEO\n");
 		dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid;
 		dec->pid[DMX_PES_VIDEO] = dvbdmxfeed->pid;
+		dec->video_filter = dvbdmxfeed->filter;
 		ttusb_dec_set_pids(dec);
 		break;
 
 	case DMX_TS_PES_AUDIO:
 		dprintk("  pes_type: DMX_TS_PES_AUDIO\n");
 		dec->pid[DMX_PES_AUDIO] = dvbdmxfeed->pid;
+		dec->audio_filter = dvbdmxfeed->filter;
 		ttusb_dec_set_pids(dec);
 		break;
 
@@ -772,12 +914,12 @@
 
 	}
 
-	ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
-
-	dec->av_pes_stream_count++;
-	ttusb_dec_start_iso_xfer(dec);
+	result = ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
+	if (result)
+		return result;
 
-	return 0;
+	dec->pva_stream_count++;
+	return ttusb_dec_start_iso_xfer(dec);
 }
 
 static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
@@ -827,9 +969,7 @@
 			dvbdmxfeed->priv = finfo;
 
 			dec->filter_stream_count++;
-			ttusb_dec_start_iso_xfer(dec);
-
-			return 0;
+			return ttusb_dec_start_iso_xfer(dec);
 		}
 
 		return -EAGAIN;
@@ -872,7 +1012,7 @@
 
 	ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL);
 
-	dec->av_pes_stream_count--;
+	dec->pva_stream_count--;
 
 	ttusb_dec_stop_iso_xfer(dec);
 
@@ -991,7 +1131,8 @@
 
 	dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE);
 	dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
-	dec->stream_pipe = usb_rcvisocpipe(dec->udev, STREAM_PIPE);
+	dec->in_pipe = usb_rcvisocpipe(dec->udev, IN_PIPE);
+	dec->out_pipe = usb_sndisocpipe(dec->udev, OUT_PIPE);
 
 	ttusb_dec_alloc_iso_urbs(dec);
 }
@@ -1001,14 +1142,16 @@
 	int i, j, actual_len, result, size, trans_count;
 	u8 b0[] = { 0x00, 0x00, 0x00, 0x00,
 		    0x00, 0x00, 0x00, 0x00,
-		    0x00, 0x00 };
+		    0x61, 0x00 };
 	u8 b1[] = { 0x61 };
 	u8 b[ARM_PACKET_SIZE];
+	char idstring[21];
 	u8 *firmware = NULL;
 	size_t firmware_size = 0;
-	u32 firmware_csum = 0;
+	u16 firmware_csum = 0;
+	u16 firmware_csum_ns;
 	u32 firmware_size_nl;
-	u32 firmware_csum_nl;
+	u32 crc32_csum, crc32_check, tmp;
 	const struct firmware *fw_entry = NULL;
 
 	dprintk("%s\n", __FUNCTION__);
@@ -1022,20 +1165,33 @@
 	firmware = fw_entry->data;
 	firmware_size = fw_entry->size;
 
-	switch (dec->model) {
-		case TTUSB_DEC2000T:
-			firmware_csum = 0x1bc86100;
-			break;
-
-		case TTUSB_DEC3000S:
-			firmware_csum = 0x00000000;
-			break;
-	}
+	if (firmware_size < 60) {
+		printk("%s: firmware size too small for DSP code (%u < 60).\n",
+			__FUNCTION__, firmware_size);
+		return -1;
+	}
+
+	/* a 32 bit checksum over the first 56 bytes of the DSP Code is stored
+	   at offset 56 of file, so use it to check if the firmware file is
+	   valid. */
+	crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
+	memcpy(&tmp, &firmware[56], 4);
+	crc32_check = htonl(tmp);
+	if (crc32_csum != crc32_check) {
+		printk("%s: crc32 check of DSP code failed (calculated "
+		       "0x%08x != 0x%08x in file), file invalid.\n",
+			__FUNCTION__, crc32_csum, crc32_check);
+		return -1;
+	}
+	memcpy(idstring, &firmware[36], 20);
+	idstring[20] = '\0';
+	printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring);
 
 	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);
+	firmware_csum = crc16(~0, firmware, firmware_size) ^ ~0;
+	firmware_csum_ns = htons(firmware_csum);
+	memcpy(&b0[6], &firmware_csum_ns, 2);
 
 	result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
 
@@ -1077,20 +1233,56 @@
 
 static int ttusb_dec_init_stb(struct ttusb_dec *dec)
 {
-	u8 c[COMMAND_PACKET_SIZE];
-	int c_length;
 	int result;
+	unsigned int mode, model, version;
 
 	dprintk("%s\n", __FUNCTION__);
 
-	result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
+	result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
 
 	if (!result) {
-		if (c_length != 0x0c || (c_length == 0x0c && c[9] != 0x63))
-			return ttusb_dec_boot_dsp(dec);
+		if (!mode) {
+			if (version == 0xABCDEFAB)
+				printk(KERN_INFO "ttusb_dec: no version "
+				       "info in Firmware\n");
+			else
+				printk(KERN_INFO "ttusb_dec: Firmware "
+				       "%x.%02x%c%c\n",
+				       version >> 24, (version >> 16) & 0xff,
+				       (version >> 8) & 0xff, version & 0xff);
+
+			result = ttusb_dec_boot_dsp(dec);
+			if (result)
+				return result;
 		else
+				return 1;
+		} else {
+			/* We can't trust the USB IDs that some firmwares
+			   give the box */
+			switch (model) {
+			case 0x00070008:
+				ttusb_dec_set_model(dec, TTUSB_DEC3000S);
+				break;
+			case 0x00070009:
+				ttusb_dec_set_model(dec, TTUSB_DEC2000T);
+				break;
+			case 0x00070011:
+				ttusb_dec_set_model(dec, TTUSB_DEC2540T);
+				break;
+			default:
+				printk(KERN_ERR "%s: unknown model returned "
+				       "by firmware (%08x) - please report\n",
+				       __FUNCTION__, model);
+				return -1;
+				break;
+			}
+
+			if (version >= 0x01770000)
+				dec->can_playback = 1;
+
 			return 0;
 	}
+	}
 	else
 		return result;
 }
@@ -1101,7 +1293,8 @@
 
 	dprintk("%s\n", __FUNCTION__);
 
-	if ((result = dvb_register_adapter(&dec->adapter, dec->model_name)) < 0) {
+	if ((result = dvb_register_adapter(&dec->adapter,
+					   dec->model_name)) < 0) {
 		printk("%s: dvb_register_adapter failed: error %d\n",
 		       __FUNCTION__, result);
 
@@ -1449,18 +1638,6 @@
 {
 	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);
 }
@@ -1509,15 +1686,15 @@
 
 	switch (id->idProduct) {
 		case 0x1006:
-			dec->model = TTUSB_DEC3000S;
-			dec->model_name = "DEC3000-s";
-		dec->firmware_name = "dvb-ttusb-dec-3000s-2.15a.fw";
+		ttusb_dec_set_model(dec, TTUSB_DEC3000S);
 			break;
 
 		case 0x1008:
-			dec->model = TTUSB_DEC2000T;
-			dec->model_name = "DEC2000-t";
-		dec->firmware_name = "dvb-ttusb-dec-2000t-2.15a.fw";
+		ttusb_dec_set_model(dec, TTUSB_DEC2000T);
+		break;
+
+	case 0x1009:
+		ttusb_dec_set_model(dec, TTUSB_DEC2540T);
 			break;
 	}
 
@@ -1536,7 +1713,7 @@
 
 	dec->active = 1;
 
-	ttusb_dec_set_streaming_interface(dec);
+	ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
 
 	return 0;
 }
@@ -1560,15 +1737,45 @@
 	kfree(dec);
 }
 
+static void ttusb_dec_set_model(struct ttusb_dec *dec,
+				enum ttusb_dec_model model)
+{
+	dec->model = model;
+
+	switch (model) {
+	case TTUSB_DEC2000T:
+		dec->model_name = "DEC2000-t";
+		dec->firmware_name = "dvb-ttusb-dec-2000t.fw";
+		dec->frontend_info = &dec2000t_frontend_info;
+		dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;
+		break;
+
+	case TTUSB_DEC2540T:
+		dec->model_name = "DEC2540-t";
+		dec->firmware_name = "dvb-ttusb-dec-2540t.fw";
+		dec->frontend_info = &dec2000t_frontend_info;
+		dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;
+		break;
+
+	case TTUSB_DEC3000S:
+		dec->model_name = "DEC3000-s";
+		dec->firmware_name = "dvb-ttusb-dec-3000s.fw";
+		dec->frontend_info = &dec3000s_frontend_info;
+		dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl;
+		break;
+	}
+}
+
 static struct usb_device_id ttusb_dec_table[] = {
 	{USB_DEVICE(0x0b48, 0x1006)},	/* DEC3000-s */
 	/*{USB_DEVICE(0x0b48, 0x1007)},	   Unconfirmed */
 	{USB_DEVICE(0x0b48, 0x1008)},	/* DEC2000-t */
+	{USB_DEVICE(0x0b48, 0x1009)},	/* DEC2540-t */
 	{}
 };
 
 static struct usb_driver ttusb_dec_driver = {
-      .name		= DRIVER_NAME,
+	.name		= "ttusb-dec",
       .probe		= ttusb_dec_probe,
       .disconnect	= ttusb_dec_disconnect,
       .id_table		= ttusb_dec_table,
@@ -1602,3 +1809,5 @@
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug level");
+MODULE_PARM(output_pva, "i");
+MODULE_PARM_DESC(output_pva, "Output PVA from dvr device");



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

end of thread, other threads:[~2004-01-18 18:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-01-18 18:35 [PATCH 0/5] LinuxTV.org DVB update Michael Hunold
2004-01-18 18:35 ` [PATCH 1/5] Update DVB documentation Michael Hunold
2004-01-18 18:35   ` [PATCH 2/5] Update saa7146 driver Michael Hunold
2004-01-18 18:35     ` [PATCH 3/5] Update DVB core Michael Hunold
2004-01-18 18:35       ` [PATCH 4/5] av7110 DVB driver splitup Michael Hunold
2004-01-18 18:35         ` [PATCH 5/5] TTUSB DVB driver update Michael Hunold

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