diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-03-10 10:29:15 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-03-24 14:26:49 -0500 |
commit | c7b0ac0546985fc6361a8d92cf808d46da797677 (patch) | |
tree | 2147eb2f6dd7b2b82e0d7b4b9a26e12ef5193252 /drivers/media/video/video-buf.c | |
parent | b2fd16b4ff2508ac16ae994f4bcd941f97754c00 (diff) |
V4L/DVB (3516): Make video_buf more generic
Video_buf were concerned to allow PCI devices to be used as
video capture devices. This patch extends video_buf features
by virtualizing pci-dependent functions and allowing other
type of devices to use it.
It is still DMA centric, although it may be used also by
devices that emulates scatter/gather behavior or a DMA device
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/video-buf.c')
-rw-r--r-- | drivers/media/video/video-buf.c | 250 |
1 files changed, 187 insertions, 63 deletions
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 87e937581d5a..d2ca0f08d0df 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c | |||
@@ -1,15 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * generic helper functions for video4linux capture buffers, to handle | 3 | * generic helper functions for video4linux capture buffers, to handle |
4 | * memory management and PCI DMA. Right now bttv + saa7134 use it. | 4 | * memory management and PCI DMA. |
5 | * Right now, bttv, saa7134, saa7146 and cx88 use it. | ||
5 | * | 6 | * |
6 | * The functions expect the hardware being able to scatter gatter | 7 | * The functions expect the hardware being able to scatter gatter |
7 | * (i.e. the buffers are not linear in physical memory, but fragmented | 8 | * (i.e. the buffers are not linear in physical memory, but fragmented |
8 | * into PAGE_SIZE chunks). They also assume the driver does not need | 9 | * into PAGE_SIZE chunks). They also assume the driver does not need |
9 | * to touch the video data (thus it is probably not useful for USB 1.1 | 10 | * to touch the video data. |
10 | * as data often must be uncompressed by the drivers). | 11 | * |
12 | * device specific map/unmap/sync stuff now are mapped as operations | ||
13 | * to allow its usage by USB and virtual devices. | ||
11 | * | 14 | * |
12 | * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] | 15 | * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] |
16 | * (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
17 | * (c) 2006 Ted Walther and John Sokol | ||
13 | * | 18 | * |
14 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by | 20 | * 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, | |||
167 | dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); | 172 | dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); |
168 | return -ENOMEM; | 173 | return -ENOMEM; |
169 | } | 174 | } |
175 | dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", | ||
176 | (unsigned long)dma->vmalloc, | ||
177 | nr_pages << PAGE_SHIFT); | ||
170 | memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); | 178 | memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); |
171 | dma->nr_pages = nr_pages; | 179 | dma->nr_pages = nr_pages; |
172 | return 0; | 180 | return 0; |
@@ -186,8 +194,10 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, | |||
186 | return 0; | 194 | return 0; |
187 | } | 195 | } |
188 | 196 | ||
189 | int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) | 197 | int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) |
190 | { | 198 | { |
199 | void *dev=q->dev; | ||
200 | |||
191 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | 201 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); |
192 | BUG_ON(0 == dma->nr_pages); | 202 | BUG_ON(0 == dma->nr_pages); |
193 | 203 | ||
@@ -197,7 +207,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) | |||
197 | } | 207 | } |
198 | if (dma->vmalloc) { | 208 | if (dma->vmalloc) { |
199 | dma->sglist = videobuf_vmalloc_to_sg | 209 | dma->sglist = videobuf_vmalloc_to_sg |
200 | (dma->vmalloc,dma->nr_pages); | 210 | (dma->vmalloc,dma->nr_pages); |
201 | } | 211 | } |
202 | if (dma->bus_addr) { | 212 | if (dma->bus_addr) { |
203 | dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); | 213 | 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) | |||
212 | dprintk(1,"scatterlist is NULL\n"); | 222 | dprintk(1,"scatterlist is NULL\n"); |
213 | return -ENOMEM; | 223 | return -ENOMEM; |
214 | } | 224 | } |
215 | |||
216 | if (!dma->bus_addr) { | 225 | if (!dma->bus_addr) { |
217 | dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages, | 226 | if (q->ops->vb_map_sg) { |
218 | dma->direction); | 227 | dma->sglen = q->ops->vb_map_sg(dev,dma->sglist, |
228 | dma->nr_pages, dma->direction); | ||
229 | } | ||
219 | if (0 == dma->sglen) { | 230 | if (0 == dma->sglen) { |
220 | printk(KERN_WARNING | 231 | printk(KERN_WARNING |
221 | "%s: pci_map_sg failed\n",__FUNCTION__); | 232 | "%s: videobuf_map_sg failed\n",__FUNCTION__); |
222 | kfree(dma->sglist); | 233 | kfree(dma->sglist); |
223 | dma->sglist = NULL; | 234 | dma->sglist = NULL; |
224 | dma->sglen = 0; | 235 | dma->sglen = 0; |
@@ -228,24 +239,31 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) | |||
228 | return 0; | 239 | return 0; |
229 | } | 240 | } |
230 | 241 | ||
231 | int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma) | 242 | int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma) |
232 | { | 243 | { |
244 | void *dev=q->dev; | ||
245 | |||
233 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | 246 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); |
234 | BUG_ON(!dma->sglen); | 247 | BUG_ON(!dma->sglen); |
235 | 248 | ||
236 | if (!dma->bus_addr) | 249 | if (!dma->bus_addr && q->ops->vb_dma_sync_sg) |
237 | pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction); | 250 | q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages, |
251 | dma->direction); | ||
252 | |||
238 | return 0; | 253 | return 0; |
239 | } | 254 | } |
240 | 255 | ||
241 | int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma) | 256 | int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) |
242 | { | 257 | { |
258 | void *dev=q->dev; | ||
259 | |||
243 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | 260 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); |
244 | if (!dma->sglen) | 261 | if (!dma->sglen) |
245 | return 0; | 262 | return 0; |
246 | 263 | ||
247 | if (!dma->bus_addr) | 264 | if (!dma->bus_addr && q->ops->vb_unmap_sg) |
248 | pci_unmap_sg(dev,dma->sglist,dma->nr_pages,dma->direction); | 265 | q->ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages, |
266 | dma->direction); | ||
249 | kfree(dma->sglist); | 267 | kfree(dma->sglist); |
250 | dma->sglist = NULL; | 268 | dma->sglist = NULL; |
251 | dma->sglen = 0; | 269 | dma->sglen = 0; |
@@ -318,7 +336,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) | |||
318 | } | 336 | } |
319 | 337 | ||
320 | int | 338 | int |
321 | videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, | 339 | videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, |
322 | struct v4l2_framebuffer *fbuf) | 340 | struct v4l2_framebuffer *fbuf) |
323 | { | 341 | { |
324 | int err,pages; | 342 | int err,pages; |
@@ -357,7 +375,7 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, | |||
357 | default: | 375 | default: |
358 | BUG(); | 376 | BUG(); |
359 | } | 377 | } |
360 | err = videobuf_dma_pci_map(pci,&vb->dma); | 378 | err = videobuf_dma_map(q,&vb->dma); |
361 | if (0 != err) | 379 | if (0 != err) |
362 | return err; | 380 | return err; |
363 | 381 | ||
@@ -366,9 +384,41 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, | |||
366 | 384 | ||
367 | /* --------------------------------------------------------------------- */ | 385 | /* --------------------------------------------------------------------- */ |
368 | 386 | ||
387 | void videobuf_queue_pci(struct videobuf_queue* q) | ||
388 | { | ||
389 | /* If not specified, defaults to PCI map sg */ | ||
390 | if (!q->ops->vb_map_sg) | ||
391 | q->ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg; | ||
392 | |||
393 | if (!q->ops->vb_dma_sync_sg) | ||
394 | q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu; | ||
395 | if (!q->ops->vb_unmap_sg) | ||
396 | q->ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; | ||
397 | } | ||
398 | |||
399 | int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) | ||
400 | { | ||
401 | struct videobuf_queue q; | ||
402 | |||
403 | q.dev=pci; | ||
404 | q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg; | ||
405 | |||
406 | return (videobuf_dma_unmap(&q,dma)); | ||
407 | } | ||
408 | |||
409 | int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) | ||
410 | { | ||
411 | struct videobuf_queue q; | ||
412 | |||
413 | q.dev=pci; | ||
414 | q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg; | ||
415 | |||
416 | return (videobuf_dma_unmap(&q,dma)); | ||
417 | } | ||
418 | |||
369 | void videobuf_queue_init(struct videobuf_queue* q, | 419 | void videobuf_queue_init(struct videobuf_queue* q, |
370 | struct videobuf_queue_ops *ops, | 420 | struct videobuf_queue_ops *ops, |
371 | struct pci_dev *pci, | 421 | void *dev, |
372 | spinlock_t *irqlock, | 422 | spinlock_t *irqlock, |
373 | enum v4l2_buf_type type, | 423 | enum v4l2_buf_type type, |
374 | enum v4l2_field field, | 424 | enum v4l2_field field, |
@@ -377,13 +427,15 @@ void videobuf_queue_init(struct videobuf_queue* q, | |||
377 | { | 427 | { |
378 | memset(q,0,sizeof(*q)); | 428 | memset(q,0,sizeof(*q)); |
379 | q->irqlock = irqlock; | 429 | q->irqlock = irqlock; |
380 | q->pci = pci; | 430 | q->dev = dev; |
381 | q->type = type; | 431 | q->type = type; |
382 | q->field = field; | 432 | q->field = field; |
383 | q->msize = msize; | 433 | q->msize = msize; |
384 | q->ops = ops; | 434 | q->ops = ops; |
385 | q->priv_data = priv; | 435 | q->priv_data = priv; |
386 | 436 | ||
437 | videobuf_queue_pci(q); | ||
438 | |||
387 | mutex_init(&q->lock); | 439 | mutex_init(&q->lock); |
388 | INIT_LIST_HEAD(&q->stream); | 440 | INIT_LIST_HEAD(&q->stream); |
389 | } | 441 | } |
@@ -431,7 +483,8 @@ videobuf_queue_cancel(struct videobuf_queue *q) | |||
431 | int i; | 483 | int i; |
432 | 484 | ||
433 | /* remove queued buffers from list */ | 485 | /* remove queued buffers from list */ |
434 | spin_lock_irqsave(q->irqlock,flags); | 486 | if (q->irqlock) |
487 | spin_lock_irqsave(q->irqlock,flags); | ||
435 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | 488 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { |
436 | if (NULL == q->bufs[i]) | 489 | if (NULL == q->bufs[i]) |
437 | continue; | 490 | continue; |
@@ -440,7 +493,8 @@ videobuf_queue_cancel(struct videobuf_queue *q) | |||
440 | q->bufs[i]->state = STATE_ERROR; | 493 | q->bufs[i]->state = STATE_ERROR; |
441 | } | 494 | } |
442 | } | 495 | } |
443 | spin_unlock_irqrestore(q->irqlock,flags); | 496 | if (q->irqlock) |
497 | spin_unlock_irqrestore(q->irqlock,flags); | ||
444 | 498 | ||
445 | /* free all buffers + clear queue */ | 499 | /* free all buffers + clear queue */ |
446 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | 500 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { |
@@ -534,19 +588,29 @@ videobuf_reqbufs(struct videobuf_queue *q, | |||
534 | unsigned int size,count; | 588 | unsigned int size,count; |
535 | int retval; | 589 | int retval; |
536 | 590 | ||
537 | if (req->type != q->type) | 591 | if (req->type != q->type) { |
592 | dprintk(1,"reqbufs: queue type invalid\n"); | ||
538 | return -EINVAL; | 593 | return -EINVAL; |
539 | if (req->count < 1) | 594 | } |
595 | if (req->count < 1) { | ||
596 | dprintk(1,"reqbufs: count invalid (%d)\n",req->count); | ||
540 | return -EINVAL; | 597 | return -EINVAL; |
598 | } | ||
541 | if (req->memory != V4L2_MEMORY_MMAP && | 599 | if (req->memory != V4L2_MEMORY_MMAP && |
542 | req->memory != V4L2_MEMORY_USERPTR && | 600 | req->memory != V4L2_MEMORY_USERPTR && |
543 | req->memory != V4L2_MEMORY_OVERLAY) | 601 | req->memory != V4L2_MEMORY_OVERLAY) { |
602 | dprintk(1,"reqbufs: memory type invalid\n"); | ||
544 | return -EINVAL; | 603 | return -EINVAL; |
604 | } | ||
545 | 605 | ||
546 | if (q->streaming) | 606 | if (q->streaming) { |
607 | dprintk(1,"reqbufs: streaming already exists\n"); | ||
547 | return -EBUSY; | 608 | return -EBUSY; |
548 | if (!list_empty(&q->stream)) | 609 | } |
610 | if (!list_empty(&q->stream)) { | ||
611 | dprintk(1,"reqbufs: stream running\n"); | ||
549 | return -EBUSY; | 612 | return -EBUSY; |
613 | } | ||
550 | 614 | ||
551 | mutex_lock(&q->lock); | 615 | mutex_lock(&q->lock); |
552 | count = req->count; | 616 | count = req->count; |
@@ -559,8 +623,10 @@ videobuf_reqbufs(struct videobuf_queue *q, | |||
559 | count, size, (count*size)>>PAGE_SHIFT); | 623 | count, size, (count*size)>>PAGE_SHIFT); |
560 | 624 | ||
561 | retval = videobuf_mmap_setup(q,count,size,req->memory); | 625 | retval = videobuf_mmap_setup(q,count,size,req->memory); |
562 | if (retval < 0) | 626 | if (retval < 0) { |
627 | dprintk(1,"reqbufs: mmap setup returned %d\n",retval); | ||
563 | goto done; | 628 | goto done; |
629 | } | ||
564 | 630 | ||
565 | req->count = count; | 631 | req->count = count; |
566 | 632 | ||
@@ -572,12 +638,18 @@ videobuf_reqbufs(struct videobuf_queue *q, | |||
572 | int | 638 | int |
573 | videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) | 639 | videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) |
574 | { | 640 | { |
575 | if (unlikely(b->type != q->type)) | 641 | if (unlikely(b->type != q->type)) { |
642 | dprintk(1,"querybuf: Wrong type.\n"); | ||
576 | return -EINVAL; | 643 | return -EINVAL; |
577 | if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) | 644 | } |
645 | if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) { | ||
646 | dprintk(1,"querybuf: index out of range.\n"); | ||
578 | return -EINVAL; | 647 | return -EINVAL; |
579 | if (unlikely(NULL == q->bufs[b->index])) | 648 | } |
649 | if (unlikely(NULL == q->bufs[b->index])) { | ||
650 | dprintk(1,"querybuf: buffer is null.\n"); | ||
580 | return -EINVAL; | 651 | return -EINVAL; |
652 | } | ||
581 | videobuf_status(b,q->bufs[b->index],q->type); | 653 | videobuf_status(b,q->bufs[b->index],q->type); |
582 | return 0; | 654 | return 0; |
583 | } | 655 | } |
@@ -593,26 +665,40 @@ videobuf_qbuf(struct videobuf_queue *q, | |||
593 | 665 | ||
594 | mutex_lock(&q->lock); | 666 | mutex_lock(&q->lock); |
595 | retval = -EBUSY; | 667 | retval = -EBUSY; |
596 | if (q->reading) | 668 | if (q->reading) { |
669 | dprintk(1,"qbuf: Reading running...\n"); | ||
597 | goto done; | 670 | goto done; |
671 | } | ||
598 | retval = -EINVAL; | 672 | retval = -EINVAL; |
599 | if (b->type != q->type) | 673 | if (b->type != q->type) { |
674 | dprintk(1,"qbuf: Wrong type.\n"); | ||
600 | goto done; | 675 | goto done; |
601 | if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) | 676 | } |
677 | if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) { | ||
678 | dprintk(1,"qbuf: index out of range.\n"); | ||
602 | goto done; | 679 | goto done; |
680 | } | ||
603 | buf = q->bufs[b->index]; | 681 | buf = q->bufs[b->index]; |
604 | if (NULL == buf) | 682 | if (NULL == buf) { |
683 | dprintk(1,"qbuf: buffer is null.\n"); | ||
605 | goto done; | 684 | goto done; |
685 | } | ||
606 | MAGIC_CHECK(buf->magic,MAGIC_BUFFER); | 686 | MAGIC_CHECK(buf->magic,MAGIC_BUFFER); |
607 | if (buf->memory != b->memory) | 687 | if (buf->memory != b->memory) { |
688 | dprintk(1,"qbuf: memory type is wrong.\n"); | ||
608 | goto done; | 689 | goto done; |
690 | } | ||
609 | if (buf->state == STATE_QUEUED || | 691 | if (buf->state == STATE_QUEUED || |
610 | buf->state == STATE_ACTIVE) | 692 | buf->state == STATE_ACTIVE) { |
693 | dprintk(1,"qbuf: buffer is already queued or active.\n"); | ||
611 | goto done; | 694 | goto done; |
695 | } | ||
612 | 696 | ||
613 | if (b->flags & V4L2_BUF_FLAG_INPUT) { | 697 | if (b->flags & V4L2_BUF_FLAG_INPUT) { |
614 | if (b->input >= q->inputs) | 698 | if (b->input >= q->inputs) { |
699 | dprintk(1,"qbuf: wrong input.\n"); | ||
615 | goto done; | 700 | goto done; |
701 | } | ||
616 | buf->input = b->input; | 702 | buf->input = b->input; |
617 | } else { | 703 | } else { |
618 | buf->input = UNSET; | 704 | buf->input = UNSET; |
@@ -620,12 +706,16 @@ videobuf_qbuf(struct videobuf_queue *q, | |||
620 | 706 | ||
621 | switch (b->memory) { | 707 | switch (b->memory) { |
622 | case V4L2_MEMORY_MMAP: | 708 | case V4L2_MEMORY_MMAP: |
623 | if (0 == buf->baddr) | 709 | if (0 == buf->baddr) { |
710 | dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n"); | ||
624 | goto done; | 711 | goto done; |
712 | } | ||
625 | break; | 713 | break; |
626 | case V4L2_MEMORY_USERPTR: | 714 | case V4L2_MEMORY_USERPTR: |
627 | if (b->length < buf->bsize) | 715 | if (b->length < buf->bsize) { |
716 | dprintk(1,"qbuf: buffer length is not enough\n"); | ||
628 | goto done; | 717 | goto done; |
718 | } | ||
629 | if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr) | 719 | if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr) |
630 | q->ops->buf_release(q,buf); | 720 | q->ops->buf_release(q,buf); |
631 | buf->baddr = b->m.userptr; | 721 | buf->baddr = b->m.userptr; |
@@ -634,20 +724,27 @@ videobuf_qbuf(struct videobuf_queue *q, | |||
634 | buf->boff = b->m.offset; | 724 | buf->boff = b->m.offset; |
635 | break; | 725 | break; |
636 | default: | 726 | default: |
727 | dprintk(1,"qbuf: wrong memory type\n"); | ||
637 | goto done; | 728 | goto done; |
638 | } | 729 | } |
639 | 730 | ||
731 | dprintk(1,"qbuf: requesting next field\n"); | ||
640 | field = videobuf_next_field(q); | 732 | field = videobuf_next_field(q); |
641 | retval = q->ops->buf_prepare(q,buf,field); | 733 | retval = q->ops->buf_prepare(q,buf,field); |
642 | if (0 != retval) | 734 | if (0 != retval) { |
735 | dprintk(1,"qbuf: buffer_prepare returned %d\n",retval); | ||
643 | goto done; | 736 | goto done; |
737 | } | ||
644 | 738 | ||
645 | list_add_tail(&buf->stream,&q->stream); | 739 | list_add_tail(&buf->stream,&q->stream); |
646 | if (q->streaming) { | 740 | if (q->streaming) { |
647 | spin_lock_irqsave(q->irqlock,flags); | 741 | if (q->irqlock) |
742 | spin_lock_irqsave(q->irqlock,flags); | ||
648 | q->ops->buf_queue(q,buf); | 743 | q->ops->buf_queue(q,buf); |
649 | spin_unlock_irqrestore(q->irqlock,flags); | 744 | if (q->irqlock) |
745 | spin_unlock_irqrestore(q->irqlock,flags); | ||
650 | } | 746 | } |
747 | dprintk(1,"qbuf: succeded\n"); | ||
651 | retval = 0; | 748 | retval = 0; |
652 | 749 | ||
653 | done: | 750 | done: |
@@ -664,26 +761,39 @@ videobuf_dqbuf(struct videobuf_queue *q, | |||
664 | 761 | ||
665 | mutex_lock(&q->lock); | 762 | mutex_lock(&q->lock); |
666 | retval = -EBUSY; | 763 | retval = -EBUSY; |
667 | if (q->reading) | 764 | if (q->reading) { |
765 | dprintk(1,"dqbuf: Reading running...\n"); | ||
668 | goto done; | 766 | goto done; |
767 | } | ||
669 | retval = -EINVAL; | 768 | retval = -EINVAL; |
670 | if (b->type != q->type) | 769 | if (b->type != q->type) { |
770 | dprintk(1,"dqbuf: Wrong type.\n"); | ||
671 | goto done; | 771 | goto done; |
672 | if (list_empty(&q->stream)) | 772 | } |
773 | if (list_empty(&q->stream)) { | ||
774 | dprintk(1,"dqbuf: stream running\n"); | ||
673 | goto done; | 775 | goto done; |
776 | } | ||
674 | buf = list_entry(q->stream.next, struct videobuf_buffer, stream); | 777 | buf = list_entry(q->stream.next, struct videobuf_buffer, stream); |
675 | retval = videobuf_waiton(buf, nonblocking, 1); | 778 | retval = videobuf_waiton(buf, nonblocking, 1); |
676 | if (retval < 0) | 779 | if (retval < 0) { |
780 | dprintk(1,"dqbuf: waiton returned %d\n",retval); | ||
677 | goto done; | 781 | goto done; |
782 | } | ||
678 | switch (buf->state) { | 783 | switch (buf->state) { |
679 | case STATE_ERROR: | 784 | case STATE_ERROR: |
785 | dprintk(1,"dqbuf: state is error\n"); | ||
680 | retval = -EIO; | 786 | retval = -EIO; |
681 | /* fall through */ | 787 | videobuf_dma_sync(q,&buf->dma); |
788 | buf->state = STATE_IDLE; | ||
789 | break; | ||
682 | case STATE_DONE: | 790 | case STATE_DONE: |
683 | videobuf_dma_pci_sync(q->pci,&buf->dma); | 791 | dprintk(1,"dqbuf: state is done\n"); |
792 | videobuf_dma_sync(q,&buf->dma); | ||
684 | buf->state = STATE_IDLE; | 793 | buf->state = STATE_IDLE; |
685 | break; | 794 | break; |
686 | default: | 795 | default: |
796 | dprintk(1,"dqbuf: state invalid\n"); | ||
687 | retval = -EINVAL; | 797 | retval = -EINVAL; |
688 | goto done; | 798 | goto done; |
689 | } | 799 | } |
@@ -711,13 +821,15 @@ int videobuf_streamon(struct videobuf_queue *q) | |||
711 | if (q->streaming) | 821 | if (q->streaming) |
712 | goto done; | 822 | goto done; |
713 | q->streaming = 1; | 823 | q->streaming = 1; |
714 | spin_lock_irqsave(q->irqlock,flags); | 824 | if (q->irqlock) |
825 | spin_lock_irqsave(q->irqlock,flags); | ||
715 | list_for_each(list,&q->stream) { | 826 | list_for_each(list,&q->stream) { |
716 | buf = list_entry(list, struct videobuf_buffer, stream); | 827 | buf = list_entry(list, struct videobuf_buffer, stream); |
717 | if (buf->state == STATE_PREPARED) | 828 | if (buf->state == STATE_PREPARED) |
718 | q->ops->buf_queue(q,buf); | 829 | q->ops->buf_queue(q,buf); |
719 | } | 830 | } |
720 | spin_unlock_irqrestore(q->irqlock,flags); | 831 | if (q->irqlock) |
832 | spin_unlock_irqrestore(q->irqlock,flags); | ||
721 | 833 | ||
722 | done: | 834 | done: |
723 | mutex_unlock(&q->lock); | 835 | mutex_unlock(&q->lock); |
@@ -762,12 +874,14 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, | |||
762 | goto done; | 874 | goto done; |
763 | 875 | ||
764 | /* start capture & wait */ | 876 | /* start capture & wait */ |
765 | spin_lock_irqsave(q->irqlock,flags); | 877 | if (q->irqlock) |
878 | spin_lock_irqsave(q->irqlock,flags); | ||
766 | q->ops->buf_queue(q,q->read_buf); | 879 | q->ops->buf_queue(q,q->read_buf); |
767 | spin_unlock_irqrestore(q->irqlock,flags); | 880 | if (q->irqlock) |
881 | spin_unlock_irqrestore(q->irqlock,flags); | ||
768 | retval = videobuf_waiton(q->read_buf,0,0); | 882 | retval = videobuf_waiton(q->read_buf,0,0); |
769 | if (0 == retval) { | 883 | if (0 == retval) { |
770 | videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); | 884 | videobuf_dma_sync(q,&q->read_buf->dma); |
771 | if (STATE_ERROR == q->read_buf->state) | 885 | if (STATE_ERROR == q->read_buf->state) |
772 | retval = -EIO; | 886 | retval = -EIO; |
773 | else | 887 | else |
@@ -809,6 +923,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
809 | /* need to capture a new frame */ | 923 | /* need to capture a new frame */ |
810 | retval = -ENOMEM; | 924 | retval = -ENOMEM; |
811 | q->read_buf = videobuf_alloc(q->msize); | 925 | q->read_buf = videobuf_alloc(q->msize); |
926 | dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf); | ||
812 | if (NULL == q->read_buf) | 927 | if (NULL == q->read_buf) |
813 | goto done; | 928 | goto done; |
814 | q->read_buf->memory = V4L2_MEMORY_USERPTR; | 929 | q->read_buf->memory = V4L2_MEMORY_USERPTR; |
@@ -820,9 +935,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
820 | q->read_buf = NULL; | 935 | q->read_buf = NULL; |
821 | goto done; | 936 | goto done; |
822 | } | 937 | } |
823 | spin_lock_irqsave(q->irqlock,flags); | 938 | if (q->irqlock) |
939 | spin_lock_irqsave(q->irqlock,flags); | ||
824 | q->ops->buf_queue(q,q->read_buf); | 940 | q->ops->buf_queue(q,q->read_buf); |
825 | spin_unlock_irqrestore(q->irqlock,flags); | 941 | if (q->irqlock) |
942 | spin_unlock_irqrestore(q->irqlock,flags); | ||
826 | q->read_off = 0; | 943 | q->read_off = 0; |
827 | } | 944 | } |
828 | 945 | ||
@@ -830,7 +947,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
830 | retval = videobuf_waiton(q->read_buf, nonblocking, 1); | 947 | retval = videobuf_waiton(q->read_buf, nonblocking, 1); |
831 | if (0 != retval) | 948 | if (0 != retval) |
832 | goto done; | 949 | goto done; |
833 | videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); | 950 | videobuf_dma_sync(q,&q->read_buf->dma); |
834 | 951 | ||
835 | if (STATE_ERROR == q->read_buf->state) { | 952 | if (STATE_ERROR == q->read_buf->state) { |
836 | /* catch I/O errors */ | 953 | /* catch I/O errors */ |
@@ -887,10 +1004,12 @@ int videobuf_read_start(struct videobuf_queue *q) | |||
887 | return err; | 1004 | return err; |
888 | list_add_tail(&q->bufs[i]->stream, &q->stream); | 1005 | list_add_tail(&q->bufs[i]->stream, &q->stream); |
889 | } | 1006 | } |
890 | spin_lock_irqsave(q->irqlock,flags); | 1007 | if (q->irqlock) |
1008 | spin_lock_irqsave(q->irqlock,flags); | ||
891 | for (i = 0; i < count; i++) | 1009 | for (i = 0; i < count; i++) |
892 | q->ops->buf_queue(q,q->bufs[i]); | 1010 | q->ops->buf_queue(q,q->bufs[i]); |
893 | spin_unlock_irqrestore(q->irqlock,flags); | 1011 | if (q->irqlock) |
1012 | spin_unlock_irqrestore(q->irqlock,flags); | ||
894 | q->reading = 1; | 1013 | q->reading = 1; |
895 | return 0; | 1014 | return 0; |
896 | } | 1015 | } |
@@ -985,9 +1104,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, | |||
985 | if (q->read_off == q->read_buf->size) { | 1104 | if (q->read_off == q->read_buf->size) { |
986 | list_add_tail(&q->read_buf->stream, | 1105 | list_add_tail(&q->read_buf->stream, |
987 | &q->stream); | 1106 | &q->stream); |
988 | spin_lock_irqsave(q->irqlock,flags); | 1107 | if (q->irqlock) |
1108 | spin_lock_irqsave(q->irqlock,flags); | ||
989 | q->ops->buf_queue(q,q->read_buf); | 1109 | q->ops->buf_queue(q,q->read_buf); |
990 | spin_unlock_irqrestore(q->irqlock,flags); | 1110 | if (q->irqlock) |
1111 | spin_unlock_irqrestore(q->irqlock,flags); | ||
991 | q->read_buf = NULL; | 1112 | q->read_buf = NULL; |
992 | } | 1113 | } |
993 | if (retval < 0) | 1114 | if (retval < 0) |
@@ -1249,11 +1370,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_init); | |||
1249 | EXPORT_SYMBOL_GPL(videobuf_dma_init_user); | 1370 | EXPORT_SYMBOL_GPL(videobuf_dma_init_user); |
1250 | EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); | 1371 | EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); |
1251 | EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); | 1372 | EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); |
1252 | EXPORT_SYMBOL_GPL(videobuf_dma_pci_map); | 1373 | EXPORT_SYMBOL_GPL(videobuf_dma_map); |
1253 | EXPORT_SYMBOL_GPL(videobuf_dma_pci_sync); | 1374 | EXPORT_SYMBOL_GPL(videobuf_dma_sync); |
1254 | EXPORT_SYMBOL_GPL(videobuf_dma_pci_unmap); | 1375 | EXPORT_SYMBOL_GPL(videobuf_dma_unmap); |
1255 | EXPORT_SYMBOL_GPL(videobuf_dma_free); | 1376 | EXPORT_SYMBOL_GPL(videobuf_dma_free); |
1256 | 1377 | ||
1378 | EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); | ||
1379 | EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); | ||
1380 | |||
1257 | EXPORT_SYMBOL_GPL(videobuf_alloc); | 1381 | EXPORT_SYMBOL_GPL(videobuf_alloc); |
1258 | EXPORT_SYMBOL_GPL(videobuf_waiton); | 1382 | EXPORT_SYMBOL_GPL(videobuf_waiton); |
1259 | EXPORT_SYMBOL_GPL(videobuf_iolock); | 1383 | EXPORT_SYMBOL_GPL(videobuf_iolock); |