* [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 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 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 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