^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * A virtual v4l2-mem2mem example device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This is a virtual device driver for testing mem-to-mem videobuf framework.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * It simulates a device that uses memory buffers for both source and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * destination, processes the data and issues an "irq" (simulated by a delayed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * workqueue).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * The device is capable of multi-instance, multi-buffer-per-transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * operation (via the mem2mem framework).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Pawel Osciak, <pawel@osciak.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Marek Szyprowski, <m.szyprowski@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * it under the terms of the GNU General Public License as published by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Free Software Foundation; either version 2 of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * License, or (at your option) any later version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <media/v4l2-mem2mem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/videobuf2-vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) MODULE_VERSION("0.2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) MODULE_ALIAS("mem2mem_testdev");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static unsigned int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) module_param(debug, uint, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MODULE_PARM_DESC(debug, "debug level");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Default transaction time in msec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static unsigned int default_transtime = 40; /* Max 25 fps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) module_param(default_transtime, uint, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) MODULE_PARM_DESC(default_transtime, "default transaction time in ms");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MIN_W 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MIN_H 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MAX_W 640
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MAX_H 480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* Pixel alignment for non-bayer formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define WIDTH_ALIGN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define HEIGHT_ALIGN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Pixel alignment for bayer formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define BAYER_WIDTH_ALIGN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define BAYER_HEIGHT_ALIGN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Flags that indicate a format can be used for capture/output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define MEM2MEM_CAPTURE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define MEM2MEM_OUTPUT BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MEM2MEM_NAME "vim2m"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Per queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* In bytes, per queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Flags that indicate processing mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define MEM2MEM_HFLIP BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define MEM2MEM_VFLIP BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define dprintk(dev, lvl, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static void vim2m_dev_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static struct platform_device vim2m_pdev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .name = MEM2MEM_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .dev.release = vim2m_dev_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct vim2m_fmt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Types the format can be used for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u32 types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static struct vim2m_fmt formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .fourcc = V4L2_PIX_FMT_RGB565, /* rrrrrggg gggbbbbb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .depth = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .fourcc = V4L2_PIX_FMT_RGB565X, /* gggbbbbb rrrrrggg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .depth = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .fourcc = V4L2_PIX_FMT_RGB24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .depth = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .fourcc = V4L2_PIX_FMT_BGR24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .depth = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .fourcc = V4L2_PIX_FMT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .depth = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .types = MEM2MEM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .fourcc = V4L2_PIX_FMT_SBGGR8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .depth = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .types = MEM2MEM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .fourcc = V4L2_PIX_FMT_SGBRG8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .depth = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .types = MEM2MEM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .fourcc = V4L2_PIX_FMT_SGRBG8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .depth = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .types = MEM2MEM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .fourcc = V4L2_PIX_FMT_SRGGB8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .depth = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .types = MEM2MEM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define NUM_FORMATS ARRAY_SIZE(formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Per-queue, driver-specific private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct vim2m_q_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned int width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned int sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) unsigned int sequence;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct vim2m_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) V4L2_M2M_SRC = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) V4L2_M2M_DST = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define V4L2_CID_TRANS_TIME_MSEC (V4L2_CID_USER_BASE + 0x1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_USER_BASE + 0x1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static struct vim2m_fmt *find_format(u32 fourcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct vim2m_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) for (k = 0; k < NUM_FORMATS; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) fmt = &formats[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (fmt->fourcc == fourcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (k == NUM_FORMATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return &formats[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void get_alignment(u32 fourcc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned int *walign, unsigned int *halign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) switch (fourcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) case V4L2_PIX_FMT_SBGGR8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) case V4L2_PIX_FMT_SGBRG8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case V4L2_PIX_FMT_SGRBG8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case V4L2_PIX_FMT_SRGGB8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *walign = BAYER_WIDTH_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) *halign = BAYER_HEIGHT_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *walign = WIDTH_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) *halign = HEIGHT_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct vim2m_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct v4l2_device v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct video_device vfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #ifdef CONFIG_MEDIA_CONTROLLER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct media_device mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) atomic_t num_inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct mutex dev_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct v4l2_m2m_dev *m2m_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct vim2m_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct v4l2_fh fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct vim2m_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct v4l2_ctrl_handler hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Processed buffers in this transaction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u8 num_processed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* Transaction length (i.e. how many buffers per transaction) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) u32 translen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* Transaction time (i.e. simulated processing time) in milliseconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) u32 transtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct mutex vb_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct delayed_work work_run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* Abort requested by m2m */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int aborting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* Processing mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) enum v4l2_colorspace colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) enum v4l2_ycbcr_encoding ycbcr_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) enum v4l2_xfer_func xfer_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) enum v4l2_quantization quant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* Source and destination queue data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct vim2m_q_data q_data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static inline struct vim2m_ctx *file2ctx(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return container_of(file->private_data, struct vim2m_ctx, fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) enum v4l2_buf_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case V4L2_BUF_TYPE_VIDEO_OUTPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return &ctx->q_data[V4L2_M2M_SRC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case V4L2_BUF_TYPE_VIDEO_CAPTURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return &ctx->q_data[V4L2_M2M_DST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static const char *type_name(enum v4l2_buf_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case V4L2_BUF_TYPE_VIDEO_OUTPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return "Output";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case V4L2_BUF_TYPE_VIDEO_CAPTURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return "Capture";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return "Invalid";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #define CLIP(__color) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) (u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static void copy_line(struct vim2m_q_data *q_data_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u8 *src, u8 *dst, bool reverse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int x, depth = q_data_out->fmt->depth >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (!reverse) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) memcpy(dst, src, q_data_out->width * depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) for (x = 0; x < q_data_out->width >> 1; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) memcpy(dst, src, depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) memcpy(dst + depth, src - depth, depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) src -= depth << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) dst += depth << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void copy_two_pixels(struct vim2m_q_data *q_data_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct vim2m_q_data *q_data_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) u8 *src[2], u8 **dst, int ypos, bool reverse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct vim2m_fmt *out = q_data_out->fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct vim2m_fmt *in = q_data_in->fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) u8 _r[2], _g[2], _b[2], *r, *g, *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* Step 1: read two consecutive pixels from src pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) r = _r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) g = _g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) b = _b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) switch (in->fourcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) case V4L2_PIX_FMT_RGB565: /* rrrrrggg gggbbbbb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u16 pix = le16_to_cpu(*(__le16 *)(src[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *r++ = (u8)(((pix & 0xf800) >> 11) << 3) | 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) *g++ = (u8)((((pix & 0x07e0) >> 5)) << 2) | 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *b++ = (u8)((pix & 0x1f) << 3) | 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case V4L2_PIX_FMT_RGB565X: /* gggbbbbb rrrrrggg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) u16 pix = be16_to_cpu(*(__be16 *)(src[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) *r++ = (u8)(((pix & 0xf800) >> 11) << 3) | 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) *g++ = (u8)((((pix & 0x07e0) >> 5)) << 2) | 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) *b++ = (u8)((pix & 0x1f) << 3) | 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case V4L2_PIX_FMT_RGB24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) *r++ = src[i][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *g++ = src[i][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *b++ = src[i][2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) case V4L2_PIX_FMT_BGR24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) *b++ = src[i][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) *g++ = src[i][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) *r++ = src[i][2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* Step 2: store two consecutive points, reversing them if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) r = _r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) g = _g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) b = _b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) switch (out->fourcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case V4L2_PIX_FMT_RGB565: /* rrrrrggg gggbbbbb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) u16 pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) __le16 *dst_pix = (__le16 *)*dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) pix = ((*r << 8) & 0xf800) | ((*g << 3) & 0x07e0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) (*b >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) *dst_pix = cpu_to_le16(pix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *dst += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) case V4L2_PIX_FMT_RGB565X: /* gggbbbbb rrrrrggg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) u16 pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) __be16 *dst_pix = (__be16 *)*dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) pix = ((*r << 8) & 0xf800) | ((*g << 3) & 0x07e0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) (*b >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) *dst_pix = cpu_to_be16(pix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) *dst += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) case V4L2_PIX_FMT_RGB24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) *(*dst)++ = *r++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) *(*dst)++ = *g++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) *(*dst)++ = *b++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) case V4L2_PIX_FMT_BGR24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *(*dst)++ = *b++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *(*dst)++ = *g++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) *(*dst)++ = *r++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case V4L2_PIX_FMT_YUYV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) u8 y, y1, u, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) y = ((8453 * (*r) + 16594 * (*g) + 3223 * (*b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) + 524288) >> 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) u = ((-4878 * (*r) - 9578 * (*g) + 14456 * (*b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) + 4210688) >> 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) v = ((14456 * (*r++) - 12105 * (*g++) - 2351 * (*b++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) + 4210688) >> 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) y1 = ((8453 * (*r) + 16594 * (*g) + 3223 * (*b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) + 524288) >> 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *(*dst)++ = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *(*dst)++ = u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) *(*dst)++ = y1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) *(*dst)++ = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) case V4L2_PIX_FMT_SBGGR8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (!(ypos & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) *(*dst)++ = *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) *(*dst)++ = *++g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) *(*dst)++ = *g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) *(*dst)++ = *++r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) case V4L2_PIX_FMT_SGBRG8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!(ypos & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *(*dst)++ = *g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *(*dst)++ = *++b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) *(*dst)++ = *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) *(*dst)++ = *++g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) case V4L2_PIX_FMT_SGRBG8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!(ypos & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) *(*dst)++ = *g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) *(*dst)++ = *++r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) *(*dst)++ = *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) *(*dst)++ = *++g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) case V4L2_PIX_FMT_SRGGB8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (!(ypos & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) *(*dst)++ = *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) *(*dst)++ = *++g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) *(*dst)++ = *g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) *(*dst)++ = *++b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static int device_process(struct vim2m_ctx *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct vb2_v4l2_buffer *in_vb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct vb2_v4l2_buffer *out_vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct vim2m_dev *dev = ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct vim2m_q_data *q_data_in, *q_data_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) u8 *p_in, *p_line, *p_in_x[2], *p, *p_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) unsigned int width, height, bytesperline, bytes_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) unsigned int x, y, y_in, y_out, x_int, x_fract, x_err, x_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) int start, end, step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) q_data_in = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (!q_data_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) bytesperline = (q_data_in->width * q_data_in->fmt->depth) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) bytes_per_pixel = q_data_in->fmt->depth >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) q_data_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (!q_data_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* As we're doing scaling, use the output dimensions here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) height = q_data_out->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) width = q_data_out->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!p_in || !p_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) v4l2_err(&dev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) "Acquiring kernel pointers to buffers failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) out_vb->sequence = q_data_out->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) in_vb->sequence = q_data_in->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) v4l2_m2m_buf_copy_metadata(in_vb, out_vb, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (ctx->mode & MEM2MEM_VFLIP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) start = height - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) end = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) step = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) end = height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) step = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) y_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * When format and resolution are identical,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * we can use a faster copy logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (q_data_in->fmt->fourcc == q_data_out->fmt->fourcc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) q_data_in->width == q_data_out->width &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) q_data_in->height == q_data_out->height) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) for (y = start; y != end; y += step, y_out++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) p = p_in + (y * bytesperline);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (ctx->mode & MEM2MEM_HFLIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) p += bytesperline - (q_data_in->fmt->depth >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) copy_line(q_data_out, p, p_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ctx->mode & MEM2MEM_HFLIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) p_out += bytesperline;
^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) /* Slower algorithm with format conversion, hflip, vflip and scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /* To speed scaler up, use Bresenham for X dimension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) x_int = q_data_in->width / q_data_out->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) x_fract = q_data_in->width % q_data_out->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) for (y = start; y != end; y += step, y_out++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) y_in = (y * q_data_in->height) / q_data_out->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) x_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) x_err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) p_line = p_in + (y_in * bytesperline);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (ctx->mode & MEM2MEM_HFLIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) p_line += bytesperline - (q_data_in->fmt->depth >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) p_in_x[0] = p_line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) for (x = 0; x < width >> 1; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) x_offset += x_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) x_err += x_fract;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (x_err > width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) x_offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) x_err -= width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (ctx->mode & MEM2MEM_HFLIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) p_in_x[1] = p_line - x_offset * bytes_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) p_in_x[1] = p_line + x_offset * bytes_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) copy_two_pixels(q_data_in, q_data_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) p_in_x, &p_out, y_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ctx->mode & MEM2MEM_HFLIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* Calculate the next p_in_x0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) x_offset += x_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) x_err += x_fract;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (x_err > width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) x_offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) x_err -= width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (ctx->mode & MEM2MEM_HFLIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) p_in_x[0] = p_line - x_offset * bytes_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) p_in_x[0] = p_line + x_offset * bytes_per_pixel;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * mem2mem callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * job_ready() - check whether an instance is ready to be scheduled to run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static int job_ready(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct vim2m_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) || v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) dprintk(ctx->dev, 1, "Not enough buffers available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static void job_abort(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct vim2m_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* Will cancel the transaction in the next interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ctx->aborting = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* device_run() - prepares and starts the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * This simulates all the immediate preparations required before starting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * a device. This will be called by the framework when it decides to schedule
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * a particular instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static void device_run(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct vim2m_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct vb2_v4l2_buffer *src_buf, *dst_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* Apply request controls if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) &ctx->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) device_process(ctx, src_buf, dst_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /* Complete request controls if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) &ctx->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /* Run delayed work, which simulates a hardware irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) schedule_delayed_work(&ctx->work_run, msecs_to_jiffies(ctx->transtime));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static void device_work(struct work_struct *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct vim2m_ctx *curr_ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct vim2m_dev *vim2m_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct vb2_v4l2_buffer *src_vb, *dst_vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) curr_ctx = container_of(w, struct vim2m_ctx, work_run.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (!curr_ctx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) pr_err("Instance released before the end of transaction\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) vim2m_dev = curr_ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) curr_ctx->num_processed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (curr_ctx->num_processed == curr_ctx->translen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) || curr_ctx->aborting) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) dprintk(curr_ctx->dev, 2, "Finishing capture buffer fill\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) curr_ctx->num_processed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) v4l2_m2m_job_finish(vim2m_dev->m2m_dev, curr_ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) device_run(curr_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * video ioctls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static int vidioc_querycap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) snprintf(cap->bus_info, sizeof(cap->bus_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) "platform:%s", MEM2MEM_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) int i, num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct vim2m_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) for (i = 0; i < NUM_FORMATS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (formats[i].types & type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /* index-th format of type type found ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (num == f->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * Correct type but haven't reached our index yet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * just increment per-type index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ++num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (i < NUM_FORMATS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /* Format found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) fmt = &formats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) f->pixelformat = fmt->fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* Format not found */
^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) static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return enum_fmt(f, MEM2MEM_CAPTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return enum_fmt(f, MEM2MEM_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static int vidioc_enum_framesizes(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct v4l2_frmsizeenum *fsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (fsize->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (!find_format(fsize->pixel_format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) fsize->stepwise.min_width = MIN_W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) fsize->stepwise.min_height = MIN_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) fsize->stepwise.max_width = MAX_W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) fsize->stepwise.max_height = MAX_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) get_alignment(fsize->pixel_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) &fsize->stepwise.step_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) &fsize->stepwise.step_height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) static int vidioc_g_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) struct vb2_queue *vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct vim2m_q_data *q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) q_data = get_q_data(ctx, f->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (!q_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) f->fmt.pix.width = q_data->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) f->fmt.pix.height = q_data->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) f->fmt.pix.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) f->fmt.pix.pixelformat = q_data->fmt->fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) f->fmt.pix.sizeimage = q_data->sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) f->fmt.pix.colorspace = ctx->colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) f->fmt.pix.xfer_func = ctx->xfer_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) f->fmt.pix.quantization = ctx->quant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return vidioc_g_fmt(file2ctx(file), f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return vidioc_g_fmt(file2ctx(file), f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static int vidioc_try_fmt(struct v4l2_format *f, struct vim2m_fmt *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) int walign, halign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * V4L2 specification specifies the driver corrects the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * format struct if any of the dimensions is unsupported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (f->fmt.pix.height < MIN_H)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) f->fmt.pix.height = MIN_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) else if (f->fmt.pix.height > MAX_H)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) f->fmt.pix.height = MAX_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (f->fmt.pix.width < MIN_W)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) f->fmt.pix.width = MIN_W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) else if (f->fmt.pix.width > MAX_W)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) f->fmt.pix.width = MAX_W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) get_alignment(f->fmt.pix.pixelformat, &walign, &halign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) f->fmt.pix.width &= ~(walign - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) f->fmt.pix.height &= ~(halign - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) f->fmt.pix.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return 0;
^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 vidioc_try_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct vim2m_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct vim2m_ctx *ctx = file2ctx(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) fmt = find_format(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) f->fmt.pix.pixelformat = formats[0].fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) fmt = find_format(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (!(fmt->types & MEM2MEM_CAPTURE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) v4l2_err(&ctx->dev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) "Fourcc format (0x%08x) invalid.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) f->fmt.pix.colorspace = ctx->colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) f->fmt.pix.xfer_func = ctx->xfer_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) f->fmt.pix.quantization = ctx->quant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return vidioc_try_fmt(f, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct vim2m_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct vim2m_ctx *ctx = file2ctx(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) fmt = find_format(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (!fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) f->fmt.pix.pixelformat = formats[0].fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) fmt = find_format(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (!(fmt->types & MEM2MEM_OUTPUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) v4l2_err(&ctx->dev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) "Fourcc format (0x%08x) invalid.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (!f->fmt.pix.colorspace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return vidioc_try_fmt(f, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) static int vidioc_s_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct vim2m_q_data *q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct vb2_queue *vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (!vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) q_data = get_q_data(ctx, f->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (!q_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (vb2_is_busy(vq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) q_data->fmt = find_format(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) q_data->width = f->fmt.pix.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) q_data->height = f->fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) q_data->sizeimage = q_data->width * q_data->height
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * q_data->fmt->depth >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) dprintk(ctx->dev, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) "Format for type %s: %dx%d (%d bpp), fmt: %c%c%c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) type_name(f->type), q_data->width, q_data->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) q_data->fmt->depth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) (q_data->fmt->fourcc & 0xff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) (q_data->fmt->fourcc >> 8) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) (q_data->fmt->fourcc >> 16) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) (q_data->fmt->fourcc >> 24) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) ret = vidioc_try_fmt_vid_cap(file, priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return vidioc_s_fmt(file2ctx(file), f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct vim2m_ctx *ctx = file2ctx(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) ret = vidioc_try_fmt_vid_out(file, priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) ret = vidioc_s_fmt(file2ctx(file), f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) ctx->colorspace = f->fmt.pix.colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) ctx->xfer_func = f->fmt.pix.xfer_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) ctx->quant = f->fmt.pix.quantization;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static int vim2m_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct vim2m_ctx *ctx =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) container_of(ctrl->handler, struct vim2m_ctx, hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) case V4L2_CID_HFLIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (ctrl->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) ctx->mode |= MEM2MEM_HFLIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ctx->mode &= ~MEM2MEM_HFLIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) case V4L2_CID_VFLIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (ctrl->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ctx->mode |= MEM2MEM_VFLIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) ctx->mode &= ~MEM2MEM_VFLIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) case V4L2_CID_TRANS_TIME_MSEC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) ctx->transtime = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (ctx->transtime < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ctx->transtime = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) case V4L2_CID_TRANS_NUM_BUFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) ctx->translen = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static const struct v4l2_ctrl_ops vim2m_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .s_ctrl = vim2m_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) .vidioc_querycap = vidioc_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) .vidioc_enum_framesizes = vidioc_enum_framesizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .vidioc_streamon = v4l2_m2m_ioctl_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) * Queue operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static int vim2m_queue_setup(struct vb2_queue *vq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) unsigned int *nbuffers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) unsigned int *nplanes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) unsigned int sizes[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct device *alloc_devs[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct vim2m_q_data *q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) unsigned int size, count = *nbuffers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) q_data = get_q_data(ctx, vq->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (!q_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) size = q_data->width * q_data->height * q_data->fmt->depth >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) while (size * count > MEM2MEM_VID_MEM_LIMIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) (count)--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) *nbuffers = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (*nplanes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return sizes[0] < size ? -EINVAL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) *nplanes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) sizes[0] = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) dprintk(ctx->dev, 1, "%s: get %d buffer(s) of size %d each.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) type_name(vq->type), count, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static int vim2m_buf_out_validate(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (vbuf->field == V4L2_FIELD_ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) vbuf->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (vbuf->field != V4L2_FIELD_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) dprintk(ctx->dev, 1, "%s field isn't supported\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static int vim2m_buf_prepare(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct vim2m_q_data *q_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) dprintk(ctx->dev, 2, "type: %s\n", type_name(vb->vb2_queue->type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) q_data = get_q_data(ctx, vb->vb2_queue->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (!q_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) dprintk(ctx->dev, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) "%s data will not fit into plane (%lu < %lu)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) __func__, vb2_plane_size(vb, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) (long)q_data->sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) vb2_set_plane_payload(vb, 0, q_data->sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static void vim2m_buf_queue(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static int vim2m_start_streaming(struct vb2_queue *q, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct vim2m_q_data *q_data = get_q_data(ctx, q->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (!q_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (V4L2_TYPE_IS_OUTPUT(q->type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) ctx->aborting = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) q_data->sequence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) static void vim2m_stop_streaming(struct vb2_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) struct vb2_v4l2_buffer *vbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) cancel_delayed_work_sync(&ctx->work_run);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (V4L2_TYPE_IS_OUTPUT(q->type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (!vbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) &ctx->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static void vim2m_buf_request_complete(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) static const struct vb2_ops vim2m_qops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) .queue_setup = vim2m_queue_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) .buf_out_validate = vim2m_buf_out_validate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) .buf_prepare = vim2m_buf_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) .buf_queue = vim2m_buf_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) .start_streaming = vim2m_start_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) .stop_streaming = vim2m_stop_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) .wait_prepare = vb2_ops_wait_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) .wait_finish = vb2_ops_wait_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) .buf_request_complete = vim2m_buf_request_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static int queue_init(void *priv, struct vb2_queue *src_vq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct vb2_queue *dst_vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct vim2m_ctx *ctx = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) src_vq->drv_priv = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) src_vq->ops = &vim2m_qops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) src_vq->mem_ops = &vb2_vmalloc_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) src_vq->lock = &ctx->vb_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) src_vq->supports_requests = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ret = vb2_queue_init(src_vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) dst_vq->drv_priv = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) dst_vq->ops = &vim2m_qops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) dst_vq->mem_ops = &vb2_vmalloc_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) dst_vq->lock = &ctx->vb_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return vb2_queue_init(dst_vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) static struct v4l2_ctrl_config vim2m_ctrl_trans_time_msec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) .ops = &vim2m_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) .id = V4L2_CID_TRANS_TIME_MSEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) .name = "Transaction Time (msec)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) .max = 10001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static const struct v4l2_ctrl_config vim2m_ctrl_trans_num_bufs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) .ops = &vim2m_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) .id = V4L2_CID_TRANS_NUM_BUFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) .name = "Buffers Per Transaction",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) .def = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) .max = MEM2MEM_DEF_NUM_BUFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) * File operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) static int vim2m_open(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) struct vim2m_dev *dev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) struct vim2m_ctx *ctx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct v4l2_ctrl_handler *hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (mutex_lock_interruptible(&dev->dev_mutex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (!ctx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) goto open_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) v4l2_fh_init(&ctx->fh, video_devdata(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) file->private_data = &ctx->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) ctx->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) hdl = &ctx->hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) v4l2_ctrl_handler_init(hdl, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) vim2m_ctrl_trans_time_msec.def = default_transtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_time_msec, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_num_bufs, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) rc = hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) v4l2_ctrl_handler_free(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) goto open_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) ctx->fh.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) v4l2_ctrl_handler_setup(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) ctx->q_data[V4L2_M2M_SRC].width = 640;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) ctx->q_data[V4L2_M2M_SRC].height = 480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) ctx->q_data[V4L2_M2M_SRC].sizeimage =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) ctx->q_data[V4L2_M2M_SRC].width *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) ctx->q_data[V4L2_M2M_SRC].height *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) (ctx->q_data[V4L2_M2M_SRC].fmt->depth >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) ctx->colorspace = V4L2_COLORSPACE_REC709;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) mutex_init(&ctx->vb_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) INIT_DELAYED_WORK(&ctx->work_run, device_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (IS_ERR(ctx->fh.m2m_ctx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) rc = PTR_ERR(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) v4l2_ctrl_handler_free(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) v4l2_fh_exit(&ctx->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) goto open_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) v4l2_fh_add(&ctx->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) atomic_inc(&dev->num_inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) dprintk(dev, 1, "Created instance: %p, m2m_ctx: %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) ctx, ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) open_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) mutex_unlock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) static int vim2m_release(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) struct vim2m_dev *dev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) struct vim2m_ctx *ctx = file2ctx(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) dprintk(dev, 1, "Releasing instance %p\n", ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) v4l2_fh_del(&ctx->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) v4l2_fh_exit(&ctx->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) v4l2_ctrl_handler_free(&ctx->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) mutex_lock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) mutex_unlock(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) atomic_dec(&dev->num_inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) static void vim2m_device_release(struct video_device *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) struct vim2m_dev *dev = container_of(vdev, struct vim2m_dev, vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) v4l2_device_unregister(&dev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) v4l2_m2m_release(dev->m2m_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) #ifdef CONFIG_MEDIA_CONTROLLER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) media_device_cleanup(&dev->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) kfree(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) static const struct v4l2_file_operations vim2m_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) .open = vim2m_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) .release = vim2m_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) .poll = v4l2_m2m_fop_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) .mmap = v4l2_m2m_fop_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) static const struct video_device vim2m_videodev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) .name = MEM2MEM_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) .vfl_dir = VFL_DIR_M2M,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) .fops = &vim2m_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) .ioctl_ops = &vim2m_ioctl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) .minor = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) .release = vim2m_device_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) static const struct v4l2_m2m_ops m2m_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) .device_run = device_run,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) .job_ready = job_ready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) .job_abort = job_abort,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) static const struct media_device_ops m2m_media_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) .req_validate = vb2_request_validate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) .req_queue = v4l2_m2m_request_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) static int vim2m_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) struct vim2m_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) struct video_device *vfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) dev = kzalloc(sizeof(*dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) goto error_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) atomic_set(&dev->num_inst, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) mutex_init(&dev->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) dev->vfd = vim2m_videodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) vfd = &dev->vfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) vfd->lock = &dev->dev_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) vfd->v4l2_dev = &dev->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) goto error_v4l2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) video_set_drvdata(vfd, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) v4l2_info(&dev->v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) "Device registered as /dev/video%d\n", vfd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) platform_set_drvdata(pdev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (IS_ERR(dev->m2m_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) ret = PTR_ERR(dev->m2m_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) dev->m2m_dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) goto error_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) #ifdef CONFIG_MEDIA_CONTROLLER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) dev->mdev.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) strscpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) strscpy(dev->mdev.bus_info, "platform:vim2m",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) sizeof(dev->mdev.bus_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) media_device_init(&dev->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) dev->mdev.ops = &m2m_media_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) dev->v4l2_dev.mdev = &dev->mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) MEDIA_ENT_F_PROC_VIDEO_SCALER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) goto error_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) ret = media_device_register(&dev->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) goto error_m2m_mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) #ifdef CONFIG_MEDIA_CONTROLLER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) error_m2m_mc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) v4l2_m2m_unregister_media_controller(dev->m2m_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) error_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) video_unregister_device(&dev->vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* vim2m_device_release called by video_unregister_device to release various objects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) error_v4l2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) v4l2_device_unregister(&dev->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) error_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) kfree(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) static int vim2m_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) struct vim2m_dev *dev = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) #ifdef CONFIG_MEDIA_CONTROLLER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) media_device_unregister(&dev->mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) v4l2_m2m_unregister_media_controller(dev->m2m_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) video_unregister_device(&dev->vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) static struct platform_driver vim2m_pdrv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) .probe = vim2m_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) .remove = vim2m_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) .name = MEM2MEM_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) static void __exit vim2m_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) platform_driver_unregister(&vim2m_pdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) platform_device_unregister(&vim2m_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) static int __init vim2m_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) ret = platform_device_register(&vim2m_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) ret = platform_driver_register(&vim2m_pdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) platform_device_unregister(&vim2m_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) module_init(vim2m_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) module_exit(vim2m_exit);