^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * V4L2 deinterlacing support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2012 Vista Silicon S.L.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Javier Martin <javier.martin@vista-silicon.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/dmaengine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <media/v4l2-mem2mem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <media/videobuf2-dma-contig.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define MEM2MEM_TEST_MODULE_NAME "mem2mem-deinterlace"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) MODULE_DESCRIPTION("mem2mem device which supports deinterlacing using dmaengine");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) MODULE_VERSION("0.0.1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static bool debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) module_param(debug, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* Flags that indicate a format can be used for capture/output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MEM2MEM_CAPTURE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MEM2MEM_OUTPUT (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define MEM2MEM_NAME "m2m-deinterlace"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define dprintk(dev, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct deinterlace_fmt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u32 fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* Types the format can be used for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static struct deinterlace_fmt formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .fourcc = V4L2_PIX_FMT_YUV420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .fourcc = V4L2_PIX_FMT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define NUM_FORMATS ARRAY_SIZE(formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Per-queue, driver-specific private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct deinterlace_q_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct deinterlace_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) enum v4l2_field field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) V4L2_M2M_SRC = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) V4L2_M2M_DST = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) YUV420_DMA_Y_ODD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) YUV420_DMA_Y_EVEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) YUV420_DMA_U_ODD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) YUV420_DMA_U_EVEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) YUV420_DMA_V_ODD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) YUV420_DMA_V_EVEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) YUV420_DMA_Y_ODD_DOUBLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) YUV420_DMA_U_ODD_DOUBLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) YUV420_DMA_V_ODD_DOUBLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) YUYV_DMA_ODD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) YUYV_DMA_EVEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) YUYV_DMA_EVEN_DOUBLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Source and destination queue data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static struct deinterlace_q_data q_data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static struct deinterlace_q_data *get_q_data(enum v4l2_buf_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) case V4L2_BUF_TYPE_VIDEO_OUTPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return &q_data[V4L2_M2M_SRC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) case V4L2_BUF_TYPE_VIDEO_CAPTURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return &q_data[V4L2_M2M_DST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static struct deinterlace_fmt *find_format(struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct deinterlace_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) for (k = 0; k < NUM_FORMATS; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) fmt = &formats[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if ((fmt->types & f->type) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) (fmt->fourcc == f->fmt.pix.pixelformat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (k == NUM_FORMATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return &formats[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct deinterlace_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct v4l2_device v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct video_device vfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) atomic_t busy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct mutex dev_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) spinlock_t irqlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct dma_chan *dma_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct v4l2_m2m_dev *m2m_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct deinterlace_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct v4l2_fh fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct deinterlace_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Abort requested by m2m */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int aborting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) enum v4l2_colorspace colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dma_cookie_t cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct dma_interleaved_template *xt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * mem2mem callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int deinterlace_job_ready(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct deinterlace_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct deinterlace_dev *pcdev = ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) !atomic_read(&ctx->dev->busy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dprintk(pcdev, "Task ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) dprintk(pcdev, "Task not ready to run\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void deinterlace_job_abort(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct deinterlace_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct deinterlace_dev *pcdev = ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ctx->aborting = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dprintk(pcdev, "Aborting task\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void dma_callback(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct deinterlace_ctx *curr_ctx = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct deinterlace_dev *pcdev = curr_ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct vb2_v4l2_buffer *src_vb, *dst_vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) atomic_set(&pcdev->busy, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) dst_vb->flags |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dst_vb->timecode = src_vb->timecode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) dprintk(pcdev, "dma transfers completed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int do_callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct deinterlace_q_data *s_q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct vb2_v4l2_buffer *src_buf, *dst_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct deinterlace_dev *pcdev = ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct dma_chan *chan = pcdev->dma_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct dma_device *dmadev = chan->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct dma_async_tx_descriptor *tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned int s_width, s_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) unsigned int s_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) dma_addr_t p_in, p_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) enum dma_ctrl_flags flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) s_width = s_q_data->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) s_height = s_q_data->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) s_size = s_width * s_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!p_in || !p_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) v4l2_err(&pcdev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) "Acquiring kernel pointers to buffers failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) case YUV420_DMA_Y_ODD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ctx->xt->numf = s_height / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ctx->xt->sgl[0].size = s_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ctx->xt->sgl[0].icg = s_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ctx->xt->src_start = p_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ctx->xt->dst_start = p_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) case YUV420_DMA_Y_EVEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ctx->xt->numf = s_height / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ctx->xt->sgl[0].size = s_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ctx->xt->sgl[0].icg = s_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ctx->xt->src_start = p_in + s_size / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ctx->xt->dst_start = p_out + s_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case YUV420_DMA_U_ODD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ctx->xt->numf = s_height / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ctx->xt->sgl[0].size = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ctx->xt->sgl[0].icg = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ctx->xt->src_start = p_in + s_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ctx->xt->dst_start = p_out + s_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case YUV420_DMA_U_EVEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ctx->xt->numf = s_height / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ctx->xt->sgl[0].size = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ctx->xt->sgl[0].icg = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ctx->xt->src_start = p_in + (9 * s_size) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ctx->xt->dst_start = p_out + s_size + s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) case YUV420_DMA_V_ODD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ctx->xt->numf = s_height / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ctx->xt->sgl[0].size = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ctx->xt->sgl[0].icg = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ctx->xt->src_start = p_in + (5 * s_size) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ctx->xt->dst_start = p_out + (5 * s_size) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case YUV420_DMA_V_EVEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ctx->xt->numf = s_height / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) ctx->xt->sgl[0].size = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ctx->xt->sgl[0].icg = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ctx->xt->src_start = p_in + (11 * s_size) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ctx->xt->dst_start = p_out + (5 * s_size) / 4 + s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) case YUV420_DMA_Y_ODD_DOUBLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) ctx->xt->numf = s_height / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ctx->xt->sgl[0].size = s_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ctx->xt->sgl[0].icg = s_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ctx->xt->src_start = p_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ctx->xt->dst_start = p_out + s_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case YUV420_DMA_U_ODD_DOUBLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ctx->xt->numf = s_height / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ctx->xt->sgl[0].size = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ctx->xt->sgl[0].icg = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ctx->xt->src_start = p_in + s_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ctx->xt->dst_start = p_out + s_size + s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) case YUV420_DMA_V_ODD_DOUBLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ctx->xt->numf = s_height / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ctx->xt->sgl[0].size = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ctx->xt->sgl[0].icg = s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ctx->xt->src_start = p_in + (5 * s_size) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ctx->xt->dst_start = p_out + (5 * s_size) / 4 + s_width / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case YUYV_DMA_ODD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ctx->xt->numf = s_height / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ctx->xt->sgl[0].size = s_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ctx->xt->sgl[0].icg = s_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ctx->xt->src_start = p_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ctx->xt->dst_start = p_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) case YUYV_DMA_EVEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ctx->xt->numf = s_height / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ctx->xt->sgl[0].size = s_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ctx->xt->sgl[0].icg = s_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ctx->xt->src_start = p_in + s_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ctx->xt->dst_start = p_out + s_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case YUYV_DMA_EVEN_DOUBLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ctx->xt->numf = s_height / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ctx->xt->sgl[0].size = s_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ctx->xt->sgl[0].icg = s_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ctx->xt->src_start = p_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ctx->xt->dst_start = p_out + s_width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* Common parameters for al transfers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ctx->xt->frame_size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ctx->xt->dir = DMA_MEM_TO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) ctx->xt->src_sgl = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ctx->xt->dst_sgl = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) tx = dmadev->device_prep_interleaved_dma(chan, ctx->xt, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (tx == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) v4l2_warn(&pcdev->v4l2_dev, "DMA interleaved prep error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (do_callback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) tx->callback = dma_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) tx->callback_param = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ctx->cookie = dmaengine_submit(tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (dma_submit_error(ctx->cookie)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) v4l2_warn(&pcdev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) "DMA submit error %d with src=0x%x dst=0x%x len=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ctx->cookie, (unsigned)p_in, (unsigned)p_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) s_size * 3/2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dma_async_issue_pending(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static void deinterlace_device_run(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct deinterlace_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct deinterlace_q_data *dst_q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) atomic_set(&ctx->dev->busy, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) dprintk(ctx->dev, "%s: DMA try issue.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) dst_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * 4 possible field conversions are possible at the moment:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * V4L2_FIELD_SEQ_TB --> V4L2_FIELD_INTERLACED_TB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * two separate fields in the same input buffer are interlaced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * in the output buffer using weaving. Top field comes first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * V4L2_FIELD_SEQ_TB --> V4L2_FIELD_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * top field from the input buffer is copied to the output buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * using line doubling. Bottom field from the input buffer is discarded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * V4L2_FIELD_SEQ_BT --> V4L2_FIELD_INTERLACED_BT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * two separate fields in the same input buffer are interlaced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * in the output buffer using weaving. Bottom field comes first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * V4L2_FIELD_SEQ_BT --> V4L2_FIELD_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * bottom field from the input buffer is copied to the output buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * using line doubling. Top field from the input buffer is discarded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) switch (dst_q_data->fmt->fourcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) case V4L2_PIX_FMT_YUV420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) switch (dst_q_data->field) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case V4L2_FIELD_INTERLACED_TB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) case V4L2_FIELD_INTERLACED_BT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) dprintk(ctx->dev, "%s: yuv420 interlaced tb.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) deinterlace_issue_dma(ctx, YUV420_DMA_Y_EVEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) deinterlace_issue_dma(ctx, YUV420_DMA_U_EVEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) deinterlace_issue_dma(ctx, YUV420_DMA_V_EVEN, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) case V4L2_FIELD_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) dprintk(ctx->dev, "%s: yuv420 interlaced line doubling.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD_DOUBLING, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD_DOUBLING, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD_DOUBLING, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) switch (dst_q_data->field) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) case V4L2_FIELD_INTERLACED_TB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) case V4L2_FIELD_INTERLACED_BT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dprintk(ctx->dev, "%s: yuyv interlaced_tb.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) deinterlace_issue_dma(ctx, YUYV_DMA_ODD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) deinterlace_issue_dma(ctx, YUYV_DMA_EVEN, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) case V4L2_FIELD_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) dprintk(ctx->dev, "%s: yuyv interlaced line doubling.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) deinterlace_issue_dma(ctx, YUYV_DMA_ODD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) deinterlace_issue_dma(ctx, YUYV_DMA_EVEN_DOUBLING, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dprintk(ctx->dev, "%s: DMA issue done.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * video ioctls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static int vidioc_querycap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) strscpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) int i, num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct deinterlace_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) for (i = 0; i < NUM_FORMATS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (formats[i].types & type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /* index-th format of type type found ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (num == f->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /* Correct type but haven't reached our index yet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * just increment per-type index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ++num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (i < NUM_FORMATS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* Format found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) fmt = &formats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) f->pixelformat = fmt->fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* Format not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return enum_fmt(f, MEM2MEM_CAPTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return enum_fmt(f, MEM2MEM_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct vb2_queue *vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct deinterlace_q_data *q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (!vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) q_data = get_q_data(f->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) f->fmt.pix.width = q_data->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) f->fmt.pix.height = q_data->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) f->fmt.pix.field = q_data->field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) f->fmt.pix.pixelformat = q_data->fmt->fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) switch (q_data->fmt->fourcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) case V4L2_PIX_FMT_YUV420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) f->fmt.pix.bytesperline = q_data->width * 3 / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) f->fmt.pix.bytesperline = q_data->width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) f->fmt.pix.sizeimage = q_data->sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) f->fmt.pix.colorspace = ctx->colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return vidioc_g_fmt(priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return vidioc_g_fmt(priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) switch (f->fmt.pix.pixelformat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) case V4L2_PIX_FMT_YUV420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct deinterlace_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct deinterlace_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) fmt = find_format(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (!fmt || !(fmt->types & MEM2MEM_CAPTURE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) f->fmt.pix.colorspace = ctx->colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) f->fmt.pix.field != V4L2_FIELD_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) f->fmt.pix.field = V4L2_FIELD_INTERLACED_TB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return vidioc_try_fmt(f, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct deinterlace_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) fmt = find_format(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (!fmt || !(fmt->types & MEM2MEM_OUTPUT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!f->fmt.pix.colorspace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (f->fmt.pix.field != V4L2_FIELD_SEQ_TB &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) f->fmt.pix.field != V4L2_FIELD_SEQ_BT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) f->fmt.pix.field = V4L2_FIELD_SEQ_TB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return vidioc_try_fmt(f, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static int vidioc_s_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct deinterlace_q_data *q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct vb2_queue *vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (!vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) q_data = get_q_data(f->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (!q_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (vb2_is_busy(vq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) q_data->fmt = find_format(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (!q_data->fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) v4l2_err(&ctx->dev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) "Couldn't set format type %d, wxh: %dx%d. fmt: %d, field: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) f->type, f->fmt.pix.width, f->fmt.pix.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) f->fmt.pix.pixelformat, f->fmt.pix.field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) q_data->width = f->fmt.pix.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) q_data->height = f->fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) q_data->field = f->fmt.pix.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) switch (f->fmt.pix.pixelformat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) case V4L2_PIX_FMT_YUV420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) q_data->sizeimage = (q_data->width * q_data->height * 3) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) q_data->sizeimage = q_data->width * q_data->height * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) dprintk(ctx->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) "Setting format for type %d, wxh: %dx%d, fmt: %d, field: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) f->type, q_data->width, q_data->height, q_data->fmt->fourcc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) q_data->field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ret = vidioc_try_fmt_vid_cap(file, priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return vidioc_s_fmt(priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct deinterlace_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ret = vidioc_try_fmt_vid_out(file, priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = vidioc_s_fmt(priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ctx->colorspace = f->fmt.pix.colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) static int vidioc_streamon(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) enum v4l2_buf_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) struct deinterlace_q_data *s_q_data, *d_q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct deinterlace_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* Check that src and dst queues have the same pix format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (s_q_data->fmt->fourcc != d_q_data->fmt->fourcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) v4l2_err(&ctx->dev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) "src and dst formats don't match.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /* Check that input and output deinterlacing types are compatible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) switch (s_q_data->field) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case V4L2_FIELD_SEQ_BT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (d_q_data->field != V4L2_FIELD_NONE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) d_q_data->field != V4L2_FIELD_INTERLACED_BT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) v4l2_err(&ctx->dev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) "src and dst field conversion [(%d)->(%d)] not supported.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) s_q_data->field, d_q_data->field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) case V4L2_FIELD_SEQ_TB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (d_q_data->field != V4L2_FIELD_NONE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) d_q_data->field != V4L2_FIELD_INTERLACED_TB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) v4l2_err(&ctx->dev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) "src and dst field conversion [(%d)->(%d)] not supported.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) s_q_data->field, d_q_data->field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return v4l2_m2m_streamon(file, ctx->fh.m2m_ctx, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .vidioc_querycap = vidioc_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .vidioc_streamon = vidioc_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * Queue operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) struct vb2_dc_conf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static int deinterlace_queue_setup(struct vb2_queue *vq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) unsigned int *nbuffers, unsigned int *nplanes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) unsigned int sizes[], struct device *alloc_devs[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) struct deinterlace_q_data *q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) unsigned int size, count = *nbuffers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) q_data = get_q_data(vq->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) switch (q_data->fmt->fourcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) case V4L2_PIX_FMT_YUV420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) size = q_data->width * q_data->height * 3 / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) size = q_data->width * q_data->height * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) *nplanes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) *nbuffers = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) sizes[0] = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static int deinterlace_buf_prepare(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct deinterlace_q_data *q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) q_data = get_q_data(vb->vb2_queue->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) __func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) vb2_set_plane_payload(vb, 0, q_data->sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) static void deinterlace_buf_queue(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) static const struct vb2_ops deinterlace_qops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .queue_setup = deinterlace_queue_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .buf_prepare = deinterlace_buf_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .buf_queue = deinterlace_buf_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .wait_prepare = vb2_ops_wait_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .wait_finish = vb2_ops_wait_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static int queue_init(void *priv, struct vb2_queue *src_vq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct vb2_queue *dst_vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct deinterlace_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) src_vq->drv_priv = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) src_vq->ops = &deinterlace_qops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) src_vq->mem_ops = &vb2_dma_contig_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) src_vq->dev = ctx->dev->v4l2_dev.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) src_vq->lock = &ctx->dev->dev_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) q_data[V4L2_M2M_SRC].fmt = &formats[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) q_data[V4L2_M2M_SRC].width = 640;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) q_data[V4L2_M2M_SRC].height = 480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) q_data[V4L2_M2M_SRC].sizeimage = (640 * 480 * 3) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) q_data[V4L2_M2M_SRC].field = V4L2_FIELD_SEQ_TB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) ret = vb2_queue_init(src_vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) dst_vq->drv_priv = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) dst_vq->ops = &deinterlace_qops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) dst_vq->mem_ops = &vb2_dma_contig_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dst_vq->dev = ctx->dev->v4l2_dev.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) dst_vq->lock = &ctx->dev->dev_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) q_data[V4L2_M2M_DST].fmt = &formats[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) q_data[V4L2_M2M_DST].width = 640;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) q_data[V4L2_M2M_DST].height = 480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) q_data[V4L2_M2M_DST].sizeimage = (640 * 480 * 3) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) q_data[V4L2_M2M_SRC].field = V4L2_FIELD_INTERLACED_TB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return vb2_queue_init(dst_vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) * File operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static int deinterlace_open(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct deinterlace_dev *pcdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct deinterlace_ctx *ctx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) v4l2_fh_init(&ctx->fh, video_devdata(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) file->private_data = &ctx->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) ctx->dev = pcdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (IS_ERR(ctx->fh.m2m_ctx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) int ret = PTR_ERR(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) ctx->xt = kzalloc(sizeof(struct dma_interleaved_template) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) sizeof(struct data_chunk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (!ctx->xt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) ctx->colorspace = V4L2_COLORSPACE_REC709;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) v4l2_fh_add(&ctx->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ctx, ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) static int deinterlace_release(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct deinterlace_dev *pcdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) struct deinterlace_ctx *ctx = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) dprintk(pcdev, "Releasing instance %p\n", ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) v4l2_fh_del(&ctx->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) v4l2_fh_exit(&ctx->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) kfree(ctx->xt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static const struct v4l2_file_operations deinterlace_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) .open = deinterlace_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) .release = deinterlace_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) .poll = v4l2_m2m_fop_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) .mmap = v4l2_m2m_fop_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) static const struct video_device deinterlace_videodev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .name = MEM2MEM_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .fops = &deinterlace_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) .ioctl_ops = &deinterlace_ioctl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) .minor = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) .release = video_device_release_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) .vfl_dir = VFL_DIR_M2M,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) static const struct v4l2_m2m_ops m2m_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .device_run = deinterlace_device_run,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .job_ready = deinterlace_job_ready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .job_abort = deinterlace_job_abort,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) static int deinterlace_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct deinterlace_dev *pcdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct video_device *vfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) dma_cap_mask_t mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (!pcdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) spin_lock_init(&pcdev->irqlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) dma_cap_zero(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) dma_cap_set(DMA_INTERLEAVE, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (!pcdev->dma_chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) dev_err(&pdev->dev, "DMA does not support INTERLEAVE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) goto rel_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) goto rel_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) atomic_set(&pcdev->busy, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) mutex_init(&pcdev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) vfd = &pcdev->vfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) *vfd = deinterlace_videodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) vfd->lock = &pcdev->dev_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) vfd->v4l2_dev = &pcdev->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) goto unreg_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) video_set_drvdata(vfd, pcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) v4l2_info(&pcdev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) " Device registered as /dev/video%d\n", vfd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) platform_set_drvdata(pdev, pcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (IS_ERR(pcdev->m2m_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) ret = PTR_ERR(pcdev->m2m_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) goto err_m2m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) err_m2m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) video_unregister_device(&pcdev->vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) unreg_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) v4l2_device_unregister(&pcdev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) rel_dma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) dma_release_channel(pcdev->dma_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) static int deinterlace_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) struct deinterlace_dev *pcdev = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) v4l2_info(&pcdev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) v4l2_m2m_release(pcdev->m2m_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) video_unregister_device(&pcdev->vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) v4l2_device_unregister(&pcdev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) dma_release_channel(pcdev->dma_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static struct platform_driver deinterlace_pdrv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) .probe = deinterlace_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) .remove = deinterlace_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) .name = MEM2MEM_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) module_platform_driver(deinterlace_pdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)