summaryrefslogtreecommitdiff
path: root/drivers/media/platform/m2m-deinterlace.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/m2m-deinterlace.c')
-rw-r--r--drivers/media/platform/m2m-deinterlace.c303
1 files changed, 95 insertions, 208 deletions
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index 540516ca872c..af098874ead5 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -1,13 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* V4L2 deinterlacing support.
*
* Copyright (c) 2012 Vista Silicon S.L.
* Javier Martin <javier.martin@vista-silicon.com>
- *
- * 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 the
- * Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version
*/
#include <linux/module.h>
@@ -41,7 +37,6 @@ module_param(debug, bool, 0644);
v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
struct deinterlace_fmt {
- char *name;
u32 fourcc;
/* Types the format can be used for */
u32 types;
@@ -49,12 +44,10 @@ struct deinterlace_fmt {
static struct deinterlace_fmt formats[] = {
{
- .name = "YUV 4:2:0 Planar",
.fourcc = V4L2_PIX_FMT_YUV420,
.types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
},
{
- .name = "YUYV 4:2:2",
.fourcc = V4L2_PIX_FMT_YUYV,
.types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
},
@@ -127,7 +120,7 @@ static struct deinterlace_fmt *find_format(struct v4l2_format *f)
struct deinterlace_dev {
struct v4l2_device v4l2_dev;
- struct video_device *vfd;
+ struct video_device vfd;
atomic_t busy;
struct mutex dev_mutex;
@@ -136,20 +129,24 @@ struct deinterlace_dev {
struct dma_chan *dma_chan;
struct v4l2_m2m_dev *m2m_dev;
- struct vb2_alloc_ctx *alloc_ctx;
};
struct deinterlace_ctx {
+ struct v4l2_fh fh;
struct deinterlace_dev *dev;
/* Abort requested by m2m */
int aborting;
enum v4l2_colorspace colorspace;
dma_cookie_t cookie;
- struct v4l2_m2m_ctx *m2m_ctx;
struct dma_interleaved_template *xt;
};
+static inline struct deinterlace_ctx *file_to_ctx(struct file *filp)
+{
+ return container_of(file_to_v4l2_fh(filp), struct deinterlace_ctx, fh);
+}
+
/*
* mem2mem callbacks
*/
@@ -158,9 +155,9 @@ static int deinterlace_job_ready(void *priv)
struct deinterlace_ctx *ctx = priv;
struct deinterlace_dev *pcdev = ctx->dev;
- if ((v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0)
- && (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0)
- && (atomic_read(&ctx->dev->busy) == 0)) {
+ if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0 &&
+ v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0 &&
+ !atomic_read(&ctx->dev->busy)) {
dprintk(pcdev, "Task ready\n");
return 1;
}
@@ -179,41 +176,30 @@ static void deinterlace_job_abort(void *priv)
dprintk(pcdev, "Aborting task\n");
- v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx);
-}
-
-static void deinterlace_lock(void *priv)
-{
- struct deinterlace_ctx *ctx = priv;
- struct deinterlace_dev *pcdev = ctx->dev;
- mutex_lock(&pcdev->dev_mutex);
-}
-
-static void deinterlace_unlock(void *priv)
-{
- struct deinterlace_ctx *ctx = priv;
- struct deinterlace_dev *pcdev = ctx->dev;
- mutex_unlock(&pcdev->dev_mutex);
+ v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->fh.m2m_ctx);
}
static void dma_callback(void *data)
{
struct deinterlace_ctx *curr_ctx = data;
struct deinterlace_dev *pcdev = curr_ctx->dev;
- struct vb2_buffer *src_vb, *dst_vb;
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
atomic_set(&pcdev->busy, 0);
- src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
- dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+ src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+ dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
- src_vb->v4l2_buf.timestamp = dst_vb->v4l2_buf.timestamp;
- src_vb->v4l2_buf.timecode = dst_vb->v4l2_buf.timecode;
+ dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
+ dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vb->flags |=
+ src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ dst_vb->timecode = src_vb->timecode;
v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
- v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx);
+ v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->fh.m2m_ctx);
dprintk(pcdev, "dma transfers completed.\n");
}
@@ -222,7 +208,7 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
int do_callback)
{
struct deinterlace_q_data *s_q_data;
- struct vb2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
struct deinterlace_dev *pcdev = ctx->dev;
struct dma_chan *chan = pcdev->dma_chan;
struct dma_device *dmadev = chan->device;
@@ -232,16 +218,17 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
dma_addr_t p_in, p_out;
enum dma_ctrl_flags flags;
- src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
- dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
s_width = s_q_data->width;
s_height = s_q_data->height;
s_size = s_width * s_height;
- p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0);
- p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+ p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+ p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf,
+ 0);
if (!p_in || !p_out) {
v4l2_err(&pcdev->v4l2_dev,
"Acquiring kernel pointers to buffers failed\n");
@@ -341,8 +328,7 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
ctx->xt->dir = DMA_MEM_TO_MEM;
ctx->xt->src_sgl = false;
ctx->xt->dst_sgl = true;
- flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT |
- DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SKIP_SRC_UNMAP;
+ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
tx = dmadev->device_prep_interleaved_dma(chan, ctx->xt, flags);
if (tx == NULL) {
@@ -382,16 +368,16 @@ static void deinterlace_device_run(void *priv)
* 4 possible field conversions are possible at the moment:
* V4L2_FIELD_SEQ_TB --> V4L2_FIELD_INTERLACED_TB:
* two separate fields in the same input buffer are interlaced
- * in the output buffer using weaving. Top field comes first.
+ * in the output buffer using weaving. Top field comes first.
* V4L2_FIELD_SEQ_TB --> V4L2_FIELD_NONE:
- * top field from the input buffer is copied to the output buffer
- * using line doubling. Bottom field from the input buffer is discarded.
+ * top field from the input buffer is copied to the output buffer
+ * using line doubling. Bottom field from the input buffer is discarded.
* V4L2_FIELD_SEQ_BT --> V4L2_FIELD_INTERLACED_BT:
* two separate fields in the same input buffer are interlaced
- * in the output buffer using weaving. Bottom field comes first.
+ * in the output buffer using weaving. Bottom field comes first.
* V4L2_FIELD_SEQ_BT --> V4L2_FIELD_NONE:
- * bottom field from the input buffer is copied to the output buffer
- * using line doubling. Top field from the input buffer is discarded.
+ * bottom field from the input buffer is copied to the output buffer
+ * using line doubling. Top field from the input buffer is discarded.
*/
switch (dst_q_data->fmt->fourcc) {
case V4L2_PIX_FMT_YUV420:
@@ -450,18 +436,9 @@ static void deinterlace_device_run(void *priv)
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
- strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
- strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card));
- /*
- * This is only a mem-to-mem video device. The capture and output
- * device capability flags are left only for backward compatibility
- * and are scheduled for removal.
- */
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
- V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-
+ strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
+ strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
+ strscpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info));
return 0;
}
@@ -486,7 +463,6 @@ static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
if (i < NUM_FORMATS) {
/* Format found */
fmt = &formats[i];
- strlcpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
}
@@ -509,13 +485,8 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
{
- struct vb2_queue *vq;
struct deinterlace_q_data *q_data;
- vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
- if (!vq)
- return -EINVAL;
-
q_data = get_q_data(f->type);
f->fmt.pix.width = q_data->width;
@@ -541,13 +512,13 @@ static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
struct v4l2_format *f)
{
- return vidioc_g_fmt(priv, f);
+ return vidioc_g_fmt(file_to_ctx(file), f);
}
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- return vidioc_g_fmt(priv, f);
+ return vidioc_g_fmt(file_to_ctx(file), f);
}
static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt)
@@ -568,8 +539,8 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt)
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
+ struct deinterlace_ctx *ctx = file_to_ctx(file);
struct deinterlace_fmt *fmt;
- struct deinterlace_ctx *ctx = priv;
fmt = find_format(f);
if (!fmt || !(fmt->types & MEM2MEM_CAPTURE))
@@ -609,9 +580,7 @@ static int vidioc_s_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
struct deinterlace_q_data *q_data;
struct vb2_queue *vq;
- vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
- if (!vq)
- return -EINVAL;
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
q_data = get_q_data(f->type);
if (!q_data)
@@ -662,61 +631,31 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
ret = vidioc_try_fmt_vid_cap(file, priv, f);
if (ret)
return ret;
- return vidioc_s_fmt(priv, f);
+ return vidioc_s_fmt(file_to_ctx(file), f);
}
static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct deinterlace_ctx *ctx = priv;
+ struct deinterlace_ctx *ctx = file_to_ctx(file);
int ret;
ret = vidioc_try_fmt_vid_out(file, priv, f);
if (ret)
return ret;
- ret = vidioc_s_fmt(priv, f);
+ ret = vidioc_s_fmt(ctx, f);
if (!ret)
ctx->colorspace = f->fmt.pix.colorspace;
return ret;
}
-static int vidioc_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *reqbufs)
-{
- struct deinterlace_ctx *ctx = priv;
-
- return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *buf)
-{
- struct deinterlace_ctx *ctx = priv;
-
- return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
- struct deinterlace_ctx *ctx = priv;
-
- return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
- struct deinterlace_ctx *ctx = priv;
-
- return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
-}
-
static int vidioc_streamon(struct file *file, void *priv,
enum v4l2_buf_type type)
{
+ struct deinterlace_ctx *ctx = file_to_ctx(file);
struct deinterlace_q_data *s_q_data, *d_q_data;
- struct deinterlace_ctx *ctx = priv;
s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -752,15 +691,7 @@ static int vidioc_streamon(struct file *file, void *priv,
return -EINVAL;
}
- return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct deinterlace_ctx *ctx = priv;
-
- return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+ return v4l2_m2m_streamon(file, ctx->fh.m2m_ctx, type);
}
static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = {
@@ -776,28 +707,24 @@ static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = {
.vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
.vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
-
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
.vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
};
/*
* Queue operations
*/
-struct vb2_dc_conf {
- struct device *dev;
-};
-
static int deinterlace_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
struct deinterlace_q_data *q_data;
@@ -818,8 +745,6 @@ static int deinterlace_queue_setup(struct vb2_queue *vq,
*nbuffers = count;
sizes[0] = size;
- alloc_ctxs[0] = ctx->dev->alloc_ctx;
-
dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
return 0;
@@ -847,11 +772,13 @@ static int deinterlace_buf_prepare(struct vb2_buffer *vb)
static void deinterlace_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
-static struct vb2_ops deinterlace_qops = {
+static const struct vb2_ops deinterlace_qops = {
.queue_setup = deinterlace_queue_setup,
.buf_prepare = deinterlace_buf_prepare,
.buf_queue = deinterlace_buf_queue,
@@ -864,12 +791,14 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
int ret;
src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+ src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
src_vq->drv_priv = ctx;
src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
src_vq->ops = &deinterlace_qops;
src_vq->mem_ops = &vb2_dma_contig_memops;
- src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->dev = ctx->dev->v4l2_dev.dev;
+ src_vq->lock = &ctx->dev->dev_mutex;
q_data[V4L2_M2M_SRC].fmt = &formats[0];
q_data[V4L2_M2M_SRC].width = 640;
q_data[V4L2_M2M_SRC].height = 480;
@@ -881,12 +810,14 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
return ret;
dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+ dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
dst_vq->drv_priv = ctx;
dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
dst_vq->ops = &deinterlace_qops;
dst_vq->mem_ops = &vb2_dma_contig_memops;
- dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ dst_vq->dev = ctx->dev->v4l2_dev.dev;
+ dst_vq->lock = &ctx->dev->dev_mutex;
q_data[V4L2_M2M_DST].fmt = &formats[0];
q_data[V4L2_M2M_DST].width = 640;
q_data[V4L2_M2M_DST].height = 480;
@@ -908,18 +839,18 @@ static int deinterlace_open(struct file *file)
if (!ctx)
return -ENOMEM;
- file->private_data = ctx;
+ v4l2_fh_init(&ctx->fh, video_devdata(file));
ctx->dev = pcdev;
- ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
- if (IS_ERR(ctx->m2m_ctx)) {
- int ret = PTR_ERR(ctx->m2m_ctx);
+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
+ if (IS_ERR(ctx->fh.m2m_ctx)) {
+ int ret = PTR_ERR(ctx->fh.m2m_ctx);
kfree(ctx);
return ret;
}
- ctx->xt = kzalloc(sizeof(struct dma_async_tx_descriptor) +
+ ctx->xt = kzalloc(sizeof(struct dma_interleaved_template) +
sizeof(struct data_chunk), GFP_KERNEL);
if (!ctx->xt) {
kfree(ctx);
@@ -927,8 +858,10 @@ static int deinterlace_open(struct file *file)
}
ctx->colorspace = V4L2_COLORSPACE_REC709;
+ v4l2_fh_add(&ctx->fh, file);
- dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
+ dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n",
+ ctx, ctx->fh.m2m_ctx);
return 0;
}
@@ -936,61 +869,42 @@ static int deinterlace_open(struct file *file)
static int deinterlace_release(struct file *file)
{
struct deinterlace_dev *pcdev = video_drvdata(file);
- struct deinterlace_ctx *ctx = file->private_data;
+ struct deinterlace_ctx *ctx = file_to_ctx(file);
dprintk(pcdev, "Releasing instance %p\n", ctx);
- v4l2_m2m_ctx_release(ctx->m2m_ctx);
+ v4l2_fh_del(&ctx->fh, file);
+ v4l2_fh_exit(&ctx->fh);
+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
kfree(ctx->xt);
kfree(ctx);
return 0;
}
-static unsigned int deinterlace_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- struct deinterlace_ctx *ctx = file->private_data;
- int ret;
-
- deinterlace_lock(ctx);
- ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
- deinterlace_unlock(ctx);
-
- return ret;
-}
-
-static int deinterlace_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct deinterlace_ctx *ctx = file->private_data;
-
- return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
-}
-
static const struct v4l2_file_operations deinterlace_fops = {
.owner = THIS_MODULE,
.open = deinterlace_open,
.release = deinterlace_release,
- .poll = deinterlace_poll,
+ .poll = v4l2_m2m_fop_poll,
.unlocked_ioctl = video_ioctl2,
- .mmap = deinterlace_mmap,
+ .mmap = v4l2_m2m_fop_mmap,
};
-static struct video_device deinterlace_videodev = {
+static const struct video_device deinterlace_videodev = {
.name = MEM2MEM_NAME,
.fops = &deinterlace_fops,
.ioctl_ops = &deinterlace_ioctl_ops,
.minor = -1,
- .release = video_device_release,
+ .release = video_device_release_empty,
.vfl_dir = VFL_DIR_M2M,
+ .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
};
-static struct v4l2_m2m_ops m2m_ops = {
+static const struct v4l2_m2m_ops m2m_ops = {
.device_run = deinterlace_device_run,
.job_ready = deinterlace_job_ready,
.job_abort = deinterlace_job_abort,
- .lock = deinterlace_lock,
- .unlock = deinterlace_unlock,
};
static int deinterlace_probe(struct platform_device *pdev)
@@ -1000,7 +914,7 @@ static int deinterlace_probe(struct platform_device *pdev)
dma_cap_mask_t mask;
int ret = 0;
- pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
+ pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
if (!pcdev)
return -ENOMEM;
@@ -1010,10 +924,11 @@ static int deinterlace_probe(struct platform_device *pdev)
dma_cap_set(DMA_INTERLEAVE, mask);
pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev);
if (!pcdev->dma_chan)
- goto free_dev;
+ return -ENODEV;
if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) {
- v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n");
+ dev_err(&pdev->dev, "DMA does not support INTERLEAVE\n");
+ ret = -ENODEV;
goto rel_dma;
}
@@ -1024,38 +939,23 @@ static int deinterlace_probe(struct platform_device *pdev)
atomic_set(&pcdev->busy, 0);
mutex_init(&pcdev->dev_mutex);
- vfd = video_device_alloc();
- if (!vfd) {
- v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
- ret = -ENOMEM;
- goto unreg_dev;
- }
-
+ vfd = &pcdev->vfd;
*vfd = deinterlace_videodev;
vfd->lock = &pcdev->dev_mutex;
vfd->v4l2_dev = &pcdev->v4l2_dev;
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+ ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
if (ret) {
v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
- goto rel_vdev;
+ goto unreg_dev;
}
video_set_drvdata(vfd, pcdev);
- snprintf(vfd->name, sizeof(vfd->name), "%s", deinterlace_videodev.name);
- pcdev->vfd = vfd;
v4l2_info(&pcdev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME
" Device registered as /dev/video%d\n", vfd->num);
platform_set_drvdata(pdev, pcdev);
- pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
- if (IS_ERR(pcdev->alloc_ctx)) {
- v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n");
- ret = PTR_ERR(pcdev->alloc_ctx);
- goto err_ctx;
- }
-
pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
if (IS_ERR(pcdev->m2m_dev)) {
v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
@@ -1065,37 +965,25 @@ static int deinterlace_probe(struct platform_device *pdev)
return 0;
- v4l2_m2m_release(pcdev->m2m_dev);
err_m2m:
- video_unregister_device(pcdev->vfd);
-err_ctx:
- vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
-rel_vdev:
- video_device_release(vfd);
+ video_unregister_device(&pcdev->vfd);
unreg_dev:
v4l2_device_unregister(&pcdev->v4l2_dev);
rel_dma:
dma_release_channel(pcdev->dma_chan);
-free_dev:
- kfree(pcdev);
return ret;
}
-static int deinterlace_remove(struct platform_device *pdev)
+static void deinterlace_remove(struct platform_device *pdev)
{
- struct deinterlace_dev *pcdev =
- (struct deinterlace_dev *)platform_get_drvdata(pdev);
+ struct deinterlace_dev *pcdev = platform_get_drvdata(pdev);
v4l2_info(&pcdev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
v4l2_m2m_release(pcdev->m2m_dev);
- video_unregister_device(pcdev->vfd);
+ video_unregister_device(&pcdev->vfd);
v4l2_device_unregister(&pcdev->v4l2_dev);
- vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
dma_release_channel(pcdev->dma_chan);
- kfree(pcdev);
-
- return 0;
}
static struct platform_driver deinterlace_pdrv = {
@@ -1103,7 +991,6 @@ static struct platform_driver deinterlace_pdrv = {
.remove = deinterlace_remove,
.driver = {
.name = MEM2MEM_NAME,
- .owner = THIS_MODULE,
},
};
module_platform_driver(deinterlace_pdrv);