From: Michael Hunold <hunold@linuxtv.org>
To: torvalds@osdl.org, akpm@osdl.org, linux-kernel@vger.kernel.org,
hunold@linuxtv.org
Subject: [PATCH 2/5] Update saa7146 driver
Date: Sun, 18 Jan 2004 13:35:38 -0500 [thread overview]
Message-ID: <1074450922352@convergence.de> (raw)
In-Reply-To: <10744509221553@convergence.de>
- [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
next prev parent reply other threads:[~2004-01-18 18:38 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Michael Hunold [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1074450922352@convergence.de \
--to=hunold@linuxtv.org \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.