|
@@ -1,15 +1,20 @@
|
|
|
/*
|
|
|
*
|
|
|
* generic helper functions for video4linux capture buffers, to handle
|
|
|
- * memory management and PCI DMA. Right now bttv + saa7134 use it.
|
|
|
+ * memory management and PCI DMA.
|
|
|
+ * Right now, bttv, saa7134, saa7146 and cx88 use it.
|
|
|
*
|
|
|
* The functions expect the hardware being able to scatter gatter
|
|
|
* (i.e. the buffers are not linear in physical memory, but fragmented
|
|
|
* into PAGE_SIZE chunks). They also assume the driver does not need
|
|
|
- * to touch the video data (thus it is probably not useful for USB 1.1
|
|
|
- * as data often must be uncompressed by the drivers).
|
|
|
+ * to touch the video data.
|
|
|
+ *
|
|
|
+ * device specific map/unmap/sync stuff now are mapped as operations
|
|
|
+ * to allow its usage by USB and virtual devices.
|
|
|
*
|
|
|
* (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
|
|
|
+ * (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
|
|
|
+ * (c) 2006 Ted Walther and John Sokol
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
@@ -167,6 +172,9 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
|
|
|
dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
+ dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
|
|
|
+ (unsigned long)dma->vmalloc,
|
|
|
+ nr_pages << PAGE_SHIFT);
|
|
|
memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT);
|
|
|
dma->nr_pages = nr_pages;
|
|
|
return 0;
|
|
@@ -186,8 +194,10 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
|
|
|
+int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
|
|
|
{
|
|
|
+ void *dev=q->dev;
|
|
|
+
|
|
|
MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
|
|
|
BUG_ON(0 == dma->nr_pages);
|
|
|
|
|
@@ -197,7 +207,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
|
|
|
}
|
|
|
if (dma->vmalloc) {
|
|
|
dma->sglist = videobuf_vmalloc_to_sg
|
|
|
- (dma->vmalloc,dma->nr_pages);
|
|
|
+ (dma->vmalloc,dma->nr_pages);
|
|
|
}
|
|
|
if (dma->bus_addr) {
|
|
|
dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
|
|
@@ -212,13 +222,14 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
|
|
|
dprintk(1,"scatterlist is NULL\n");
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
-
|
|
|
if (!dma->bus_addr) {
|
|
|
- dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages,
|
|
|
- dma->direction);
|
|
|
+ if (q->ops->vb_map_sg) {
|
|
|
+ dma->sglen = q->ops->vb_map_sg(dev,dma->sglist,
|
|
|
+ dma->nr_pages, dma->direction);
|
|
|
+ }
|
|
|
if (0 == dma->sglen) {
|
|
|
printk(KERN_WARNING
|
|
|
- "%s: pci_map_sg failed\n",__FUNCTION__);
|
|
|
+ "%s: videobuf_map_sg failed\n",__FUNCTION__);
|
|
|
kfree(dma->sglist);
|
|
|
dma->sglist = NULL;
|
|
|
dma->sglen = 0;
|
|
@@ -228,24 +239,31 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma)
|
|
|
+int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
|
|
|
{
|
|
|
+ void *dev=q->dev;
|
|
|
+
|
|
|
MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
|
|
|
BUG_ON(!dma->sglen);
|
|
|
|
|
|
- if (!dma->bus_addr)
|
|
|
- pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction);
|
|
|
+ if (!dma->bus_addr && q->ops->vb_dma_sync_sg)
|
|
|
+ q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages,
|
|
|
+ dma->direction);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma)
|
|
|
+int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
|
|
|
{
|
|
|
+ void *dev=q->dev;
|
|
|
+
|
|
|
MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
|
|
|
if (!dma->sglen)
|
|
|
return 0;
|
|
|
|
|
|
- if (!dma->bus_addr)
|
|
|
- pci_unmap_sg(dev,dma->sglist,dma->nr_pages,dma->direction);
|
|
|
+ if (!dma->bus_addr && q->ops->vb_unmap_sg)
|
|
|
+ q->ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages,
|
|
|
+ dma->direction);
|
|
|
kfree(dma->sglist);
|
|
|
dma->sglist = NULL;
|
|
|
dma->sglen = 0;
|
|
@@ -318,7 +336,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
|
|
|
}
|
|
|
|
|
|
int
|
|
|
-videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb,
|
|
|
+videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
|
|
|
struct v4l2_framebuffer *fbuf)
|
|
|
{
|
|
|
int err,pages;
|
|
@@ -357,7 +375,7 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb,
|
|
|
default:
|
|
|
BUG();
|
|
|
}
|
|
|
- err = videobuf_dma_pci_map(pci,&vb->dma);
|
|
|
+ err = videobuf_dma_map(q,&vb->dma);
|
|
|
if (0 != err)
|
|
|
return err;
|
|
|
|
|
@@ -366,9 +384,41 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb,
|
|
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
|
|
+void videobuf_queue_pci(struct videobuf_queue* q)
|
|
|
+{
|
|
|
+ /* If not specified, defaults to PCI map sg */
|
|
|
+ if (!q->ops->vb_map_sg)
|
|
|
+ q->ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg;
|
|
|
+
|
|
|
+ if (!q->ops->vb_dma_sync_sg)
|
|
|
+ q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu;
|
|
|
+ if (!q->ops->vb_unmap_sg)
|
|
|
+ q->ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
|
|
|
+}
|
|
|
+
|
|
|
+int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
|
|
|
+{
|
|
|
+ struct videobuf_queue q;
|
|
|
+
|
|
|
+ q.dev=pci;
|
|
|
+ q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
|
|
|
+
|
|
|
+ return (videobuf_dma_unmap(&q,dma));
|
|
|
+}
|
|
|
+
|
|
|
+int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
|
|
|
+{
|
|
|
+ struct videobuf_queue q;
|
|
|
+
|
|
|
+ q.dev=pci;
|
|
|
+ q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
|
|
|
+
|
|
|
+ return (videobuf_dma_unmap(&q,dma));
|
|
|
+}
|
|
|
+
|
|
|
void videobuf_queue_init(struct videobuf_queue* q,
|
|
|
struct videobuf_queue_ops *ops,
|
|
|
- struct pci_dev *pci,
|
|
|
+ void *dev,
|
|
|
spinlock_t *irqlock,
|
|
|
enum v4l2_buf_type type,
|
|
|
enum v4l2_field field,
|
|
@@ -377,13 +427,15 @@ void videobuf_queue_init(struct videobuf_queue* q,
|
|
|
{
|
|
|
memset(q,0,sizeof(*q));
|
|
|
q->irqlock = irqlock;
|
|
|
- q->pci = pci;
|
|
|
+ q->dev = dev;
|
|
|
q->type = type;
|
|
|
q->field = field;
|
|
|
q->msize = msize;
|
|
|
q->ops = ops;
|
|
|
q->priv_data = priv;
|
|
|
|
|
|
+ videobuf_queue_pci(q);
|
|
|
+
|
|
|
mutex_init(&q->lock);
|
|
|
INIT_LIST_HEAD(&q->stream);
|
|
|
}
|
|
@@ -431,7 +483,8 @@ videobuf_queue_cancel(struct videobuf_queue *q)
|
|
|
int i;
|
|
|
|
|
|
/* remove queued buffers from list */
|
|
|
- spin_lock_irqsave(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_lock_irqsave(q->irqlock,flags);
|
|
|
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
|
|
|
if (NULL == q->bufs[i])
|
|
|
continue;
|
|
@@ -440,7 +493,8 @@ videobuf_queue_cancel(struct videobuf_queue *q)
|
|
|
q->bufs[i]->state = STATE_ERROR;
|
|
|
}
|
|
|
}
|
|
|
- spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
|
|
|
/* free all buffers + clear queue */
|
|
|
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
|
|
@@ -534,19 +588,29 @@ videobuf_reqbufs(struct videobuf_queue *q,
|
|
|
unsigned int size,count;
|
|
|
int retval;
|
|
|
|
|
|
- if (req->type != q->type)
|
|
|
+ if (req->type != q->type) {
|
|
|
+ dprintk(1,"reqbufs: queue type invalid\n");
|
|
|
return -EINVAL;
|
|
|
- if (req->count < 1)
|
|
|
+ }
|
|
|
+ if (req->count < 1) {
|
|
|
+ dprintk(1,"reqbufs: count invalid (%d)\n",req->count);
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
if (req->memory != V4L2_MEMORY_MMAP &&
|
|
|
req->memory != V4L2_MEMORY_USERPTR &&
|
|
|
- req->memory != V4L2_MEMORY_OVERLAY)
|
|
|
+ req->memory != V4L2_MEMORY_OVERLAY) {
|
|
|
+ dprintk(1,"reqbufs: memory type invalid\n");
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
- if (q->streaming)
|
|
|
+ if (q->streaming) {
|
|
|
+ dprintk(1,"reqbufs: streaming already exists\n");
|
|
|
return -EBUSY;
|
|
|
- if (!list_empty(&q->stream))
|
|
|
+ }
|
|
|
+ if (!list_empty(&q->stream)) {
|
|
|
+ dprintk(1,"reqbufs: stream running\n");
|
|
|
return -EBUSY;
|
|
|
+ }
|
|
|
|
|
|
mutex_lock(&q->lock);
|
|
|
count = req->count;
|
|
@@ -559,8 +623,10 @@ videobuf_reqbufs(struct videobuf_queue *q,
|
|
|
count, size, (count*size)>>PAGE_SHIFT);
|
|
|
|
|
|
retval = videobuf_mmap_setup(q,count,size,req->memory);
|
|
|
- if (retval < 0)
|
|
|
+ if (retval < 0) {
|
|
|
+ dprintk(1,"reqbufs: mmap setup returned %d\n",retval);
|
|
|
goto done;
|
|
|
+ }
|
|
|
|
|
|
req->count = count;
|
|
|
|
|
@@ -572,12 +638,18 @@ videobuf_reqbufs(struct videobuf_queue *q,
|
|
|
int
|
|
|
videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
|
|
|
{
|
|
|
- if (unlikely(b->type != q->type))
|
|
|
+ if (unlikely(b->type != q->type)) {
|
|
|
+ dprintk(1,"querybuf: Wrong type.\n");
|
|
|
return -EINVAL;
|
|
|
- if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME))
|
|
|
+ }
|
|
|
+ if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) {
|
|
|
+ dprintk(1,"querybuf: index out of range.\n");
|
|
|
return -EINVAL;
|
|
|
- if (unlikely(NULL == q->bufs[b->index]))
|
|
|
+ }
|
|
|
+ if (unlikely(NULL == q->bufs[b->index])) {
|
|
|
+ dprintk(1,"querybuf: buffer is null.\n");
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
videobuf_status(b,q->bufs[b->index],q->type);
|
|
|
return 0;
|
|
|
}
|
|
@@ -593,26 +665,40 @@ videobuf_qbuf(struct videobuf_queue *q,
|
|
|
|
|
|
mutex_lock(&q->lock);
|
|
|
retval = -EBUSY;
|
|
|
- if (q->reading)
|
|
|
+ if (q->reading) {
|
|
|
+ dprintk(1,"qbuf: Reading running...\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
retval = -EINVAL;
|
|
|
- if (b->type != q->type)
|
|
|
+ if (b->type != q->type) {
|
|
|
+ dprintk(1,"qbuf: Wrong type.\n");
|
|
|
goto done;
|
|
|
- if (b->index < 0 || b->index >= VIDEO_MAX_FRAME)
|
|
|
+ }
|
|
|
+ if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {
|
|
|
+ dprintk(1,"qbuf: index out of range.\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
buf = q->bufs[b->index];
|
|
|
- if (NULL == buf)
|
|
|
+ if (NULL == buf) {
|
|
|
+ dprintk(1,"qbuf: buffer is null.\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
MAGIC_CHECK(buf->magic,MAGIC_BUFFER);
|
|
|
- if (buf->memory != b->memory)
|
|
|
+ if (buf->memory != b->memory) {
|
|
|
+ dprintk(1,"qbuf: memory type is wrong.\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
if (buf->state == STATE_QUEUED ||
|
|
|
- buf->state == STATE_ACTIVE)
|
|
|
+ buf->state == STATE_ACTIVE) {
|
|
|
+ dprintk(1,"qbuf: buffer is already queued or active.\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
|
|
|
if (b->flags & V4L2_BUF_FLAG_INPUT) {
|
|
|
- if (b->input >= q->inputs)
|
|
|
+ if (b->input >= q->inputs) {
|
|
|
+ dprintk(1,"qbuf: wrong input.\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
buf->input = b->input;
|
|
|
} else {
|
|
|
buf->input = UNSET;
|
|
@@ -620,12 +706,16 @@ videobuf_qbuf(struct videobuf_queue *q,
|
|
|
|
|
|
switch (b->memory) {
|
|
|
case V4L2_MEMORY_MMAP:
|
|
|
- if (0 == buf->baddr)
|
|
|
+ if (0 == buf->baddr) {
|
|
|
+ dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
break;
|
|
|
case V4L2_MEMORY_USERPTR:
|
|
|
- if (b->length < buf->bsize)
|
|
|
+ if (b->length < buf->bsize) {
|
|
|
+ dprintk(1,"qbuf: buffer length is not enough\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr)
|
|
|
q->ops->buf_release(q,buf);
|
|
|
buf->baddr = b->m.userptr;
|
|
@@ -634,20 +724,27 @@ videobuf_qbuf(struct videobuf_queue *q,
|
|
|
buf->boff = b->m.offset;
|
|
|
break;
|
|
|
default:
|
|
|
+ dprintk(1,"qbuf: wrong memory type\n");
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
+ dprintk(1,"qbuf: requesting next field\n");
|
|
|
field = videobuf_next_field(q);
|
|
|
retval = q->ops->buf_prepare(q,buf,field);
|
|
|
- if (0 != retval)
|
|
|
+ if (0 != retval) {
|
|
|
+ dprintk(1,"qbuf: buffer_prepare returned %d\n",retval);
|
|
|
goto done;
|
|
|
+ }
|
|
|
|
|
|
list_add_tail(&buf->stream,&q->stream);
|
|
|
if (q->streaming) {
|
|
|
- spin_lock_irqsave(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_lock_irqsave(q->irqlock,flags);
|
|
|
q->ops->buf_queue(q,buf);
|
|
|
- spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
}
|
|
|
+ dprintk(1,"qbuf: succeded\n");
|
|
|
retval = 0;
|
|
|
|
|
|
done:
|
|
@@ -664,26 +761,39 @@ videobuf_dqbuf(struct videobuf_queue *q,
|
|
|
|
|
|
mutex_lock(&q->lock);
|
|
|
retval = -EBUSY;
|
|
|
- if (q->reading)
|
|
|
+ if (q->reading) {
|
|
|
+ dprintk(1,"dqbuf: Reading running...\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
retval = -EINVAL;
|
|
|
- if (b->type != q->type)
|
|
|
+ if (b->type != q->type) {
|
|
|
+ dprintk(1,"dqbuf: Wrong type.\n");
|
|
|
goto done;
|
|
|
- if (list_empty(&q->stream))
|
|
|
+ }
|
|
|
+ if (list_empty(&q->stream)) {
|
|
|
+ dprintk(1,"dqbuf: stream running\n");
|
|
|
goto done;
|
|
|
+ }
|
|
|
buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
|
|
|
retval = videobuf_waiton(buf, nonblocking, 1);
|
|
|
- if (retval < 0)
|
|
|
+ if (retval < 0) {
|
|
|
+ dprintk(1,"dqbuf: waiton returned %d\n",retval);
|
|
|
goto done;
|
|
|
+ }
|
|
|
switch (buf->state) {
|
|
|
case STATE_ERROR:
|
|
|
+ dprintk(1,"dqbuf: state is error\n");
|
|
|
retval = -EIO;
|
|
|
- /* fall through */
|
|
|
+ videobuf_dma_sync(q,&buf->dma);
|
|
|
+ buf->state = STATE_IDLE;
|
|
|
+ break;
|
|
|
case STATE_DONE:
|
|
|
- videobuf_dma_pci_sync(q->pci,&buf->dma);
|
|
|
+ dprintk(1,"dqbuf: state is done\n");
|
|
|
+ videobuf_dma_sync(q,&buf->dma);
|
|
|
buf->state = STATE_IDLE;
|
|
|
break;
|
|
|
default:
|
|
|
+ dprintk(1,"dqbuf: state invalid\n");
|
|
|
retval = -EINVAL;
|
|
|
goto done;
|
|
|
}
|
|
@@ -711,13 +821,15 @@ int videobuf_streamon(struct videobuf_queue *q)
|
|
|
if (q->streaming)
|
|
|
goto done;
|
|
|
q->streaming = 1;
|
|
|
- spin_lock_irqsave(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_lock_irqsave(q->irqlock,flags);
|
|
|
list_for_each(list,&q->stream) {
|
|
|
buf = list_entry(list, struct videobuf_buffer, stream);
|
|
|
if (buf->state == STATE_PREPARED)
|
|
|
q->ops->buf_queue(q,buf);
|
|
|
}
|
|
|
- spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
|
|
|
done:
|
|
|
mutex_unlock(&q->lock);
|
|
@@ -762,12 +874,14 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data,
|
|
|
goto done;
|
|
|
|
|
|
/* start capture & wait */
|
|
|
- spin_lock_irqsave(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_lock_irqsave(q->irqlock,flags);
|
|
|
q->ops->buf_queue(q,q->read_buf);
|
|
|
- spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
retval = videobuf_waiton(q->read_buf,0,0);
|
|
|
if (0 == retval) {
|
|
|
- videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
|
|
|
+ videobuf_dma_sync(q,&q->read_buf->dma);
|
|
|
if (STATE_ERROR == q->read_buf->state)
|
|
|
retval = -EIO;
|
|
|
else
|
|
@@ -809,6 +923,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
|
|
|
/* need to capture a new frame */
|
|
|
retval = -ENOMEM;
|
|
|
q->read_buf = videobuf_alloc(q->msize);
|
|
|
+ dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf);
|
|
|
if (NULL == q->read_buf)
|
|
|
goto done;
|
|
|
q->read_buf->memory = V4L2_MEMORY_USERPTR;
|
|
@@ -820,9 +935,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
|
|
|
q->read_buf = NULL;
|
|
|
goto done;
|
|
|
}
|
|
|
- spin_lock_irqsave(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_lock_irqsave(q->irqlock,flags);
|
|
|
q->ops->buf_queue(q,q->read_buf);
|
|
|
- spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
q->read_off = 0;
|
|
|
}
|
|
|
|
|
@@ -830,7 +947,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
|
|
|
retval = videobuf_waiton(q->read_buf, nonblocking, 1);
|
|
|
if (0 != retval)
|
|
|
goto done;
|
|
|
- videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
|
|
|
+ videobuf_dma_sync(q,&q->read_buf->dma);
|
|
|
|
|
|
if (STATE_ERROR == q->read_buf->state) {
|
|
|
/* catch I/O errors */
|
|
@@ -887,10 +1004,12 @@ int videobuf_read_start(struct videobuf_queue *q)
|
|
|
return err;
|
|
|
list_add_tail(&q->bufs[i]->stream, &q->stream);
|
|
|
}
|
|
|
- spin_lock_irqsave(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_lock_irqsave(q->irqlock,flags);
|
|
|
for (i = 0; i < count; i++)
|
|
|
q->ops->buf_queue(q,q->bufs[i]);
|
|
|
- spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
q->reading = 1;
|
|
|
return 0;
|
|
|
}
|
|
@@ -985,9 +1104,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
|
|
|
if (q->read_off == q->read_buf->size) {
|
|
|
list_add_tail(&q->read_buf->stream,
|
|
|
&q->stream);
|
|
|
- spin_lock_irqsave(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_lock_irqsave(q->irqlock,flags);
|
|
|
q->ops->buf_queue(q,q->read_buf);
|
|
|
- spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
+ if (q->irqlock)
|
|
|
+ spin_unlock_irqrestore(q->irqlock,flags);
|
|
|
q->read_buf = NULL;
|
|
|
}
|
|
|
if (retval < 0)
|
|
@@ -1249,11 +1370,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_init);
|
|
|
EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
|
|
|
EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
|
|
|
EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay);
|
|
|
-EXPORT_SYMBOL_GPL(videobuf_dma_pci_map);
|
|
|
-EXPORT_SYMBOL_GPL(videobuf_dma_pci_sync);
|
|
|
-EXPORT_SYMBOL_GPL(videobuf_dma_pci_unmap);
|
|
|
+EXPORT_SYMBOL_GPL(videobuf_dma_map);
|
|
|
+EXPORT_SYMBOL_GPL(videobuf_dma_sync);
|
|
|
+EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
|
|
|
EXPORT_SYMBOL_GPL(videobuf_dma_free);
|
|
|
|
|
|
+EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
|
|
|
+EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
|
|
|
+
|
|
|
EXPORT_SYMBOL_GPL(videobuf_alloc);
|
|
|
EXPORT_SYMBOL_GPL(videobuf_waiton);
|
|
|
EXPORT_SYMBOL_GPL(videobuf_iolock);
|