[media] V4L: Add mem2mem ioctl and file operation helpers

This patch adds ioctl helpers to the V4L2 mem-to-mem API, so we can avoid
several ioctl handlers in the mem-to-mem video node drivers that are simply
a pass-through to the v4l2_m2m_* calls. These helpers will only be useful
for drivers that use same mutex for both OUTPUT and CAPTURE queue, which
is the case for all currently in tree v4l2 m2m drivers. In order to use
the helpers the drivers are required to use struct v4l2_fh.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Sylwester Nawrocki 2013-09-14 18:39:04 -03:00 committed by Mauro Carvalho Chehab
parent 2e1ab9cb94
commit 8e6e8f93f7
3 changed files with 154 additions and 0 deletions

View File

@ -558,6 +558,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
if (m2m_ctx->m2m_dev->m2m_ops->unlock)
m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv);
else if (m2m_ctx->q_lock)
mutex_unlock(m2m_ctx->q_lock);
if (list_empty(&src_q->done_list))
poll_wait(file, &src_q->done_wq, wait);
@ -566,6 +568,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
if (m2m_ctx->m2m_dev->m2m_ops->lock)
m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
else if (m2m_ctx->q_lock)
mutex_lock(m2m_ctx->q_lock);
spin_lock_irqsave(&src_q->done_lock, flags);
if (!list_empty(&src_q->done_list))
@ -693,6 +697,13 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
if (ret)
goto err;
/*
* If both queues use same mutex assign it as the common buffer
* queues lock to the m2m context. This lock is used in the
* v4l2_m2m_ioctl_* helpers.
*/
if (out_q_ctx->q.lock == cap_q_ctx->q.lock)
m2m_ctx->q_lock = out_q_ctx->q.lock;
return m2m_ctx;
err:
@ -740,3 +751,118 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb)
}
EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
/* Videobuf2 ioctl helpers */
int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *rb)
{
struct v4l2_fh *fh = file->private_data;
return v4l2_m2m_reqbufs(file, fh->m2m_ctx, rb);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_reqbufs);
int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv,
struct v4l2_create_buffers *create)
{
struct v4l2_fh *fh = file->private_data;
return v4l2_m2m_create_bufs(file, fh->m2m_ctx, create);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_create_bufs);
int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
struct v4l2_fh *fh = file->private_data;
return v4l2_m2m_querybuf(file, fh->m2m_ctx, buf);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_querybuf);
int v4l2_m2m_ioctl_qbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
struct v4l2_fh *fh = file->private_data;
return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_qbuf);
int v4l2_m2m_ioctl_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
struct v4l2_fh *fh = file->private_data;
return v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_dqbuf);
int v4l2_m2m_ioctl_expbuf(struct file *file, void *priv,
struct v4l2_exportbuffer *eb)
{
struct v4l2_fh *fh = file->private_data;
return v4l2_m2m_expbuf(file, fh->m2m_ctx, eb);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_expbuf);
int v4l2_m2m_ioctl_streamon(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct v4l2_fh *fh = file->private_data;
return v4l2_m2m_streamon(file, fh->m2m_ctx, type);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamon);
int v4l2_m2m_ioctl_streamoff(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct v4l2_fh *fh = file->private_data;
return v4l2_m2m_streamoff(file, fh->m2m_ctx, type);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamoff);
/*
* v4l2_file_operations helpers. It is assumed here same lock is used
* for the output and the capture buffer queue.
*/
int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma)
{
struct v4l2_fh *fh = file->private_data;
struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx;
int ret;
if (m2m_ctx->q_lock && mutex_lock_interruptible(m2m_ctx->q_lock))
return -ERESTARTSYS;
ret = v4l2_m2m_mmap(file, m2m_ctx, vma);
if (m2m_ctx->q_lock)
mutex_unlock(m2m_ctx->q_lock);
return ret;
}
EXPORT_SYMBOL_GPL(v4l2_m2m_fop_mmap);
unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait)
{
struct v4l2_fh *fh = file->private_data;
struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx;
unsigned int ret;
if (m2m_ctx->q_lock)
mutex_lock(m2m_ctx->q_lock);
ret = v4l2_m2m_poll(file, m2m_ctx, wait);
if (m2m_ctx->q_lock)
mutex_unlock(m2m_ctx->q_lock);
return ret;
}
EXPORT_SYMBOL_GPL(v4l2_m2m_fop_poll);

View File

@ -45,6 +45,10 @@ struct v4l2_fh {
struct list_head available; /* Dequeueable event */
unsigned int navailable;
u32 sequence;
#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV)
struct v4l2_m2m_ctx *m2m_ctx;
#endif
};
/*

View File

@ -64,6 +64,9 @@ struct v4l2_m2m_queue_ctx {
};
struct v4l2_m2m_ctx {
/* optional cap/out vb2 queues lock */
struct mutex *q_lock;
/* private: internal use only */
struct v4l2_m2m_dev *m2m_dev;
@ -229,5 +232,26 @@ static inline void *v4l2_m2m_dst_buf_remove(struct v4l2_m2m_ctx *m2m_ctx)
return v4l2_m2m_buf_remove(&m2m_ctx->cap_q_ctx);
}
/* v4l2 ioctl helpers */
int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *rb);
int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh,
struct v4l2_create_buffers *create);
int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh,
struct v4l2_buffer *buf);
int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh,
struct v4l2_exportbuffer *eb);
int v4l2_m2m_ioctl_qbuf(struct file *file, void *fh,
struct v4l2_buffer *buf);
int v4l2_m2m_ioctl_dqbuf(struct file *file, void *fh,
struct v4l2_buffer *buf);
int v4l2_m2m_ioctl_streamon(struct file *file, void *fh,
enum v4l2_buf_type type);
int v4l2_m2m_ioctl_streamoff(struct file *file, void *fh,
enum v4l2_buf_type type);
int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma);
unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait);
#endif /* _MEDIA_V4L2_MEM2MEM_H */