diff options
| author | Tomasz Stanislawski <t.stanislaws@samsung.com> | 2012-06-14 10:32:24 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-11-25 14:21:00 -0500 |
| commit | 83ae7c5a1b5b5cd4380ff70797e4c5dcfb61a70d (patch) | |
| tree | 2b1b4741b24b73c9a61ebe48fb9a399b194e01e0 | |
| parent | 19b6ef51640fb35666884c7b577b1a24a4be8e34 (diff) | |
[media] v4l: vb2: add buffer exporting via dmabuf
This patch adds extension to videobuf2-core. It allow to export an mmap buffer
as a DMABUF file descriptor.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-mem2mem.c | 13 | ||||
| -rw-r--r-- | drivers/media/v4l2-core/videobuf2-core.c | 83 | ||||
| -rw-r--r-- | include/media/v4l2-mem2mem.h | 3 | ||||
| -rw-r--r-- | include/media/videobuf2-core.h | 4 |
4 files changed, 103 insertions, 0 deletions
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 017fed8ad2a..438ea45d107 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | |||
| @@ -369,6 +369,19 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | |||
| 369 | EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf); | 369 | EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf); |
| 370 | 370 | ||
| 371 | /** | 371 | /** |
| 372 | * v4l2_m2m_expbuf() - export a source or destination buffer, depending on | ||
| 373 | * the type | ||
| 374 | */ | ||
| 375 | int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
| 376 | struct v4l2_exportbuffer *eb) | ||
| 377 | { | ||
| 378 | struct vb2_queue *vq; | ||
| 379 | |||
| 380 | vq = v4l2_m2m_get_vq(m2m_ctx, eb->type); | ||
| 381 | return vb2_expbuf(vq, eb); | ||
| 382 | } | ||
| 383 | EXPORT_SYMBOL_GPL(v4l2_m2m_expbuf); | ||
| 384 | /** | ||
| 372 | * v4l2_m2m_streamon() - turn on streaming for a video queue | 385 | * v4l2_m2m_streamon() - turn on streaming for a video queue |
| 373 | */ | 386 | */ |
| 374 | int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | 387 | int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 613dea16a30..9f81be23a81 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
| @@ -1751,6 +1751,79 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off, | |||
| 1751 | } | 1751 | } |
| 1752 | 1752 | ||
| 1753 | /** | 1753 | /** |
| 1754 | * vb2_expbuf() - Export a buffer as a file descriptor | ||
| 1755 | * @q: videobuf2 queue | ||
| 1756 | * @eb: export buffer structure passed from userspace to vidioc_expbuf | ||
| 1757 | * handler in driver | ||
| 1758 | * | ||
| 1759 | * The return values from this function are intended to be directly returned | ||
| 1760 | * from vidioc_expbuf handler in driver. | ||
| 1761 | */ | ||
| 1762 | int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) | ||
| 1763 | { | ||
| 1764 | struct vb2_buffer *vb = NULL; | ||
| 1765 | struct vb2_plane *vb_plane; | ||
| 1766 | int ret; | ||
| 1767 | struct dma_buf *dbuf; | ||
| 1768 | |||
| 1769 | if (q->memory != V4L2_MEMORY_MMAP) { | ||
| 1770 | dprintk(1, "Queue is not currently set up for mmap\n"); | ||
| 1771 | return -EINVAL; | ||
| 1772 | } | ||
| 1773 | |||
| 1774 | if (!q->mem_ops->get_dmabuf) { | ||
| 1775 | dprintk(1, "Queue does not support DMA buffer exporting\n"); | ||
| 1776 | return -EINVAL; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | if (eb->flags & ~O_CLOEXEC) { | ||
| 1780 | dprintk(1, "Queue does support only O_CLOEXEC flag\n"); | ||
| 1781 | return -EINVAL; | ||
| 1782 | } | ||
| 1783 | |||
| 1784 | if (eb->type != q->type) { | ||
| 1785 | dprintk(1, "qbuf: invalid buffer type\n"); | ||
| 1786 | return -EINVAL; | ||
| 1787 | } | ||
| 1788 | |||
| 1789 | if (eb->index >= q->num_buffers) { | ||
| 1790 | dprintk(1, "buffer index out of range\n"); | ||
| 1791 | return -EINVAL; | ||
| 1792 | } | ||
| 1793 | |||
| 1794 | vb = q->bufs[eb->index]; | ||
| 1795 | |||
| 1796 | if (eb->plane >= vb->num_planes) { | ||
| 1797 | dprintk(1, "buffer plane out of range\n"); | ||
| 1798 | return -EINVAL; | ||
| 1799 | } | ||
| 1800 | |||
| 1801 | vb_plane = &vb->planes[eb->plane]; | ||
| 1802 | |||
| 1803 | dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv); | ||
| 1804 | if (IS_ERR_OR_NULL(dbuf)) { | ||
| 1805 | dprintk(1, "Failed to export buffer %d, plane %d\n", | ||
| 1806 | eb->index, eb->plane); | ||
| 1807 | return -EINVAL; | ||
| 1808 | } | ||
| 1809 | |||
| 1810 | ret = dma_buf_fd(dbuf, eb->flags); | ||
| 1811 | if (ret < 0) { | ||
| 1812 | dprintk(3, "buffer %d, plane %d failed to export (%d)\n", | ||
| 1813 | eb->index, eb->plane, ret); | ||
| 1814 | dma_buf_put(dbuf); | ||
| 1815 | return ret; | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | dprintk(3, "buffer %d, plane %d exported as %d descriptor\n", | ||
| 1819 | eb->index, eb->plane, ret); | ||
| 1820 | eb->fd = ret; | ||
| 1821 | |||
| 1822 | return 0; | ||
| 1823 | } | ||
| 1824 | EXPORT_SYMBOL_GPL(vb2_expbuf); | ||
| 1825 | |||
| 1826 | /** | ||
| 1754 | * vb2_mmap() - map video buffers into application address space | 1827 | * vb2_mmap() - map video buffers into application address space |
| 1755 | * @q: videobuf2 queue | 1828 | * @q: videobuf2 queue |
| 1756 | * @vma: vma passed to the mmap file operation handler in the driver | 1829 | * @vma: vma passed to the mmap file operation handler in the driver |
| @@ -2456,6 +2529,16 @@ int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
| 2456 | } | 2529 | } |
| 2457 | EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff); | 2530 | EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff); |
| 2458 | 2531 | ||
| 2532 | int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p) | ||
| 2533 | { | ||
| 2534 | struct video_device *vdev = video_devdata(file); | ||
| 2535 | |||
| 2536 | if (vb2_queue_is_busy(vdev, file)) | ||
| 2537 | return -EBUSY; | ||
| 2538 | return vb2_expbuf(vdev->queue, p); | ||
| 2539 | } | ||
| 2540 | EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf); | ||
| 2541 | |||
| 2459 | /* v4l2_file_operations helpers */ | 2542 | /* v4l2_file_operations helpers */ |
| 2460 | 2543 | ||
| 2461 | int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) | 2544 | int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) |
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index 131cc4a5367..7e82d2b193d 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h | |||
| @@ -111,6 +111,9 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | |||
| 111 | int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | 111 | int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
| 112 | struct v4l2_buffer *buf); | 112 | struct v4l2_buffer *buf); |
| 113 | 113 | ||
| 114 | int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
| 115 | struct v4l2_exportbuffer *eb); | ||
| 116 | |||
| 114 | int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | 117 | int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
| 115 | enum v4l2_buf_type type); | 118 | enum v4l2_buf_type type); |
| 116 | int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | 119 | int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 24b9c90194f..9cfd4ee9e56 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h | |||
| @@ -81,6 +81,7 @@ struct vb2_fileio_data; | |||
| 81 | struct vb2_mem_ops { | 81 | struct vb2_mem_ops { |
| 82 | void *(*alloc)(void *alloc_ctx, unsigned long size); | 82 | void *(*alloc)(void *alloc_ctx, unsigned long size); |
| 83 | void (*put)(void *buf_priv); | 83 | void (*put)(void *buf_priv); |
| 84 | struct dma_buf *(*get_dmabuf)(void *buf_priv); | ||
| 84 | 85 | ||
| 85 | void *(*get_userptr)(void *alloc_ctx, unsigned long vaddr, | 86 | void *(*get_userptr)(void *alloc_ctx, unsigned long vaddr, |
| 86 | unsigned long size, int write); | 87 | unsigned long size, int write); |
| @@ -363,6 +364,7 @@ int __must_check vb2_queue_init(struct vb2_queue *q); | |||
| 363 | void vb2_queue_release(struct vb2_queue *q); | 364 | void vb2_queue_release(struct vb2_queue *q); |
| 364 | 365 | ||
| 365 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b); | 366 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b); |
| 367 | int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb); | ||
| 366 | int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking); | 368 | int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking); |
| 367 | 369 | ||
| 368 | int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type); | 370 | int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type); |
| @@ -472,6 +474,8 @@ int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); | |||
| 472 | int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p); | 474 | int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p); |
| 473 | int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i); | 475 | int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i); |
| 474 | int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i); | 476 | int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i); |
| 477 | int vb2_ioctl_expbuf(struct file *file, void *priv, | ||
| 478 | struct v4l2_exportbuffer *p); | ||
| 475 | 479 | ||
| 476 | /* struct v4l2_file_operations helpers */ | 480 | /* struct v4l2_file_operations helpers */ |
| 477 | 481 | ||
