Commit 83ae7c5a1b5b5cd4380ff70797e4c5dcfb61a70d
Committed by
Mauro Carvalho Chehab
1 parent
19b6ef5164
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
[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>
Showing 4 changed files with 103 additions and 0 deletions Side-by-side Diff
drivers/media/v4l2-core/v4l2-mem2mem.c
... | ... | @@ -369,6 +369,19 @@ |
369 | 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 | 385 | * v4l2_m2m_streamon() - turn on streaming for a video queue |
373 | 386 | */ |
374 | 387 | int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
drivers/media/v4l2-core/videobuf2-core.c
... | ... | @@ -1751,6 +1751,79 @@ |
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 | 1827 | * vb2_mmap() - map video buffers into application address space |
1755 | 1828 | * @q: videobuf2 queue |
1756 | 1829 | * @vma: vma passed to the mmap file operation handler in the driver |
... | ... | @@ -2455,6 +2528,16 @@ |
2455 | 2528 | return vb2_streamoff(vdev->queue, i); |
2456 | 2529 | } |
2457 | 2530 | EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff); |
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); | |
2458 | 2541 | |
2459 | 2542 | /* v4l2_file_operations helpers */ |
2460 | 2543 |
include/media/v4l2-mem2mem.h
... | ... | @@ -111,6 +111,9 @@ |
111 | 111 | int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
112 | 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 | 117 | int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
115 | 118 | enum v4l2_buf_type type); |
116 | 119 | int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, |
include/media/videobuf2-core.h
... | ... | @@ -81,6 +81,7 @@ |
81 | 81 | struct vb2_mem_ops { |
82 | 82 | void *(*alloc)(void *alloc_ctx, unsigned long size); |
83 | 83 | void (*put)(void *buf_priv); |
84 | + struct dma_buf *(*get_dmabuf)(void *buf_priv); | |
84 | 85 | |
85 | 86 | void *(*get_userptr)(void *alloc_ctx, unsigned long vaddr, |
86 | 87 | unsigned long size, int write); |
... | ... | @@ -363,6 +364,7 @@ |
363 | 364 | void vb2_queue_release(struct vb2_queue *q); |
364 | 365 | |
365 | 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 | 368 | int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking); |
367 | 369 | |
368 | 370 | int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type); |
... | ... | @@ -472,6 +474,8 @@ |
472 | 474 | int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p); |
473 | 475 | int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i); |
474 | 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 | 480 | /* struct v4l2_file_operations helpers */ |
477 | 481 |