aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/platform/vimc
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+huawei@kernel.org>2020-03-24 10:39:43 +0100
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2020-04-14 10:29:04 +0200
commit4b32216adb010a364f23a055c45e06e839b089f9 (patch)
tree22481ce43cd63d628025e80a11ef9de5c580a5e2 /drivers/media/platform/vimc
parentdee1877d9168f3e4b5e3c384d6d217dd1bbd4b49 (diff)
media: split test drivers from platform directory
When the first test device was added (vivi.c), there were just one file. I was too lazy on that time to create a separate directory just for it, so I kept it together with platform. Now, we have vivid, vicodec, vim2m and vimc. Also, a new virtual driver has been prepared to support DVB API. So, it is time to solve this mess, by placing test stuff on a separate directory. It should be noticed that we also have some skeleton drivers (for V4L and for DVB). For now, we'll keep them separate, as they're not really test drivers, but instead, just examples. The DVB frontend ones will likely be part of a new DVB test driver. By that time, it should make sense to move them here as well. Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Diffstat (limited to 'drivers/media/platform/vimc')
-rw-r--r--drivers/media/platform/vimc/Kconfig15
-rw-r--r--drivers/media/platform/vimc/Makefile6
-rw-r--r--drivers/media/platform/vimc/vimc-capture.c480
-rw-r--r--drivers/media/platform/vimc/vimc-common.c369
-rw-r--r--drivers/media/platform/vimc/vimc-common.h224
-rw-r--r--drivers/media/platform/vimc/vimc-core.c381
-rw-r--r--drivers/media/platform/vimc/vimc-debayer.c581
-rw-r--r--drivers/media/platform/vimc/vimc-scaler.c511
-rw-r--r--drivers/media/platform/vimc/vimc-sensor.c376
-rw-r--r--drivers/media/platform/vimc/vimc-streamer.c238
-rw-r--r--drivers/media/platform/vimc/vimc-streamer.h44
11 files changed, 0 insertions, 3225 deletions
diff --git a/drivers/media/platform/vimc/Kconfig b/drivers/media/platform/vimc/Kconfig
deleted file mode 100644
index bd221d3e1a4a..000000000000
--- a/drivers/media/platform/vimc/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_VIMC
- tristate "Virtual Media Controller Driver (VIMC)"
- depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
- select VIDEOBUF2_VMALLOC
- select VIDEO_V4L2_TPG
- help
- Skeleton driver for Virtual Media Controller
-
- This driver can be compared to the vivid driver for emulating
- a media node that exposes a complex media topology. The topology
- is hard coded for now but is meant to be highly configurable in
- the future.
-
- When in doubt, say N.
diff --git a/drivers/media/platform/vimc/Makefile b/drivers/media/platform/vimc/Makefile
deleted file mode 100644
index a53b2b532e9f..000000000000
--- a/drivers/media/platform/vimc/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-vimc-y := vimc-core.o vimc-common.o vimc-streamer.o vimc-capture.o \
- vimc-debayer.o vimc-scaler.o vimc-sensor.o
-
-obj-$(CONFIG_VIDEO_VIMC) += vimc.o
-
diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c
deleted file mode 100644
index 23e740c1c5c0..000000000000
--- a/drivers/media/platform/vimc/vimc-capture.c
+++ /dev/null
@@ -1,480 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-capture.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
-#include <media/videobuf2-vmalloc.h>
-
-#include "vimc-common.h"
-#include "vimc-streamer.h"
-
-struct vimc_cap_device {
- struct vimc_ent_device ved;
- struct video_device vdev;
- struct v4l2_pix_format format;
- struct vb2_queue queue;
- struct list_head buf_list;
- /*
- * NOTE: in a real driver, a spin lock must be used to access the
- * queue because the frames are generated from a hardware interruption
- * and the isr is not allowed to sleep.
- * Even if it is not necessary a spinlock in the vimc driver, we
- * use it here as a code reference
- */
- spinlock_t qlock;
- struct mutex lock;
- u32 sequence;
- struct vimc_stream stream;
- struct media_pad pad;
-};
-
-static const struct v4l2_pix_format fmt_default = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_RGB24,
- .field = V4L2_FIELD_NONE,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
-};
-
-struct vimc_cap_buffer {
- /*
- * struct vb2_v4l2_buffer must be the first element
- * the videobuf2 framework will allocate this struct based on
- * buf_struct_size and use the first sizeof(struct vb2_buffer) bytes of
- * memory as a vb2_buffer
- */
- struct vb2_v4l2_buffer vb2;
- struct list_head list;
-};
-
-static int vimc_cap_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- strscpy(cap->driver, VIMC_PDEV_NAME, sizeof(cap->driver));
- strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card));
- snprintf(cap->bus_info, sizeof(cap->bus_info),
- "platform:%s", VIMC_PDEV_NAME);
-
- return 0;
-}
-
-static void vimc_cap_get_format(struct vimc_ent_device *ved,
- struct v4l2_pix_format *fmt)
-{
- struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device,
- ved);
-
- *fmt = vcap->format;
-}
-
-static int vimc_cap_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vimc_cap_device *vcap = video_drvdata(file);
-
- f->fmt.pix = vcap->format;
-
- return 0;
-}
-
-static int vimc_cap_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct v4l2_pix_format *format = &f->fmt.pix;
- const struct vimc_pix_map *vpix;
-
- format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH,
- VIMC_FRAME_MAX_WIDTH) & ~1;
- format->height = clamp_t(u32, format->height, VIMC_FRAME_MIN_HEIGHT,
- VIMC_FRAME_MAX_HEIGHT) & ~1;
-
- /* Don't accept a pixelformat that is not on the table */
- vpix = vimc_pix_map_by_pixelformat(format->pixelformat);
- if (!vpix) {
- format->pixelformat = fmt_default.pixelformat;
- vpix = vimc_pix_map_by_pixelformat(format->pixelformat);
- }
- /* TODO: Add support for custom bytesperline values */
- format->bytesperline = format->width * vpix->bpp;
- format->sizeimage = format->bytesperline * format->height;
-
- if (format->field == V4L2_FIELD_ANY)
- format->field = fmt_default.field;
-
- vimc_colorimetry_clamp(format);
-
- return 0;
-}
-
-static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vimc_cap_device *vcap = video_drvdata(file);
- int ret;
-
- /* Do not change the format while stream is on */
- if (vb2_is_busy(&vcap->queue))
- return -EBUSY;
-
- ret = vimc_cap_try_fmt_vid_cap(file, priv, f);
- if (ret)
- return ret;
-
- dev_dbg(vcap->ved.dev, "%s: format update: "
- "old:%dx%d (0x%x, %d, %d, %d, %d) "
- "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vcap->vdev.name,
- /* old */
- vcap->format.width, vcap->format.height,
- vcap->format.pixelformat, vcap->format.colorspace,
- vcap->format.quantization, vcap->format.xfer_func,
- vcap->format.ycbcr_enc,
- /* new */
- f->fmt.pix.width, f->fmt.pix.height,
- f->fmt.pix.pixelformat, f->fmt.pix.colorspace,
- f->fmt.pix.quantization, f->fmt.pix.xfer_func,
- f->fmt.pix.ycbcr_enc);
-
- vcap->format = f->fmt.pix;
-
- return 0;
-}
-
-static int vimc_cap_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- const struct vimc_pix_map *vpix = vimc_pix_map_by_index(f->index);
-
- if (!vpix)
- return -EINVAL;
-
- f->pixelformat = vpix->pixelformat;
-
- return 0;
-}
-
-static int vimc_cap_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
-{
- const struct vimc_pix_map *vpix;
-
- if (fsize->index)
- return -EINVAL;
-
- /* Only accept code in the pix map table */
- vpix = vimc_pix_map_by_code(fsize->pixel_format);
- if (!vpix)
- return -EINVAL;
-
- fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
- fsize->stepwise.min_width = VIMC_FRAME_MIN_WIDTH;
- fsize->stepwise.max_width = VIMC_FRAME_MAX_WIDTH;
- fsize->stepwise.min_height = VIMC_FRAME_MIN_HEIGHT;
- fsize->stepwise.max_height = VIMC_FRAME_MAX_HEIGHT;
- fsize->stepwise.step_width = 1;
- fsize->stepwise.step_height = 1;
-
- return 0;
-}
-
-static const struct v4l2_file_operations vimc_cap_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = vb2_fop_release,
- .read = vb2_fop_read,
- .poll = vb2_fop_poll,
- .unlocked_ioctl = video_ioctl2,
- .mmap = vb2_fop_mmap,
-};
-
-static const struct v4l2_ioctl_ops vimc_cap_ioctl_ops = {
- .vidioc_querycap = vimc_cap_querycap,
-
- .vidioc_g_fmt_vid_cap = vimc_cap_g_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = vimc_cap_s_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = vimc_cap_try_fmt_vid_cap,
- .vidioc_enum_fmt_vid_cap = vimc_cap_enum_fmt_vid_cap,
- .vidioc_enum_framesizes = vimc_cap_enum_framesizes,
-
- .vidioc_reqbufs = vb2_ioctl_reqbufs,
- .vidioc_create_bufs = vb2_ioctl_create_bufs,
- .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
- .vidioc_querybuf = vb2_ioctl_querybuf,
- .vidioc_qbuf = vb2_ioctl_qbuf,
- .vidioc_dqbuf = vb2_ioctl_dqbuf,
- .vidioc_expbuf = vb2_ioctl_expbuf,
- .vidioc_streamon = vb2_ioctl_streamon,
- .vidioc_streamoff = vb2_ioctl_streamoff,
-};
-
-static void vimc_cap_return_all_buffers(struct vimc_cap_device *vcap,
- enum vb2_buffer_state state)
-{
- struct vimc_cap_buffer *vbuf, *node;
-
- spin_lock(&vcap->qlock);
-
- list_for_each_entry_safe(vbuf, node, &vcap->buf_list, list) {
- list_del(&vbuf->list);
- vb2_buffer_done(&vbuf->vb2.vb2_buf, state);
- }
-
- spin_unlock(&vcap->qlock);
-}
-
-static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
- struct media_entity *entity = &vcap->vdev.entity;
- int ret;
-
- vcap->sequence = 0;
-
- /* Start the media pipeline */
- ret = media_pipeline_start(entity, &vcap->stream.pipe);
- if (ret) {
- vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);
- return ret;
- }
-
- ret = vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 1);
- if (ret) {
- media_pipeline_stop(entity);
- vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);
- return ret;
- }
-
- return 0;
-}
-
-/*
- * Stop the stream engine. Any remaining buffers in the stream queue are
- * dequeued and passed on to the vb2 framework marked as STATE_ERROR.
- */
-static void vimc_cap_stop_streaming(struct vb2_queue *vq)
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
-
- vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 0);
-
- /* Stop the media pipeline */
- media_pipeline_stop(&vcap->vdev.entity);
-
- /* Release all active buffers */
- vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_ERROR);
-}
-
-static void vimc_cap_buf_queue(struct vb2_buffer *vb2_buf)
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vb2_buf->vb2_queue);
- struct vimc_cap_buffer *buf = container_of(vb2_buf,
- struct vimc_cap_buffer,
- vb2.vb2_buf);
-
- spin_lock(&vcap->qlock);
- list_add_tail(&buf->list, &vcap->buf_list);
- spin_unlock(&vcap->qlock);
-}
-
-static int vimc_cap_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned int sizes[],
- struct device *alloc_devs[])
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
-
- if (*nplanes)
- return sizes[0] < vcap->format.sizeimage ? -EINVAL : 0;
- /* We don't support multiplanes for now */
- *nplanes = 1;
- sizes[0] = vcap->format.sizeimage;
-
- return 0;
-}
-
-static int vimc_cap_buffer_prepare(struct vb2_buffer *vb)
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vb->vb2_queue);
- unsigned long size = vcap->format.sizeimage;
-
- if (vb2_plane_size(vb, 0) < size) {
- dev_err(vcap->ved.dev, "%s: buffer too small (%lu < %lu)\n",
- vcap->vdev.name, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
- return 0;
-}
-
-static const struct vb2_ops vimc_cap_qops = {
- .start_streaming = vimc_cap_start_streaming,
- .stop_streaming = vimc_cap_stop_streaming,
- .buf_queue = vimc_cap_buf_queue,
- .queue_setup = vimc_cap_queue_setup,
- .buf_prepare = vimc_cap_buffer_prepare,
- /*
- * Since q->lock is set we can use the standard
- * vb2_ops_wait_prepare/finish helper functions.
- */
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-static const struct media_entity_operations vimc_cap_mops = {
- .link_validate = vimc_vdev_link_validate,
-};
-
-void vimc_cap_release(struct vimc_ent_device *ved)
-{
- struct vimc_cap_device *vcap =
- container_of(ved, struct vimc_cap_device, ved);
-
- media_entity_cleanup(vcap->ved.ent);
- kfree(vcap);
-}
-
-void vimc_cap_unregister(struct vimc_ent_device *ved)
-{
- struct vimc_cap_device *vcap =
- container_of(ved, struct vimc_cap_device, ved);
-
- vb2_queue_release(&vcap->queue);
- video_unregister_device(&vcap->vdev);
-}
-
-static void *vimc_cap_process_frame(struct vimc_ent_device *ved,
- const void *frame)
-{
- struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device,
- ved);
- struct vimc_cap_buffer *vimc_buf;
- void *vbuf;
-
- spin_lock(&vcap->qlock);
-
- /* Get the first entry of the list */
- vimc_buf = list_first_entry_or_null(&vcap->buf_list,
- typeof(*vimc_buf), list);
- if (!vimc_buf) {
- spin_unlock(&vcap->qlock);
- return ERR_PTR(-EAGAIN);
- }
-
- /* Remove this entry from the list */
- list_del(&vimc_buf->list);
-
- spin_unlock(&vcap->qlock);
-
- /* Fill the buffer */
- vimc_buf->vb2.vb2_buf.timestamp = ktime_get_ns();
- vimc_buf->vb2.sequence = vcap->sequence++;
- vimc_buf->vb2.field = vcap->format.field;
-
- vbuf = vb2_plane_vaddr(&vimc_buf->vb2.vb2_buf, 0);
-
- memcpy(vbuf, frame, vcap->format.sizeimage);
-
- /* Set it as ready */
- vb2_set_plane_payload(&vimc_buf->vb2.vb2_buf, 0,
- vcap->format.sizeimage);
- vb2_buffer_done(&vimc_buf->vb2.vb2_buf, VB2_BUF_STATE_DONE);
- return NULL;
-}
-
-struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc,
- const char *vcfg_name)
-{
- struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
- const struct vimc_pix_map *vpix;
- struct vimc_cap_device *vcap;
- struct video_device *vdev;
- struct vb2_queue *q;
- int ret;
-
- /* Allocate the vimc_cap_device struct */
- vcap = kzalloc(sizeof(*vcap), GFP_KERNEL);
- if (!vcap)
- return NULL;
-
- /* Initialize the media entity */
- vcap->vdev.entity.name = vcfg_name;
- vcap->vdev.entity.function = MEDIA_ENT_F_IO_V4L;
- vcap->pad.flags = MEDIA_PAD_FL_SINK;
- ret = media_entity_pads_init(&vcap->vdev.entity,
- 1, &vcap->pad);
- if (ret)
- goto err_free_vcap;
-
- /* Initialize the lock */
- mutex_init(&vcap->lock);
-
- /* Initialize the vb2 queue */
- q = &vcap->queue;
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_USERPTR;
- q->drv_priv = vcap;
- q->buf_struct_size = sizeof(struct vimc_cap_buffer);
- q->ops = &vimc_cap_qops;
- q->mem_ops = &vb2_vmalloc_memops;
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->min_buffers_needed = 2;
- q->lock = &vcap->lock;
-
- ret = vb2_queue_init(q);
- if (ret) {
- dev_err(vimc->mdev.dev, "%s: vb2 queue init failed (err=%d)\n",
- vcfg_name, ret);
- goto err_clean_m_ent;
- }
-
- /* Initialize buffer list and its lock */
- INIT_LIST_HEAD(&vcap->buf_list);
- spin_lock_init(&vcap->qlock);
-
- /* Set default frame format */
- vcap->format = fmt_default;
- vpix = vimc_pix_map_by_pixelformat(vcap->format.pixelformat);
- vcap->format.bytesperline = vcap->format.width * vpix->bpp;
- vcap->format.sizeimage = vcap->format.bytesperline *
- vcap->format.height;
-
- /* Fill the vimc_ent_device struct */
- vcap->ved.ent = &vcap->vdev.entity;
- vcap->ved.process_frame = vimc_cap_process_frame;
- vcap->ved.vdev_get_format = vimc_cap_get_format;
- vcap->ved.dev = vimc->mdev.dev;
-
- /* Initialize the video_device struct */
- vdev = &vcap->vdev;
- vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- vdev->entity.ops = &vimc_cap_mops;
- vdev->release = video_device_release_empty;
- vdev->fops = &vimc_cap_fops;
- vdev->ioctl_ops = &vimc_cap_ioctl_ops;
- vdev->lock = &vcap->lock;
- vdev->queue = q;
- vdev->v4l2_dev = v4l2_dev;
- vdev->vfl_dir = VFL_DIR_RX;
- strscpy(vdev->name, vcfg_name, sizeof(vdev->name));
- video_set_drvdata(vdev, &vcap->ved);
-
- /* Register the video_device with the v4l2 and the media framework */
- ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
- if (ret) {
- dev_err(vimc->mdev.dev, "%s: video register failed (err=%d)\n",
- vcap->vdev.name, ret);
- goto err_release_queue;
- }
-
- return &vcap->ved;
-
-err_release_queue:
- vb2_queue_release(q);
-err_clean_m_ent:
- media_entity_cleanup(&vcap->vdev.entity);
-err_free_vcap:
- kfree(vcap);
-
- return NULL;
-}
diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c
deleted file mode 100644
index c95c17c048f2..000000000000
--- a/drivers/media/platform/vimc/vimc-common.c
+++ /dev/null
@@ -1,369 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-common.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include "vimc-common.h"
-
-/*
- * NOTE: non-bayer formats need to come first (necessary for enum_mbus_code
- * in the scaler)
- */
-static const struct vimc_pix_map vimc_pix_map_list[] = {
- /* TODO: add all missing formats */
-
- /* RGB formats */
- {
- .code = MEDIA_BUS_FMT_BGR888_1X24,
- .pixelformat = V4L2_PIX_FMT_BGR24,
- .bpp = 3,
- .bayer = false,
- },
- {
- .code = MEDIA_BUS_FMT_RGB888_1X24,
- .pixelformat = V4L2_PIX_FMT_RGB24,
- .bpp = 3,
- .bayer = false,
- },
- {
- .code = MEDIA_BUS_FMT_ARGB8888_1X32,
- .pixelformat = V4L2_PIX_FMT_ARGB32,
- .bpp = 4,
- .bayer = false,
- },
-
- /* Bayer formats */
- {
- .code = MEDIA_BUS_FMT_SBGGR8_1X8,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGBRG8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGRBG8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB8_1X8,
- .pixelformat = V4L2_PIX_FMT_SRGGB8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
- .pixelformat = V4L2_PIX_FMT_SBGGR10,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_1X10,
- .pixelformat = V4L2_PIX_FMT_SGBRG10,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
- .pixelformat = V4L2_PIX_FMT_SGRBG10,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
- .pixelformat = V4L2_PIX_FMT_SRGGB10,
- .bpp = 2,
- .bayer = true,
- },
-
- /* 10bit raw bayer a-law compressed to 8 bits */
- {
- .code = MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8,
- .pixelformat = V4L2_PIX_FMT_SBGGR10ALAW8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGBRG10ALAW8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8,
- .pixelformat = V4L2_PIX_FMT_SRGGB10ALAW8,
- .bpp = 1,
- .bayer = true,
- },
-
- /* 10bit raw bayer DPCM compressed to 8 bits */
- {
- .code = MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
- .pixelformat = V4L2_PIX_FMT_SBGGR10DPCM8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGBRG10DPCM8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
- .pixelformat = V4L2_PIX_FMT_SRGGB10DPCM8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR12_1X12,
- .pixelformat = V4L2_PIX_FMT_SBGGR12,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG12_1X12,
- .pixelformat = V4L2_PIX_FMT_SGBRG12,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG12_1X12,
- .pixelformat = V4L2_PIX_FMT_SGRBG12,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB12_1X12,
- .pixelformat = V4L2_PIX_FMT_SRGGB12,
- .bpp = 2,
- .bayer = true,
- },
-};
-
-bool vimc_is_source(struct media_entity *ent)
-{
- unsigned int i;
-
- for (i = 0; i < ent->num_pads; i++)
- if (ent->pads[i].flags & MEDIA_PAD_FL_SINK)
- return false;
- return true;
-}
-
-const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i)
-{
- if (i >= ARRAY_SIZE(vimc_pix_map_list))
- return NULL;
-
- return &vimc_pix_map_list[i];
-}
-
-const struct vimc_pix_map *vimc_pix_map_by_code(u32 code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
- if (vimc_pix_map_list[i].code == code)
- return &vimc_pix_map_list[i];
- }
- return NULL;
-}
-
-const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
- if (vimc_pix_map_list[i].pixelformat == pixelformat)
- return &vimc_pix_map_list[i];
- }
- return NULL;
-}
-
-static int vimc_get_pix_format(struct media_pad *pad,
- struct v4l2_pix_format *fmt)
-{
- if (is_media_entity_v4l2_subdev(pad->entity)) {
- struct v4l2_subdev *sd =
- media_entity_to_v4l2_subdev(pad->entity);
- struct v4l2_subdev_format sd_fmt;
- const struct vimc_pix_map *pix_map;
- int ret;
-
- sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
- sd_fmt.pad = pad->index;
-
- ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt);
- if (ret)
- return ret;
-
- v4l2_fill_pix_format(fmt, &sd_fmt.format);
- pix_map = vimc_pix_map_by_code(sd_fmt.format.code);
- fmt->pixelformat = pix_map->pixelformat;
- } else if (is_media_entity_v4l2_video_device(pad->entity)) {
- struct video_device *vdev = container_of(pad->entity,
- struct video_device,
- entity);
- struct vimc_ent_device *ved = video_get_drvdata(vdev);
-
- if (!ved->vdev_get_format)
- return -ENOIOCTLCMD;
-
- ved->vdev_get_format(ved, fmt);
- } else {
- return -EINVAL;
- }
-
- return 0;
-}
-
-int vimc_vdev_link_validate(struct media_link *link)
-{
- struct v4l2_pix_format source_fmt, sink_fmt;
- int ret;
-
- ret = vimc_get_pix_format(link->source, &source_fmt);
- if (ret)
- return ret;
-
- ret = vimc_get_pix_format(link->sink, &sink_fmt);
- if (ret)
- return ret;
-
- pr_info("vimc link validate: "
- "%s:src:%dx%d (0x%x, %d, %d, %d, %d) "
- "%s:snk:%dx%d (0x%x, %d, %d, %d, %d)\n",
- /* src */
- link->source->entity->name,
- source_fmt.width, source_fmt.height,
- source_fmt.pixelformat, source_fmt.colorspace,
- source_fmt.quantization, source_fmt.xfer_func,
- source_fmt.ycbcr_enc,
- /* sink */
- link->sink->entity->name,
- sink_fmt.width, sink_fmt.height,
- sink_fmt.pixelformat, sink_fmt.colorspace,
- sink_fmt.quantization, sink_fmt.xfer_func,
- sink_fmt.ycbcr_enc);
-
- /* The width, height and pixelformat must match. */
- if (source_fmt.width != sink_fmt.width ||
- source_fmt.height != sink_fmt.height ||
- source_fmt.pixelformat != sink_fmt.pixelformat)
- return -EPIPE;
-
- /*
- * The field order must match, or the sink field order must be NONE
- * to support interlaced hardware connected to bridges that support
- * progressive formats only.
- */
- if (source_fmt.field != sink_fmt.field &&
- sink_fmt.field != V4L2_FIELD_NONE)
- return -EPIPE;
-
- /*
- * If colorspace is DEFAULT, then assume all the colorimetry is also
- * DEFAULT, return 0 to skip comparing the other colorimetry parameters
- */
- if (source_fmt.colorspace == V4L2_COLORSPACE_DEFAULT ||
- sink_fmt.colorspace == V4L2_COLORSPACE_DEFAULT)
- return 0;
-
- /* Colorspace must match. */
- if (source_fmt.colorspace != sink_fmt.colorspace)
- return -EPIPE;
-
- /* Colorimetry must match if they are not set to DEFAULT */
- if (source_fmt.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT &&
- sink_fmt.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT &&
- source_fmt.ycbcr_enc != sink_fmt.ycbcr_enc)
- return -EPIPE;
-
- if (source_fmt.quantization != V4L2_QUANTIZATION_DEFAULT &&
- sink_fmt.quantization != V4L2_QUANTIZATION_DEFAULT &&
- source_fmt.quantization != sink_fmt.quantization)
- return -EPIPE;
-
- if (source_fmt.xfer_func != V4L2_XFER_FUNC_DEFAULT &&
- sink_fmt.xfer_func != V4L2_XFER_FUNC_DEFAULT &&
- source_fmt.xfer_func != sink_fmt.xfer_func)
- return -EPIPE;
-
- return 0;
-}
-
-static const struct media_entity_operations vimc_ent_sd_mops = {
- .link_validate = v4l2_subdev_link_validate,
-};
-
-int vimc_ent_sd_register(struct vimc_ent_device *ved,
- struct v4l2_subdev *sd,
- struct v4l2_device *v4l2_dev,
- const char *const name,
- u32 function,
- u16 num_pads,
- struct media_pad *pads,
- const struct v4l2_subdev_ops *sd_ops)
-{
- int ret;
-
- /* Fill the vimc_ent_device struct */
- ved->ent = &sd->entity;
-
- /* Initialize the subdev */
- v4l2_subdev_init(sd, sd_ops);
- sd->entity.function = function;
- sd->entity.ops = &vimc_ent_sd_mops;
- sd->owner = THIS_MODULE;
- strscpy(sd->name, name, sizeof(sd->name));
- v4l2_set_subdevdata(sd, ved);
-
- /* Expose this subdev to user space */
- sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- if (sd->ctrl_handler)
- sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
-
- /* Initialize the media entity */
- ret = media_entity_pads_init(&sd->entity, num_pads, pads);
- if (ret)
- return ret;
-
- /* Register the subdev with the v4l2 and the media framework */
- ret = v4l2_device_register_subdev(v4l2_dev, sd);
- if (ret) {
- dev_err(v4l2_dev->dev,
- "%s: subdev register failed (err=%d)\n",
- name, ret);
- goto err_clean_m_ent;
- }
-
- return 0;
-
-err_clean_m_ent:
- media_entity_cleanup(&sd->entity);
- return ret;
-}
diff --git a/drivers/media/platform/vimc/vimc-common.h b/drivers/media/platform/vimc/vimc-common.h
deleted file mode 100644
index 616d5a6b0754..000000000000
--- a/drivers/media/platform/vimc/vimc-common.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * vimc-common.h Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#ifndef _VIMC_COMMON_H_
-#define _VIMC_COMMON_H_
-
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <media/media-device.h>
-#include <media/v4l2-device.h>
-
-#define VIMC_PDEV_NAME "vimc"
-
-/* VIMC-specific controls */
-#define VIMC_CID_VIMC_BASE (0x00f00000 | 0xf000)
-#define VIMC_CID_VIMC_CLASS (0x00f00000 | 1)
-#define VIMC_CID_TEST_PATTERN (VIMC_CID_VIMC_BASE + 0)
-#define VIMC_CID_MEAN_WIN_SIZE (VIMC_CID_VIMC_BASE + 1)
-
-#define VIMC_FRAME_MAX_WIDTH 4096
-#define VIMC_FRAME_MAX_HEIGHT 2160
-#define VIMC_FRAME_MIN_WIDTH 16
-#define VIMC_FRAME_MIN_HEIGHT 16
-
-#define VIMC_FRAME_INDEX(lin, col, width, bpp) ((lin * width + col) * bpp)
-
-/* Source and sink pad checks */
-#define VIMC_IS_SRC(pad) (pad)
-#define VIMC_IS_SINK(pad) (!(pad))
-
-/**
- * struct vimc_colorimetry_clamp - Adjust colorimetry parameters
- *
- * @fmt: the pointer to struct v4l2_pix_format or
- * struct v4l2_mbus_framefmt
- *
- * Entities must check if colorimetry given by the userspace is valid, if not
- * then set them as DEFAULT
- */
-#define vimc_colorimetry_clamp(fmt) \
-do { \
- if ((fmt)->colorspace == V4L2_COLORSPACE_DEFAULT \
- || (fmt)->colorspace > V4L2_COLORSPACE_DCI_P3) { \
- (fmt)->colorspace = V4L2_COLORSPACE_DEFAULT; \
- (fmt)->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; \
- (fmt)->quantization = V4L2_QUANTIZATION_DEFAULT; \
- (fmt)->xfer_func = V4L2_XFER_FUNC_DEFAULT; \
- } \
- if ((fmt)->ycbcr_enc > V4L2_YCBCR_ENC_SMPTE240M) \
- (fmt)->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; \
- if ((fmt)->quantization > V4L2_QUANTIZATION_LIM_RANGE) \
- (fmt)->quantization = V4L2_QUANTIZATION_DEFAULT; \
- if ((fmt)->xfer_func > V4L2_XFER_FUNC_SMPTE2084) \
- (fmt)->xfer_func = V4L2_XFER_FUNC_DEFAULT; \
-} while (0)
-
-/**
- * struct vimc_pix_map - maps media bus code with v4l2 pixel format
- *
- * @code: media bus format code defined by MEDIA_BUS_FMT_* macros
- * @bbp: number of bytes each pixel occupies
- * @pixelformat: pixel format devined by V4L2_PIX_FMT_* macros
- *
- * Struct which matches the MEDIA_BUS_FMT_* codes with the corresponding
- * V4L2_PIX_FMT_* fourcc pixelformat and its bytes per pixel (bpp)
- */
-struct vimc_pix_map {
- unsigned int code;
- unsigned int bpp;
- u32 pixelformat;
- bool bayer;
-};
-
-/**
- * struct vimc_ent_device - core struct that represents an entity in the
- * topology
- *
- * @dev: a pointer of the device struct of the driver
- * @ent: the pointer to struct media_entity for the node
- * @process_frame: callback send a frame to that node
- * @vdev_get_format: callback that returns the current format a pad, used
- * only when is_media_entity_v4l2_video_device(ent) returns
- * true
- *
- * Each node of the topology must create a vimc_ent_device struct. Depending on
- * the node it will be of an instance of v4l2_subdev or video_device struct
- * where both contains a struct media_entity.
- * Those structures should embedded the vimc_ent_device struct through
- * v4l2_set_subdevdata() and video_set_drvdata() respectivaly, allowing the
- * vimc_ent_device struct to be retrieved from the corresponding struct
- * media_entity
- */
-struct vimc_ent_device {
- struct device *dev;
- struct media_entity *ent;
- void * (*process_frame)(struct vimc_ent_device *ved,
- const void *frame);
- void (*vdev_get_format)(struct vimc_ent_device *ved,
- struct v4l2_pix_format *fmt);
-};
-
-/**
- * struct vimc_device - main device for vimc driver
- *
- * @pipe_cfg pointer to the vimc pipeline configuration structure
- * @ent_devs array of vimc_ent_device pointers
- * @mdev the associated media_device parent
- * @v4l2_dev Internal v4l2 parent device
- */
-struct vimc_device {
- const struct vimc_pipeline_config *pipe_cfg;
- struct vimc_ent_device **ent_devs;
- struct media_device mdev;
- struct v4l2_device v4l2_dev;
-};
-
-/**
- * struct vimc_ent_config Structure which describes individual
- * configuration for each entity
- *
- * @name entity name
- * @ved pointer to vimc_ent_device (a node in the
- * topology)
- * @add initializes and registers
- * vim entity - called from vimc-core
- * @unregister unregisters vimc entity - called from vimc-core
- * @release releases vimc entity - called from the v4l2_dev
- * release callback
- */
-struct vimc_ent_config {
- const char *name;
- struct vimc_ent_device *(*add)(struct vimc_device *vimc,
- const char *vcfg_name);
- void (*unregister)(struct vimc_ent_device *ved);
- void (*release)(struct vimc_ent_device *ved);
-};
-
-/**
- * vimc_is_source - returns true if the entity has only source pads
- *
- * @ent: pointer to &struct media_entity
- *
- */
-bool vimc_is_source(struct media_entity *ent);
-
-/* prototypes for vimc_ent_config hooks */
-struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc,
- const char *vcfg_name);
-void vimc_cap_unregister(struct vimc_ent_device *ved);
-void vimc_cap_release(struct vimc_ent_device *ved);
-
-struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
- const char *vcfg_name);
-void vimc_deb_release(struct vimc_ent_device *ved);
-
-struct vimc_ent_device *vimc_sca_add(struct vimc_device *vimc,
- const char *vcfg_name);
-void vimc_sca_release(struct vimc_ent_device *ved);
-
-struct vimc_ent_device *vimc_sen_add(struct vimc_device *vimc,
- const char *vcfg_name);
-void vimc_sen_release(struct vimc_ent_device *ved);
-
-/**
- * vimc_pix_map_by_index - get vimc_pix_map struct by its index
- *
- * @i: index of the vimc_pix_map struct in vimc_pix_map_list
- */
-const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i);
-
-/**
- * vimc_pix_map_by_code - get vimc_pix_map struct by media bus code
- *
- * @code: media bus format code defined by MEDIA_BUS_FMT_* macros
- */
-const struct vimc_pix_map *vimc_pix_map_by_code(u32 code);
-
-/**
- * vimc_pix_map_by_pixelformat - get vimc_pix_map struct by v4l2 pixel format
- *
- * @pixelformat: pixel format devined by V4L2_PIX_FMT_* macros
- */
-const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat);
-
-/**
- * vimc_ent_sd_register - initialize and register a subdev node
- *
- * @ved: the vimc_ent_device struct to be initialize
- * @sd: the v4l2_subdev struct to be initialize and registered
- * @v4l2_dev: the v4l2 device to register the v4l2_subdev
- * @name: name of the sub-device. Please notice that the name must be
- * unique.
- * @function: media entity function defined by MEDIA_ENT_F_* macros
- * @num_pads: number of pads to initialize
- * @pads: the array of pads of the entity, the caller should set the
- flags of the pads
- * @sd_ops: pointer to &struct v4l2_subdev_ops.
- *
- * Helper function initialize and register the struct vimc_ent_device and struct
- * v4l2_subdev which represents a subdev node in the topology
- */
-int vimc_ent_sd_register(struct vimc_ent_device *ved,
- struct v4l2_subdev *sd,
- struct v4l2_device *v4l2_dev,
- const char *const name,
- u32 function,
- u16 num_pads,
- struct media_pad *pads,
- const struct v4l2_subdev_ops *sd_ops);
-
-/**
- * vimc_vdev_link_validate - validates a media link
- *
- * @link: pointer to &struct media_link
- *
- * This function calls validates if a media link is valid for streaming.
- */
-int vimc_vdev_link_validate(struct media_link *link);
-
-#endif
diff --git a/drivers/media/platform/vimc/vimc-core.c b/drivers/media/platform/vimc/vimc-core.c
deleted file mode 100644
index 339126e565dc..000000000000
--- a/drivers/media/platform/vimc/vimc-core.c
+++ /dev/null
@@ -1,381 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-core.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <media/media-device.h>
-#include <media/v4l2-device.h>
-
-#include "vimc-common.h"
-
-#define VIMC_MDEV_MODEL_NAME "VIMC MDEV"
-
-#define VIMC_ENT_LINK(src, srcpad, sink, sinkpad, link_flags) { \
- .src_ent = src, \
- .src_pad = srcpad, \
- .sink_ent = sink, \
- .sink_pad = sinkpad, \
- .flags = link_flags, \
-}
-
-/* Structure which describes links between entities */
-struct vimc_ent_link {
- unsigned int src_ent;
- u16 src_pad;
- unsigned int sink_ent;
- u16 sink_pad;
- u32 flags;
-};
-
-/* Structure which describes the whole topology */
-struct vimc_pipeline_config {
- const struct vimc_ent_config *ents;
- size_t num_ents;
- const struct vimc_ent_link *links;
- size_t num_links;
-};
-
-/* --------------------------------------------------------------------------
- * Topology Configuration
- */
-
-static struct vimc_ent_config ent_config[] = {
- {
- .name = "Sensor A",
- .add = vimc_sen_add,
- .release = vimc_sen_release,
- },
- {
- .name = "Sensor B",
- .add = vimc_sen_add,
- .release = vimc_sen_release,
- },
- {
- .name = "Debayer A",
- .add = vimc_deb_add,
- .release = vimc_deb_release,
- },
- {
- .name = "Debayer B",
- .add = vimc_deb_add,
- .release = vimc_deb_release,
- },
- {
- .name = "Raw Capture 0",
- .add = vimc_cap_add,
- .unregister = vimc_cap_unregister,
- .release = vimc_cap_release,
- },
- {
- .name = "Raw Capture 1",
- .add = vimc_cap_add,
- .unregister = vimc_cap_unregister,
- .release = vimc_cap_release,
- },
- {
- /* TODO: change this to vimc-input when it is implemented */
- .name = "RGB/YUV Input",
- .add = vimc_sen_add,
- .release = vimc_sen_release,
- },
- {
- .name = "Scaler",
- .add = vimc_sca_add,
- .release = vimc_sca_release,
- },
- {
- .name = "RGB/YUV Capture",
- .add = vimc_cap_add,
- .unregister = vimc_cap_unregister,
- .release = vimc_cap_release,
- },
-};
-
-static const struct vimc_ent_link ent_links[] = {
- /* Link: Sensor A (Pad 0)->(Pad 0) Debayer A */
- VIMC_ENT_LINK(0, 0, 2, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
- /* Link: Sensor A (Pad 0)->(Pad 0) Raw Capture 0 */
- VIMC_ENT_LINK(0, 0, 4, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
- /* Link: Sensor B (Pad 0)->(Pad 0) Debayer B */
- VIMC_ENT_LINK(1, 0, 3, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
- /* Link: Sensor B (Pad 0)->(Pad 0) Raw Capture 1 */
- VIMC_ENT_LINK(1, 0, 5, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
- /* Link: Debayer A (Pad 1)->(Pad 0) Scaler */
- VIMC_ENT_LINK(2, 1, 7, 0, MEDIA_LNK_FL_ENABLED),
- /* Link: Debayer B (Pad 1)->(Pad 0) Scaler */
- VIMC_ENT_LINK(3, 1, 7, 0, 0),
- /* Link: RGB/YUV Input (Pad 0)->(Pad 0) Scaler */
- VIMC_ENT_LINK(6, 0, 7, 0, 0),
- /* Link: Scaler (Pad 1)->(Pad 0) RGB/YUV Capture */
- VIMC_ENT_LINK(7, 1, 8, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
-};
-
-static struct vimc_pipeline_config pipe_cfg = {
- .ents = ent_config,
- .num_ents = ARRAY_SIZE(ent_config),
- .links = ent_links,
- .num_links = ARRAY_SIZE(ent_links)
-};
-
-/* -------------------------------------------------------------------------- */
-
-static void vimc_rm_links(struct vimc_device *vimc)
-{
- unsigned int i;
-
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
- media_entity_remove_links(vimc->ent_devs[i]->ent);
-}
-
-static int vimc_create_links(struct vimc_device *vimc)
-{
- unsigned int i;
- int ret;
-
- /* Initialize the links between entities */
- for (i = 0; i < vimc->pipe_cfg->num_links; i++) {
- const struct vimc_ent_link *link = &vimc->pipe_cfg->links[i];
-
- struct vimc_ent_device *ved_src =
- vimc->ent_devs[link->src_ent];
- struct vimc_ent_device *ved_sink =
- vimc->ent_devs[link->sink_ent];
-
- ret = media_create_pad_link(ved_src->ent, link->src_pad,
- ved_sink->ent, link->sink_pad,
- link->flags);
- if (ret)
- goto err_rm_links;
- }
-
- return 0;
-
-err_rm_links:
- vimc_rm_links(vimc);
- return ret;
-}
-
-static int vimc_add_subdevs(struct vimc_device *vimc)
-{
- unsigned int i;
-
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++) {
- dev_dbg(vimc->mdev.dev, "new entity for %s\n",
- vimc->pipe_cfg->ents[i].name);
- vimc->ent_devs[i] = vimc->pipe_cfg->ents[i].add(vimc,
- vimc->pipe_cfg->ents[i].name);
- if (!vimc->ent_devs[i]) {
- dev_err(vimc->mdev.dev, "add new entity for %s\n",
- vimc->pipe_cfg->ents[i].name);
- return -EINVAL;
- }
- }
- return 0;
-}
-
-static void vimc_release_subdevs(struct vimc_device *vimc)
-{
- unsigned int i;
-
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
- if (vimc->ent_devs[i])
- vimc->pipe_cfg->ents[i].release(vimc->ent_devs[i]);
-}
-
-static void vimc_unregister_subdevs(struct vimc_device *vimc)
-{
- unsigned int i;
-
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
- if (vimc->ent_devs[i] && vimc->pipe_cfg->ents[i].unregister)
- vimc->pipe_cfg->ents[i].unregister(vimc->ent_devs[i]);
-}
-
-static void vimc_v4l2_dev_release(struct v4l2_device *v4l2_dev)
-{
- struct vimc_device *vimc =
- container_of(v4l2_dev, struct vimc_device, v4l2_dev);
-
- vimc_release_subdevs(vimc);
- media_device_cleanup(&vimc->mdev);
- kfree(vimc->ent_devs);
- kfree(vimc);
-}
-
-static int vimc_register_devices(struct vimc_device *vimc)
-{
- int ret;
-
- /* Register the v4l2 struct */
- ret = v4l2_device_register(vimc->mdev.dev, &vimc->v4l2_dev);
- if (ret) {
- dev_err(vimc->mdev.dev,
- "v4l2 device register failed (err=%d)\n", ret);
- return ret;
- }
- /* allocate ent_devs */
- vimc->ent_devs = kcalloc(vimc->pipe_cfg->num_ents,
- sizeof(*vimc->ent_devs), GFP_KERNEL);
- if (!vimc->ent_devs) {
- ret = -ENOMEM;
- goto err_v4l2_unregister;
- }
-
- /* Invoke entity config hooks to initialize and register subdevs */
- ret = vimc_add_subdevs(vimc);
- if (ret)
- /* remove sundevs that got added */
- goto err_rm_subdevs;
-
- /* Initialize links */
- ret = vimc_create_links(vimc);
- if (ret)
- goto err_rm_subdevs;
-
- /* Register the media device */
- ret = media_device_register(&vimc->mdev);
- if (ret) {
- dev_err(vimc->mdev.dev,
- "media device register failed (err=%d)\n", ret);
- goto err_rm_subdevs;
- }
-
- /* Expose all subdev's nodes*/
- ret = v4l2_device_register_subdev_nodes(&vimc->v4l2_dev);
- if (ret) {
- dev_err(vimc->mdev.dev,
- "vimc subdev nodes registration failed (err=%d)\n",
- ret);
- goto err_mdev_unregister;
- }
-
- return 0;
-
-err_mdev_unregister:
- media_device_unregister(&vimc->mdev);
-err_rm_subdevs:
- vimc_unregister_subdevs(vimc);
- vimc_release_subdevs(vimc);
- kfree(vimc->ent_devs);
-err_v4l2_unregister:
- v4l2_device_unregister(&vimc->v4l2_dev);
-
- return ret;
-}
-
-static void vimc_unregister(struct vimc_device *vimc)
-{
- vimc_unregister_subdevs(vimc);
- media_device_unregister(&vimc->mdev);
- v4l2_device_unregister(&vimc->v4l2_dev);
-}
-
-static int vimc_probe(struct platform_device *pdev)
-{
- struct vimc_device *vimc;
- int ret;
-
- dev_dbg(&pdev->dev, "probe");
-
- vimc = kzalloc(sizeof(*vimc), GFP_KERNEL);
- if (!vimc)
- return -ENOMEM;
-
- vimc->pipe_cfg = &pipe_cfg;
-
- /* Link the media device within the v4l2_device */
- vimc->v4l2_dev.mdev = &vimc->mdev;
-
- /* Initialize media device */
- strscpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME,
- sizeof(vimc->mdev.model));
- snprintf(vimc->mdev.bus_info, sizeof(vimc->mdev.bus_info),
- "platform:%s", VIMC_PDEV_NAME);
- vimc->mdev.dev = &pdev->dev;
- media_device_init(&vimc->mdev);
-
- ret = vimc_register_devices(vimc);
- if (ret) {
- media_device_cleanup(&vimc->mdev);
- kfree(vimc);
- return ret;
- }
- /*
- * the release cb is set only after successful registration.
- * if the registration fails, we release directly from probe
- */
-
- vimc->v4l2_dev.release = vimc_v4l2_dev_release;
- platform_set_drvdata(pdev, vimc);
- return 0;
-}
-
-static int vimc_remove(struct platform_device *pdev)
-{
- struct vimc_device *vimc = platform_get_drvdata(pdev);
-
- dev_dbg(&pdev->dev, "remove");
-
- vimc_unregister(vimc);
- v4l2_device_put(&vimc->v4l2_dev);
-
- return 0;
-}
-
-static void vimc_dev_release(struct device *dev)
-{
-}
-
-static struct platform_device vimc_pdev = {
- .name = VIMC_PDEV_NAME,
- .dev.release = vimc_dev_release,
-};
-
-static struct platform_driver vimc_pdrv = {
- .probe = vimc_probe,
- .remove = vimc_remove,
- .driver = {
- .name = VIMC_PDEV_NAME,
- },
-};
-
-static int __init vimc_init(void)
-{
- int ret;
-
- ret = platform_device_register(&vimc_pdev);
- if (ret) {
- dev_err(&vimc_pdev.dev,
- "platform device registration failed (err=%d)\n", ret);
- return ret;
- }
-
- ret = platform_driver_register(&vimc_pdrv);
- if (ret) {
- dev_err(&vimc_pdev.dev,
- "platform driver registration failed (err=%d)\n", ret);
- platform_driver_unregister(&vimc_pdrv);
- return ret;
- }
-
- return 0;
-}
-
-static void __exit vimc_exit(void)
-{
- platform_driver_unregister(&vimc_pdrv);
-
- platform_device_unregister(&vimc_pdev);
-}
-
-module_init(vimc_init);
-module_exit(vimc_exit);
-
-MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC)");
-MODULE_AUTHOR("Helen Fornazier <helen.fornazier@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/vimc/vimc-debayer.c b/drivers/media/platform/vimc/vimc-debayer.c
deleted file mode 100644
index baf6bf9f65b5..000000000000
--- a/drivers/media/platform/vimc/vimc-debayer.c
+++ /dev/null
@@ -1,581 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-debayer.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/vmalloc.h>
-#include <linux/v4l2-mediabus.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-subdev.h>
-
-#include "vimc-common.h"
-
-enum vimc_deb_rgb_colors {
- VIMC_DEB_RED = 0,
- VIMC_DEB_GREEN = 1,
- VIMC_DEB_BLUE = 2,
-};
-
-struct vimc_deb_pix_map {
- u32 code;
- enum vimc_deb_rgb_colors order[2][2];
-};
-
-struct vimc_deb_device {
- struct vimc_ent_device ved;
- struct v4l2_subdev sd;
- /* The active format */
- struct v4l2_mbus_framefmt sink_fmt;
- u32 src_code;
- void (*set_rgb_src)(struct vimc_deb_device *vdeb, unsigned int lin,
- unsigned int col, unsigned int rgb[3]);
- /* Values calculated when the stream starts */
- u8 *src_frame;
- const struct vimc_deb_pix_map *sink_pix_map;
- unsigned int sink_bpp;
- unsigned int mean_win_size;
- struct v4l2_ctrl_handler hdl;
- struct media_pad pads[2];
-};
-
-static const struct v4l2_mbus_framefmt sink_fmt_default = {
- .width = 640,
- .height = 480,
- .code = MEDIA_BUS_FMT_SRGGB8_1X8,
- .field = V4L2_FIELD_NONE,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
-};
-
-static const struct vimc_deb_pix_map vimc_deb_pix_map_list[] = {
- {
- .code = MEDIA_BUS_FMT_SBGGR8_1X8,
- .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_RED } }
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG8_1X8,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
- { VIMC_DEB_RED, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG8_1X8,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
- { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB8_1X8,
- .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
- .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_RED } }
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_1X10,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
- { VIMC_DEB_RED, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
- { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
- .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR12_1X12,
- .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_RED } }
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG12_1X12,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
- { VIMC_DEB_RED, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG12_1X12,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
- { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB12_1X12,
- .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
- },
-};
-
-static const struct vimc_deb_pix_map *vimc_deb_pix_map_by_code(u32 code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(vimc_deb_pix_map_list); i++)
- if (vimc_deb_pix_map_list[i].code == code)
- return &vimc_deb_pix_map_list[i];
-
- return NULL;
-}
-
-static int vimc_deb_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *mf;
- unsigned int i;
-
- mf = v4l2_subdev_get_try_format(sd, cfg, 0);
- *mf = sink_fmt_default;
-
- for (i = 1; i < sd->entity.num_pads; i++) {
- mf = v4l2_subdev_get_try_format(sd, cfg, i);
- *mf = sink_fmt_default;
- mf->code = vdeb->src_code;
- }
-
- return 0;
-}
-
-static int vimc_deb_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- /* We only support one format for source pads */
- if (VIMC_IS_SRC(code->pad)) {
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
-
- if (code->index)
- return -EINVAL;
-
- code->code = vdeb->src_code;
- } else {
- if (code->index >= ARRAY_SIZE(vimc_deb_pix_map_list))
- return -EINVAL;
-
- code->code = vimc_deb_pix_map_list[code->index].code;
- }
-
- return 0;
-}
-
-static int vimc_deb_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
-
- if (fse->index)
- return -EINVAL;
-
- if (VIMC_IS_SINK(fse->pad)) {
- const struct vimc_deb_pix_map *vpix =
- vimc_deb_pix_map_by_code(fse->code);
-
- if (!vpix)
- return -EINVAL;
- } else if (fse->code != vdeb->src_code) {
- return -EINVAL;
- }
-
- fse->min_width = VIMC_FRAME_MIN_WIDTH;
- fse->max_width = VIMC_FRAME_MAX_WIDTH;
- fse->min_height = VIMC_FRAME_MIN_HEIGHT;
- fse->max_height = VIMC_FRAME_MAX_HEIGHT;
-
- return 0;
-}
-
-static int vimc_deb_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
-
- /* Get the current sink format */
- fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ?
- *v4l2_subdev_get_try_format(sd, cfg, 0) :
- vdeb->sink_fmt;
-
- /* Set the right code for the source pad */
- if (VIMC_IS_SRC(fmt->pad))
- fmt->format.code = vdeb->src_code;
-
- return 0;
-}
-
-static void vimc_deb_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
-{
- const struct vimc_deb_pix_map *vpix;
-
- /* Don't accept a code that is not on the debayer table */
- vpix = vimc_deb_pix_map_by_code(fmt->code);
- if (!vpix)
- fmt->code = sink_fmt_default.code;
-
- fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
- VIMC_FRAME_MAX_WIDTH) & ~1;
- fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
- VIMC_FRAME_MAX_HEIGHT) & ~1;
-
- if (fmt->field == V4L2_FIELD_ANY)
- fmt->field = sink_fmt_default.field;
-
- vimc_colorimetry_clamp(fmt);
-}
-
-static int vimc_deb_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *sink_fmt;
-
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- /* Do not change the format while stream is on */
- if (vdeb->src_frame)
- return -EBUSY;
-
- sink_fmt = &vdeb->sink_fmt;
- } else {
- sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
- }
-
- /*
- * Do not change the format of the source pad,
- * it is propagated from the sink
- */
- if (VIMC_IS_SRC(fmt->pad)) {
- fmt->format = *sink_fmt;
- /* TODO: Add support for other formats */
- fmt->format.code = vdeb->src_code;
- } else {
- /* Set the new format in the sink pad */
- vimc_deb_adjust_sink_fmt(&fmt->format);
-
- dev_dbg(vdeb->ved.dev, "%s: sink format update: "
- "old:%dx%d (0x%x, %d, %d, %d, %d) "
- "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdeb->sd.name,
- /* old */
- sink_fmt->width, sink_fmt->height, sink_fmt->code,
- sink_fmt->colorspace, sink_fmt->quantization,
- sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
- /* new */
- fmt->format.width, fmt->format.height, fmt->format.code,
- fmt->format.colorspace, fmt->format.quantization,
- fmt->format.xfer_func, fmt->format.ycbcr_enc);
-
- *sink_fmt = fmt->format;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_pad_ops vimc_deb_pad_ops = {
- .init_cfg = vimc_deb_init_cfg,
- .enum_mbus_code = vimc_deb_enum_mbus_code,
- .enum_frame_size = vimc_deb_enum_frame_size,
- .get_fmt = vimc_deb_get_fmt,
- .set_fmt = vimc_deb_set_fmt,
-};
-
-static void vimc_deb_set_rgb_mbus_fmt_rgb888_1x24(struct vimc_deb_device *vdeb,
- unsigned int lin,
- unsigned int col,
- unsigned int rgb[3])
-{
- unsigned int i, index;
-
- index = VIMC_FRAME_INDEX(lin, col, vdeb->sink_fmt.width, 3);
- for (i = 0; i < 3; i++)
- vdeb->src_frame[index + i] = rgb[i];
-}
-
-static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
-
- if (enable) {
- const struct vimc_pix_map *vpix;
- unsigned int frame_size;
-
- if (vdeb->src_frame)
- return 0;
-
- /* Calculate the frame size of the source pad */
- vpix = vimc_pix_map_by_code(vdeb->src_code);
- frame_size = vdeb->sink_fmt.width * vdeb->sink_fmt.height *
- vpix->bpp;
-
- /* Save the bytes per pixel of the sink */
- vpix = vimc_pix_map_by_code(vdeb->sink_fmt.code);
- vdeb->sink_bpp = vpix->bpp;
-
- /* Get the corresponding pixel map from the table */
- vdeb->sink_pix_map =
- vimc_deb_pix_map_by_code(vdeb->sink_fmt.code);
-
- /*
- * Allocate the frame buffer. Use vmalloc to be able to
- * allocate a large amount of memory
- */
- vdeb->src_frame = vmalloc(frame_size);
- if (!vdeb->src_frame)
- return -ENOMEM;
-
- } else {
- if (!vdeb->src_frame)
- return 0;
-
- vfree(vdeb->src_frame);
- vdeb->src_frame = NULL;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_core_ops vimc_deb_core_ops = {
- .log_status = v4l2_ctrl_subdev_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
-static const struct v4l2_subdev_video_ops vimc_deb_video_ops = {
- .s_stream = vimc_deb_s_stream,
-};
-
-static const struct v4l2_subdev_ops vimc_deb_ops = {
- .core = &vimc_deb_core_ops,
- .pad = &vimc_deb_pad_ops,
- .video = &vimc_deb_video_ops,
-};
-
-static unsigned int vimc_deb_get_val(const u8 *bytes,
- const unsigned int n_bytes)
-{
- unsigned int i;
- unsigned int acc = 0;
-
- for (i = 0; i < n_bytes; i++)
- acc = acc + (bytes[i] << (8 * i));
-
- return acc;
-}
-
-static void vimc_deb_calc_rgb_sink(struct vimc_deb_device *vdeb,
- const u8 *frame,
- const unsigned int lin,
- const unsigned int col,
- unsigned int rgb[3])
-{
- unsigned int i, seek, wlin, wcol;
- unsigned int n_rgb[3] = {0, 0, 0};
-
- for (i = 0; i < 3; i++)
- rgb[i] = 0;
-
- /*
- * Calculate how many we need to subtract to get to the pixel in
- * the top left corner of the mean window (considering the current
- * pixel as the center)
- */
- seek = vdeb->mean_win_size / 2;
-
- /* Sum the values of the colors in the mean window */
-
- dev_dbg(vdeb->ved.dev,
- "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n",
- vdeb->sd.name, lin, col, vdeb->sink_fmt.height, seek);
-
- /*
- * Iterate through all the lines in the mean window, start
- * with zero if the pixel is outside the frame and don't pass
- * the height when the pixel is in the bottom border of the
- * frame
- */
- for (wlin = seek > lin ? 0 : lin - seek;
- wlin < lin + seek + 1 && wlin < vdeb->sink_fmt.height;
- wlin++) {
-
- /*
- * Iterate through all the columns in the mean window, start
- * with zero if the pixel is outside the frame and don't pass
- * the width when the pixel is in the right border of the
- * frame
- */
- for (wcol = seek > col ? 0 : col - seek;
- wcol < col + seek + 1 && wcol < vdeb->sink_fmt.width;
- wcol++) {
- enum vimc_deb_rgb_colors color;
- unsigned int index;
-
- /* Check which color this pixel is */
- color = vdeb->sink_pix_map->order[wlin % 2][wcol % 2];
-
- index = VIMC_FRAME_INDEX(wlin, wcol,
- vdeb->sink_fmt.width,
- vdeb->sink_bpp);
-
- dev_dbg(vdeb->ved.dev,
- "deb: %s: RGB CALC: frame index %d, win pos %dx%d, color %d\n",
- vdeb->sd.name, index, wlin, wcol, color);
-
- /* Get its value */
- rgb[color] = rgb[color] +
- vimc_deb_get_val(&frame[index], vdeb->sink_bpp);
-
- /* Save how many values we already added */
- n_rgb[color]++;
-
- dev_dbg(vdeb->ved.dev, "deb: %s: RGB CALC: val %d, n %d\n",
- vdeb->sd.name, rgb[color], n_rgb[color]);
- }
- }
-
- /* Calculate the mean */
- for (i = 0; i < 3; i++) {
- dev_dbg(vdeb->ved.dev,
- "deb: %s: PRE CALC: %dx%d Color %d, val %d, n %d\n",
- vdeb->sd.name, lin, col, i, rgb[i], n_rgb[i]);
-
- if (n_rgb[i])
- rgb[i] = rgb[i] / n_rgb[i];
-
- dev_dbg(vdeb->ved.dev,
- "deb: %s: FINAL CALC: %dx%d Color %d, val %d\n",
- vdeb->sd.name, lin, col, i, rgb[i]);
- }
-}
-
-static void *vimc_deb_process_frame(struct vimc_ent_device *ved,
- const void *sink_frame)
-{
- struct vimc_deb_device *vdeb = container_of(ved, struct vimc_deb_device,
- ved);
- unsigned int rgb[3];
- unsigned int i, j;
-
- /* If the stream in this node is not active, just return */
- if (!vdeb->src_frame)
- return ERR_PTR(-EINVAL);
-
- for (i = 0; i < vdeb->sink_fmt.height; i++)
- for (j = 0; j < vdeb->sink_fmt.width; j++) {
- vimc_deb_calc_rgb_sink(vdeb, sink_frame, i, j, rgb);
- vdeb->set_rgb_src(vdeb, i, j, rgb);
- }
-
- return vdeb->src_frame;
-}
-
-static int vimc_deb_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vimc_deb_device *vdeb =
- container_of(ctrl->handler, struct vimc_deb_device, hdl);
-
- switch (ctrl->id) {
- case VIMC_CID_MEAN_WIN_SIZE:
- vdeb->mean_win_size = ctrl->val;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vimc_deb_ctrl_ops = {
- .s_ctrl = vimc_deb_s_ctrl,
-};
-
-void vimc_deb_release(struct vimc_ent_device *ved)
-{
- struct vimc_deb_device *vdeb =
- container_of(ved, struct vimc_deb_device, ved);
-
- v4l2_ctrl_handler_free(&vdeb->hdl);
- media_entity_cleanup(vdeb->ved.ent);
- kfree(vdeb);
-}
-
-static const struct v4l2_ctrl_config vimc_deb_ctrl_class = {
- .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
- .id = VIMC_CID_VIMC_CLASS,
- .name = "VIMC Controls",
- .type = V4L2_CTRL_TYPE_CTRL_CLASS,
-};
-
-static const struct v4l2_ctrl_config vimc_deb_ctrl_mean_win_size = {
- .ops = &vimc_deb_ctrl_ops,
- .id = VIMC_CID_MEAN_WIN_SIZE,
- .name = "Debayer Mean Window Size",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 1,
- .max = 25,
- .step = 2,
- .def = 3,
-};
-
-struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
- const char *vcfg_name)
-{
- struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
- struct vimc_deb_device *vdeb;
- int ret;
-
- /* Allocate the vdeb struct */
- vdeb = kzalloc(sizeof(*vdeb), GFP_KERNEL);
- if (!vdeb)
- return NULL;
-
- /* Create controls: */
- v4l2_ctrl_handler_init(&vdeb->hdl, 2);
- v4l2_ctrl_new_custom(&vdeb->hdl, &vimc_deb_ctrl_class, NULL);
- v4l2_ctrl_new_custom(&vdeb->hdl, &vimc_deb_ctrl_mean_win_size, NULL);
- vdeb->sd.ctrl_handler = &vdeb->hdl;
- if (vdeb->hdl.error) {
- ret = vdeb->hdl.error;
- goto err_free_vdeb;
- }
-
- /* Initialize ved and sd */
- vdeb->pads[0].flags = MEDIA_PAD_FL_SINK;
- vdeb->pads[1].flags = MEDIA_PAD_FL_SOURCE;
-
- ret = vimc_ent_sd_register(&vdeb->ved, &vdeb->sd, v4l2_dev,
- vcfg_name,
- MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2,
- vdeb->pads, &vimc_deb_ops);
- if (ret)
- goto err_free_hdl;
-
- vdeb->ved.process_frame = vimc_deb_process_frame;
- vdeb->ved.dev = vimc->mdev.dev;
- vdeb->mean_win_size = vimc_deb_ctrl_mean_win_size.def;
-
- /* Initialize the frame format */
- vdeb->sink_fmt = sink_fmt_default;
- /*
- * TODO: Add support for more output formats, we only support
- * RGB888 for now
- * NOTE: the src format is always the same as the sink, except
- * for the code
- */
- vdeb->src_code = MEDIA_BUS_FMT_RGB888_1X24;
- vdeb->set_rgb_src = vimc_deb_set_rgb_mbus_fmt_rgb888_1x24;
-
- return &vdeb->ved;
-
-err_free_hdl:
- v4l2_ctrl_handler_free(&vdeb->hdl);
-err_free_vdeb:
- kfree(vdeb);
-
- return NULL;
-}
diff --git a/drivers/media/platform/vimc/vimc-scaler.c b/drivers/media/platform/vimc/vimc-scaler.c
deleted file mode 100644
index 7521439747c5..000000000000
--- a/drivers/media/platform/vimc/vimc-scaler.c
+++ /dev/null
@@ -1,511 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-scaler.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/moduleparam.h>
-#include <linux/vmalloc.h>
-#include <linux/v4l2-mediabus.h>
-#include <media/v4l2-rect.h>
-#include <media/v4l2-subdev.h>
-
-#include "vimc-common.h"
-
-static unsigned int sca_mult = 3;
-module_param(sca_mult, uint, 0000);
-MODULE_PARM_DESC(sca_mult, " the image size multiplier");
-
-#define MAX_ZOOM 8
-
-#define VIMC_SCA_FMT_WIDTH_DEFAULT 640
-#define VIMC_SCA_FMT_HEIGHT_DEFAULT 480
-
-struct vimc_sca_device {
- struct vimc_ent_device ved;
- struct v4l2_subdev sd;
- /* NOTE: the source fmt is the same as the sink
- * with the width and hight multiplied by mult
- */
- struct v4l2_mbus_framefmt sink_fmt;
- struct v4l2_rect crop_rect;
- /* Values calculated when the stream starts */
- u8 *src_frame;
- unsigned int src_line_size;
- unsigned int bpp;
- struct media_pad pads[2];
-};
-
-static const struct v4l2_mbus_framefmt sink_fmt_default = {
- .width = VIMC_SCA_FMT_WIDTH_DEFAULT,
- .height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
- .code = MEDIA_BUS_FMT_RGB888_1X24,
- .field = V4L2_FIELD_NONE,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
-};
-
-static const struct v4l2_rect crop_rect_default = {
- .width = VIMC_SCA_FMT_WIDTH_DEFAULT,
- .height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
- .top = 0,
- .left = 0,
-};
-
-static const struct v4l2_rect crop_rect_min = {
- .width = VIMC_FRAME_MIN_WIDTH,
- .height = VIMC_FRAME_MIN_HEIGHT,
- .top = 0,
- .left = 0,
-};
-
-static struct v4l2_rect
-vimc_sca_get_crop_bound_sink(const struct v4l2_mbus_framefmt *sink_fmt)
-{
- /* Get the crop bounds to clamp the crop rectangle correctly */
- struct v4l2_rect r = {
- .left = 0,
- .top = 0,
- .width = sink_fmt->width,
- .height = sink_fmt->height,
- };
- return r;
-}
-
-static void vimc_sca_adjust_sink_crop(struct v4l2_rect *r,
- const struct v4l2_mbus_framefmt *sink_fmt)
-{
- const struct v4l2_rect sink_rect =
- vimc_sca_get_crop_bound_sink(sink_fmt);
-
- /* Disallow rectangles smaller than the minimal one. */
- v4l2_rect_set_min_size(r, &crop_rect_min);
- v4l2_rect_map_inside(r, &sink_rect);
-}
-
-static int vimc_sca_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg)
-{
- struct v4l2_mbus_framefmt *mf;
- struct v4l2_rect *r;
- unsigned int i;
-
- mf = v4l2_subdev_get_try_format(sd, cfg, 0);
- *mf = sink_fmt_default;
-
- r = v4l2_subdev_get_try_crop(sd, cfg, 0);
- *r = crop_rect_default;
-
- for (i = 1; i < sd->entity.num_pads; i++) {
- mf = v4l2_subdev_get_try_format(sd, cfg, i);
- *mf = sink_fmt_default;
- mf->width = mf->width * sca_mult;
- mf->height = mf->height * sca_mult;
- }
-
- return 0;
-}
-
-static int vimc_sca_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- const struct vimc_pix_map *vpix = vimc_pix_map_by_index(code->index);
-
- /* We don't support bayer format */
- if (!vpix || vpix->bayer)
- return -EINVAL;
-
- code->code = vpix->code;
-
- return 0;
-}
-
-static int vimc_sca_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
-{
- const struct vimc_pix_map *vpix;
-
- if (fse->index)
- return -EINVAL;
-
- /* Only accept code in the pix map table in non bayer format */
- vpix = vimc_pix_map_by_code(fse->code);
- if (!vpix || vpix->bayer)
- return -EINVAL;
-
- fse->min_width = VIMC_FRAME_MIN_WIDTH;
- fse->min_height = VIMC_FRAME_MIN_HEIGHT;
-
- if (VIMC_IS_SINK(fse->pad)) {
- fse->max_width = VIMC_FRAME_MAX_WIDTH;
- fse->max_height = VIMC_FRAME_MAX_HEIGHT;
- } else {
- fse->max_width = VIMC_FRAME_MAX_WIDTH * MAX_ZOOM;
- fse->max_height = VIMC_FRAME_MAX_HEIGHT * MAX_ZOOM;
- }
-
- return 0;
-}
-
-static int vimc_sca_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *format)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
- struct v4l2_rect *crop_rect;
-
- /* Get the current sink format */
- if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
- crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
- } else {
- format->format = vsca->sink_fmt;
- crop_rect = &vsca->crop_rect;
- }
-
- /* Scale the frame size for the source pad */
- if (VIMC_IS_SRC(format->pad)) {
- format->format.width = crop_rect->width * sca_mult;
- format->format.height = crop_rect->height * sca_mult;
- }
-
- return 0;
-}
-
-static void vimc_sca_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
-{
- const struct vimc_pix_map *vpix;
-
- /* Only accept code in the pix map table in non bayer format */
- vpix = vimc_pix_map_by_code(fmt->code);
- if (!vpix || vpix->bayer)
- fmt->code = sink_fmt_default.code;
-
- fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
- VIMC_FRAME_MAX_WIDTH) & ~1;
- fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
- VIMC_FRAME_MAX_HEIGHT) & ~1;
-
- if (fmt->field == V4L2_FIELD_ANY)
- fmt->field = sink_fmt_default.field;
-
- vimc_colorimetry_clamp(fmt);
-}
-
-static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *sink_fmt;
- struct v4l2_rect *crop_rect;
-
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- /* Do not change the format while stream is on */
- if (vsca->src_frame)
- return -EBUSY;
-
- sink_fmt = &vsca->sink_fmt;
- crop_rect = &vsca->crop_rect;
- } else {
- sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
- crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
- }
-
- /*
- * Do not change the format of the source pad,
- * it is propagated from the sink
- */
- if (VIMC_IS_SRC(fmt->pad)) {
- fmt->format = *sink_fmt;
- fmt->format.width = crop_rect->width * sca_mult;
- fmt->format.height = crop_rect->height * sca_mult;
- } else {
- /* Set the new format in the sink pad */
- vimc_sca_adjust_sink_fmt(&fmt->format);
-
- dev_dbg(vsca->ved.dev, "%s: sink format update: "
- "old:%dx%d (0x%x, %d, %d, %d, %d) "
- "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsca->sd.name,
- /* old */
- sink_fmt->width, sink_fmt->height, sink_fmt->code,
- sink_fmt->colorspace, sink_fmt->quantization,
- sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
- /* new */
- fmt->format.width, fmt->format.height, fmt->format.code,
- fmt->format.colorspace, fmt->format.quantization,
- fmt->format.xfer_func, fmt->format.ycbcr_enc);
-
- *sink_fmt = fmt->format;
-
- /* Do the crop, but respect the current bounds */
- vimc_sca_adjust_sink_crop(crop_rect, sink_fmt);
- }
-
- return 0;
-}
-
-static int vimc_sca_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_selection *sel)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *sink_fmt;
- struct v4l2_rect *crop_rect;
-
- if (VIMC_IS_SRC(sel->pad))
- return -EINVAL;
-
- if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- sink_fmt = &vsca->sink_fmt;
- crop_rect = &vsca->crop_rect;
- } else {
- sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
- crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
- }
-
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP:
- sel->r = *crop_rect;
- break;
- case V4L2_SEL_TGT_CROP_BOUNDS:
- sel->r = vimc_sca_get_crop_bound_sink(sink_fmt);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vimc_sca_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_selection *sel)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *sink_fmt;
- struct v4l2_rect *crop_rect;
-
- if (VIMC_IS_SRC(sel->pad))
- return -EINVAL;
-
- if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- /* Do not change the format while stream is on */
- if (vsca->src_frame)
- return -EBUSY;
-
- crop_rect = &vsca->crop_rect;
- sink_fmt = &vsca->sink_fmt;
- } else {
- crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
- sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
- }
-
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP:
- /* Do the crop, but respect the current bounds */
- vimc_sca_adjust_sink_crop(&sel->r, sink_fmt);
- *crop_rect = sel->r;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_pad_ops vimc_sca_pad_ops = {
- .init_cfg = vimc_sca_init_cfg,
- .enum_mbus_code = vimc_sca_enum_mbus_code,
- .enum_frame_size = vimc_sca_enum_frame_size,
- .get_fmt = vimc_sca_get_fmt,
- .set_fmt = vimc_sca_set_fmt,
- .get_selection = vimc_sca_get_selection,
- .set_selection = vimc_sca_set_selection,
-};
-
-static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
-
- if (enable) {
- const struct vimc_pix_map *vpix;
- unsigned int frame_size;
-
- if (vsca->src_frame)
- return 0;
-
- /* Save the bytes per pixel of the sink */
- vpix = vimc_pix_map_by_code(vsca->sink_fmt.code);
- vsca->bpp = vpix->bpp;
-
- /* Calculate the width in bytes of the src frame */
- vsca->src_line_size = vsca->crop_rect.width *
- sca_mult * vsca->bpp;
-
- /* Calculate the frame size of the source pad */
- frame_size = vsca->src_line_size * vsca->crop_rect.height *
- sca_mult;
-
- /* Allocate the frame buffer. Use vmalloc to be able to
- * allocate a large amount of memory
- */
- vsca->src_frame = vmalloc(frame_size);
- if (!vsca->src_frame)
- return -ENOMEM;
-
- } else {
- if (!vsca->src_frame)
- return 0;
-
- vfree(vsca->src_frame);
- vsca->src_frame = NULL;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_video_ops vimc_sca_video_ops = {
- .s_stream = vimc_sca_s_stream,
-};
-
-static const struct v4l2_subdev_ops vimc_sca_ops = {
- .pad = &vimc_sca_pad_ops,
- .video = &vimc_sca_video_ops,
-};
-
-static void vimc_sca_fill_pix(u8 *const ptr,
- const u8 *const pixel,
- const unsigned int bpp)
-{
- unsigned int i;
-
- /* copy the pixel to the pointer */
- for (i = 0; i < bpp; i++)
- ptr[i] = pixel[i];
-}
-
-static void vimc_sca_scale_pix(const struct vimc_sca_device *const vsca,
- unsigned int lin, unsigned int col,
- const u8 *const sink_frame)
-{
- const struct v4l2_rect crop_rect = vsca->crop_rect;
- unsigned int i, j, index;
- const u8 *pixel;
-
- /* Point to the pixel value in position (lin, col) in the sink frame */
- index = VIMC_FRAME_INDEX(lin, col,
- vsca->sink_fmt.width,
- vsca->bpp);
- pixel = &sink_frame[index];
-
- dev_dbg(vsca->ved.dev,
- "sca: %s: --- scale_pix sink pos %dx%d, index %d ---\n",
- vsca->sd.name, lin, col, index);
-
- /* point to the place we are going to put the first pixel
- * in the scaled src frame
- */
- lin -= crop_rect.top;
- col -= crop_rect.left;
- index = VIMC_FRAME_INDEX(lin * sca_mult, col * sca_mult,
- crop_rect.width * sca_mult, vsca->bpp);
-
- dev_dbg(vsca->ved.dev, "sca: %s: scale_pix src pos %dx%d, index %d\n",
- vsca->sd.name, lin * sca_mult, col * sca_mult, index);
-
- /* Repeat this pixel mult times */
- for (i = 0; i < sca_mult; i++) {
- /* Iterate through each beginning of a
- * pixel repetition in a line
- */
- for (j = 0; j < sca_mult * vsca->bpp; j += vsca->bpp) {
- dev_dbg(vsca->ved.dev,
- "sca: %s: sca: scale_pix src pos %d\n",
- vsca->sd.name, index + j);
-
- /* copy the pixel to the position index + j */
- vimc_sca_fill_pix(&vsca->src_frame[index + j],
- pixel, vsca->bpp);
- }
-
- /* move the index to the next line */
- index += vsca->src_line_size;
- }
-}
-
-static void vimc_sca_fill_src_frame(const struct vimc_sca_device *const vsca,
- const u8 *const sink_frame)
-{
- const struct v4l2_rect r = vsca->crop_rect;
- unsigned int i, j;
-
- /* Scale each pixel from the original sink frame */
- /* TODO: implement scale down, only scale up is supported for now */
- for (i = r.top; i < r.top + r.height; i++)
- for (j = r.left; j < r.left + r.width; j++)
- vimc_sca_scale_pix(vsca, i, j, sink_frame);
-}
-
-static void *vimc_sca_process_frame(struct vimc_ent_device *ved,
- const void *sink_frame)
-{
- struct vimc_sca_device *vsca = container_of(ved, struct vimc_sca_device,
- ved);
-
- /* If the stream in this node is not active, just return */
- if (!vsca->src_frame)
- return ERR_PTR(-EINVAL);
-
- vimc_sca_fill_src_frame(vsca, sink_frame);
-
- return vsca->src_frame;
-};
-
-void vimc_sca_release(struct vimc_ent_device *ved)
-{
- struct vimc_sca_device *vsca =
- container_of(ved, struct vimc_sca_device, ved);
-
- media_entity_cleanup(vsca->ved.ent);
- kfree(vsca);
-}
-
-struct vimc_ent_device *vimc_sca_add(struct vimc_device *vimc,
- const char *vcfg_name)
-{
- struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
- struct vimc_sca_device *vsca;
- int ret;
-
- /* Allocate the vsca struct */
- vsca = kzalloc(sizeof(*vsca), GFP_KERNEL);
- if (!vsca)
- return NULL;
-
- /* Initialize ved and sd */
- vsca->pads[0].flags = MEDIA_PAD_FL_SINK;
- vsca->pads[1].flags = MEDIA_PAD_FL_SOURCE;
-
- ret = vimc_ent_sd_register(&vsca->ved, &vsca->sd, v4l2_dev,
- vcfg_name,
- MEDIA_ENT_F_PROC_VIDEO_SCALER, 2,
- vsca->pads, &vimc_sca_ops);
- if (ret) {
- kfree(vsca);
- return NULL;
- }
-
- vsca->ved.process_frame = vimc_sca_process_frame;
- vsca->ved.dev = vimc->mdev.dev;
-
- /* Initialize the frame format */
- vsca->sink_fmt = sink_fmt_default;
-
- /* Initialize the crop selection */
- vsca->crop_rect = crop_rect_default;
-
- return &vsca->ved;
-}
diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c
deleted file mode 100644
index 92daee58209e..000000000000
--- a/drivers/media/platform/vimc/vimc-sensor.c
+++ /dev/null
@@ -1,376 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-sensor.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/v4l2-mediabus.h>
-#include <linux/vmalloc.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-subdev.h>
-#include <media/tpg/v4l2-tpg.h>
-
-#include "vimc-common.h"
-
-struct vimc_sen_device {
- struct vimc_ent_device ved;
- struct v4l2_subdev sd;
- struct tpg_data tpg;
- u8 *frame;
- /* The active format */
- struct v4l2_mbus_framefmt mbus_format;
- struct v4l2_ctrl_handler hdl;
- struct media_pad pad;
-};
-
-static const struct v4l2_mbus_framefmt fmt_default = {
- .width = 640,
- .height = 480,
- .code = MEDIA_BUS_FMT_RGB888_1X24,
- .field = V4L2_FIELD_NONE,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
-};
-
-static int vimc_sen_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg)
-{
- unsigned int i;
-
- for (i = 0; i < sd->entity.num_pads; i++) {
- struct v4l2_mbus_framefmt *mf;
-
- mf = v4l2_subdev_get_try_format(sd, cfg, i);
- *mf = fmt_default;
- }
-
- return 0;
-}
-
-static int vimc_sen_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- const struct vimc_pix_map *vpix = vimc_pix_map_by_index(code->index);
-
- if (!vpix)
- return -EINVAL;
-
- code->code = vpix->code;
-
- return 0;
-}
-
-static int vimc_sen_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
-{
- const struct vimc_pix_map *vpix;
-
- if (fse->index)
- return -EINVAL;
-
- /* Only accept code in the pix map table */
- vpix = vimc_pix_map_by_code(fse->code);
- if (!vpix)
- return -EINVAL;
-
- fse->min_width = VIMC_FRAME_MIN_WIDTH;
- fse->max_width = VIMC_FRAME_MAX_WIDTH;
- fse->min_height = VIMC_FRAME_MIN_HEIGHT;
- fse->max_height = VIMC_FRAME_MAX_HEIGHT;
-
- return 0;
-}
-
-static int vimc_sen_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_sen_device *vsen =
- container_of(sd, struct vimc_sen_device, sd);
-
- fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ?
- *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) :
- vsen->mbus_format;
-
- return 0;
-}
-
-static void vimc_sen_tpg_s_format(struct vimc_sen_device *vsen)
-{
- const struct vimc_pix_map *vpix =
- vimc_pix_map_by_code(vsen->mbus_format.code);
-
- tpg_reset_source(&vsen->tpg, vsen->mbus_format.width,
- vsen->mbus_format.height, vsen->mbus_format.field);
- tpg_s_bytesperline(&vsen->tpg, 0, vsen->mbus_format.width * vpix->bpp);
- tpg_s_buf_height(&vsen->tpg, vsen->mbus_format.height);
- tpg_s_fourcc(&vsen->tpg, vpix->pixelformat);
- /* TODO: add support for V4L2_FIELD_ALTERNATE */
- tpg_s_field(&vsen->tpg, vsen->mbus_format.field, false);
- tpg_s_colorspace(&vsen->tpg, vsen->mbus_format.colorspace);
- tpg_s_ycbcr_enc(&vsen->tpg, vsen->mbus_format.ycbcr_enc);
- tpg_s_quantization(&vsen->tpg, vsen->mbus_format.quantization);
- tpg_s_xfer_func(&vsen->tpg, vsen->mbus_format.xfer_func);
-}
-
-static void vimc_sen_adjust_fmt(struct v4l2_mbus_framefmt *fmt)
-{
- const struct vimc_pix_map *vpix;
-
- /* Only accept code in the pix map table */
- vpix = vimc_pix_map_by_code(fmt->code);
- if (!vpix)
- fmt->code = fmt_default.code;
-
- fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
- VIMC_FRAME_MAX_WIDTH) & ~1;
- fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
- VIMC_FRAME_MAX_HEIGHT) & ~1;
-
- /* TODO: add support for V4L2_FIELD_ALTERNATE */
- if (fmt->field == V4L2_FIELD_ANY || fmt->field == V4L2_FIELD_ALTERNATE)
- fmt->field = fmt_default.field;
-
- vimc_colorimetry_clamp(fmt);
-}
-
-static int vimc_sen_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_sen_device *vsen = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *mf;
-
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- /* Do not change the format while stream is on */
- if (vsen->frame)
- return -EBUSY;
-
- mf = &vsen->mbus_format;
- } else {
- mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
- }
-
- /* Set the new format */
- vimc_sen_adjust_fmt(&fmt->format);
-
- dev_dbg(vsen->ved.dev, "%s: format update: "
- "old:%dx%d (0x%x, %d, %d, %d, %d) "
- "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsen->sd.name,
- /* old */
- mf->width, mf->height, mf->code,
- mf->colorspace, mf->quantization,
- mf->xfer_func, mf->ycbcr_enc,
- /* new */
- fmt->format.width, fmt->format.height, fmt->format.code,
- fmt->format.colorspace, fmt->format.quantization,
- fmt->format.xfer_func, fmt->format.ycbcr_enc);
-
- *mf = fmt->format;
-
- return 0;
-}
-
-static const struct v4l2_subdev_pad_ops vimc_sen_pad_ops = {
- .init_cfg = vimc_sen_init_cfg,
- .enum_mbus_code = vimc_sen_enum_mbus_code,
- .enum_frame_size = vimc_sen_enum_frame_size,
- .get_fmt = vimc_sen_get_fmt,
- .set_fmt = vimc_sen_set_fmt,
-};
-
-static void *vimc_sen_process_frame(struct vimc_ent_device *ved,
- const void *sink_frame)
-{
- struct vimc_sen_device *vsen = container_of(ved, struct vimc_sen_device,
- ved);
-
- tpg_fill_plane_buffer(&vsen->tpg, 0, 0, vsen->frame);
- return vsen->frame;
-}
-
-static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct vimc_sen_device *vsen =
- container_of(sd, struct vimc_sen_device, sd);
-
- if (enable) {
- const struct vimc_pix_map *vpix;
- unsigned int frame_size;
-
- /* Calculate the frame size */
- vpix = vimc_pix_map_by_code(vsen->mbus_format.code);
- frame_size = vsen->mbus_format.width * vpix->bpp *
- vsen->mbus_format.height;
-
- /*
- * Allocate the frame buffer. Use vmalloc to be able to
- * allocate a large amount of memory
- */
- vsen->frame = vmalloc(frame_size);
- if (!vsen->frame)
- return -ENOMEM;
-
- /* configure the test pattern generator */
- vimc_sen_tpg_s_format(vsen);
-
- } else {
-
- vfree(vsen->frame);
- vsen->frame = NULL;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_core_ops vimc_sen_core_ops = {
- .log_status = v4l2_ctrl_subdev_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
-static const struct v4l2_subdev_video_ops vimc_sen_video_ops = {
- .s_stream = vimc_sen_s_stream,
-};
-
-static const struct v4l2_subdev_ops vimc_sen_ops = {
- .core = &vimc_sen_core_ops,
- .pad = &vimc_sen_pad_ops,
- .video = &vimc_sen_video_ops,
-};
-
-static int vimc_sen_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vimc_sen_device *vsen =
- container_of(ctrl->handler, struct vimc_sen_device, hdl);
-
- switch (ctrl->id) {
- case VIMC_CID_TEST_PATTERN:
- tpg_s_pattern(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_HFLIP:
- tpg_s_hflip(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_VFLIP:
- tpg_s_vflip(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_BRIGHTNESS:
- tpg_s_brightness(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_CONTRAST:
- tpg_s_contrast(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_HUE:
- tpg_s_hue(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_SATURATION:
- tpg_s_saturation(&vsen->tpg, ctrl->val);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vimc_sen_ctrl_ops = {
- .s_ctrl = vimc_sen_s_ctrl,
-};
-
-void vimc_sen_release(struct vimc_ent_device *ved)
-{
- struct vimc_sen_device *vsen =
- container_of(ved, struct vimc_sen_device, ved);
-
- v4l2_ctrl_handler_free(&vsen->hdl);
- tpg_free(&vsen->tpg);
- media_entity_cleanup(vsen->ved.ent);
- kfree(vsen);
-}
-
-/* Image Processing Controls */
-static const struct v4l2_ctrl_config vimc_sen_ctrl_class = {
- .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
- .id = VIMC_CID_VIMC_CLASS,
- .name = "VIMC Controls",
- .type = V4L2_CTRL_TYPE_CTRL_CLASS,
-};
-
-static const struct v4l2_ctrl_config vimc_sen_ctrl_test_pattern = {
- .ops = &vimc_sen_ctrl_ops,
- .id = VIMC_CID_TEST_PATTERN,
- .name = "Test Pattern",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = TPG_PAT_NOISE,
- .qmenu = tpg_pattern_strings,
-};
-
-struct vimc_ent_device *vimc_sen_add(struct vimc_device *vimc,
- const char *vcfg_name)
-{
- struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
- struct vimc_sen_device *vsen;
- int ret;
-
- /* Allocate the vsen struct */
- vsen = kzalloc(sizeof(*vsen), GFP_KERNEL);
- if (!vsen)
- return NULL;
-
- v4l2_ctrl_handler_init(&vsen->hdl, 4);
-
- v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_class, NULL);
- v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_test_pattern, NULL);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_VFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_HFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_CONTRAST, 0, 255, 1, 128);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_HUE, -128, 127, 1, 0);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_SATURATION, 0, 255, 1, 128);
- vsen->sd.ctrl_handler = &vsen->hdl;
- if (vsen->hdl.error) {
- ret = vsen->hdl.error;
- goto err_free_vsen;
- }
-
- /* Initialize the test pattern generator */
- tpg_init(&vsen->tpg, vsen->mbus_format.width,
- vsen->mbus_format.height);
- ret = tpg_alloc(&vsen->tpg, VIMC_FRAME_MAX_WIDTH);
- if (ret)
- goto err_free_hdl;
-
- /* Initialize ved and sd */
- vsen->pad.flags = MEDIA_PAD_FL_SOURCE;
- ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev,
- vcfg_name,
- MEDIA_ENT_F_CAM_SENSOR, 1, &vsen->pad,
- &vimc_sen_ops);
- if (ret)
- goto err_free_tpg;
-
- vsen->ved.process_frame = vimc_sen_process_frame;
- vsen->ved.dev = vimc->mdev.dev;
-
- /* Initialize the frame format */
- vsen->mbus_format = fmt_default;
-
- return &vsen->ved;
-
-err_free_tpg:
- tpg_free(&vsen->tpg);
-err_free_hdl:
- v4l2_ctrl_handler_free(&vsen->hdl);
-err_free_vsen:
- kfree(vsen);
-
- return NULL;
-}
diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c
deleted file mode 100644
index 65feb3c596db..000000000000
--- a/drivers/media/platform/vimc/vimc-streamer.c
+++ /dev/null
@@ -1,238 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * vimc-streamer.c Virtual Media Controller Driver
- *
- * Copyright (C) 2018 Lucas A. M. Magalhães <lucmaga@gmail.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/freezer.h>
-#include <linux/kthread.h>
-
-#include "vimc-streamer.h"
-
-/**
- * vimc_get_source_entity - get the entity connected with the first sink pad
- *
- * @ent: reference media_entity
- *
- * Helper function that returns the media entity containing the source pad
- * linked with the first sink pad from the given media entity pad list.
- *
- * Return: The source pad or NULL, if it wasn't found.
- */
-static struct media_entity *vimc_get_source_entity(struct media_entity *ent)
-{
- struct media_pad *pad;
- int i;
-
- for (i = 0; i < ent->num_pads; i++) {
- if (ent->pads[i].flags & MEDIA_PAD_FL_SOURCE)
- continue;
- pad = media_entity_remote_pad(&ent->pads[i]);
- return pad ? pad->entity : NULL;
- }
- return NULL;
-}
-
-/**
- * vimc_streamer_pipeline_terminate - Disable stream in all ved in stream
- *
- * @stream: the pointer to the stream structure with the pipeline to be
- * disabled.
- *
- * Calls s_stream to disable the stream in each entity of the pipeline
- *
- */
-static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
-{
- struct vimc_ent_device *ved;
- struct v4l2_subdev *sd;
-
- while (stream->pipe_size) {
- stream->pipe_size--;
- ved = stream->ved_pipeline[stream->pipe_size];
- stream->ved_pipeline[stream->pipe_size] = NULL;
-
- if (!is_media_entity_v4l2_subdev(ved->ent))
- continue;
-
- sd = media_entity_to_v4l2_subdev(ved->ent);
- v4l2_subdev_call(sd, video, s_stream, 0);
- }
-}
-
-/**
- * vimc_streamer_pipeline_init - Initializes the stream structure
- *
- * @stream: the pointer to the stream structure to be initialized
- * @ved: the pointer to the vimc entity initializing the stream
- *
- * Initializes the stream structure. Walks through the entity graph to
- * construct the pipeline used later on the streamer thread.
- * Calls vimc_streamer_s_stream() to enable stream in all entities of
- * the pipeline.
- *
- * Return: 0 if success, error code otherwise.
- */
-static int vimc_streamer_pipeline_init(struct vimc_stream *stream,
- struct vimc_ent_device *ved)
-{
- struct media_entity *entity;
- struct video_device *vdev;
- struct v4l2_subdev *sd;
- int ret = 0;
-
- stream->pipe_size = 0;
- while (stream->pipe_size < VIMC_STREAMER_PIPELINE_MAX_SIZE) {
- if (!ved) {
- vimc_streamer_pipeline_terminate(stream);
- return -EINVAL;
- }
- stream->ved_pipeline[stream->pipe_size++] = ved;
-
- if (is_media_entity_v4l2_subdev(ved->ent)) {
- sd = media_entity_to_v4l2_subdev(ved->ent);
- ret = v4l2_subdev_call(sd, video, s_stream, 1);
- if (ret && ret != -ENOIOCTLCMD) {
- dev_err(ved->dev, "subdev_call error %s\n",
- ved->ent->name);
- vimc_streamer_pipeline_terminate(stream);
- return ret;
- }
- }
-
- entity = vimc_get_source_entity(ved->ent);
- /* Check if the end of the pipeline was reached */
- if (!entity) {
- /* the first entity of the pipe should be source only */
- if (!vimc_is_source(ved->ent)) {
- dev_err(ved->dev,
- "first entity in the pipe '%s' is not a source\n",
- ved->ent->name);
- vimc_streamer_pipeline_terminate(stream);
- return -EPIPE;
- }
- return 0;
- }
-
- /* Get the next device in the pipeline */
- if (is_media_entity_v4l2_subdev(entity)) {
- sd = media_entity_to_v4l2_subdev(entity);
- ved = v4l2_get_subdevdata(sd);
- } else {
- vdev = container_of(entity,
- struct video_device,
- entity);
- ved = video_get_drvdata(vdev);
- }
- }
-
- vimc_streamer_pipeline_terminate(stream);
- return -EINVAL;
-}
-
-/**
- * vimc_streamer_thread - Process frames through the pipeline
- *
- * @data: vimc_stream struct of the current stream
- *
- * From the source to the sink, gets a frame from each subdevice and send to
- * the next one of the pipeline at a fixed framerate.
- *
- * Return:
- * Always zero (created as ``int`` instead of ``void`` to comply with
- * kthread API).
- */
-static int vimc_streamer_thread(void *data)
-{
- struct vimc_stream *stream = data;
- u8 *frame = NULL;
- int i;
-
- set_freezable();
-
- for (;;) {
- try_to_freeze();
- if (kthread_should_stop())
- break;
-
- for (i = stream->pipe_size - 1; i >= 0; i--) {
- frame = stream->ved_pipeline[i]->process_frame(
- stream->ved_pipeline[i], frame);
- if (!frame || IS_ERR(frame))
- break;
- }
- //wait for 60hz
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 60);
- }
-
- return 0;
-}
-
-/**
- * vimc_streamer_s_stream - Start/stop the streaming on the media pipeline
- *
- * @stream: the pointer to the stream structure of the current stream
- * @ved: pointer to the vimc entity of the entity of the stream
- * @enable: flag to determine if stream should start/stop
- *
- * When starting, check if there is no ``stream->kthread`` allocated. This
- * should indicate that a stream is already running. Then, it initializes the
- * pipeline, creates and runs a kthread to consume buffers through the pipeline.
- * When stopping, analogously check if there is a stream running, stop the
- * thread and terminates the pipeline.
- *
- * Return: 0 if success, error code otherwise.
- */
-int vimc_streamer_s_stream(struct vimc_stream *stream,
- struct vimc_ent_device *ved,
- int enable)
-{
- int ret;
-
- if (!stream || !ved)
- return -EINVAL;
-
- if (enable) {
- if (stream->kthread)
- return 0;
-
- ret = vimc_streamer_pipeline_init(stream, ved);
- if (ret)
- return ret;
-
- stream->kthread = kthread_run(vimc_streamer_thread, stream,
- "vimc-streamer thread");
-
- if (IS_ERR(stream->kthread)) {
- ret = PTR_ERR(stream->kthread);
- dev_err(ved->dev, "kthread_run failed with %d\n", ret);
- vimc_streamer_pipeline_terminate(stream);
- stream->kthread = NULL;
- return ret;
- }
-
- } else {
- if (!stream->kthread)
- return 0;
-
- ret = kthread_stop(stream->kthread);
- /*
- * kthread_stop returns -EINTR in cases when streamon was
- * immediately followed by streamoff, and the thread didn't had
- * a chance to run. Ignore errors to stop the stream in the
- * pipeline.
- */
- if (ret)
- dev_dbg(ved->dev, "kthread_stop returned '%d'\n", ret);
-
- stream->kthread = NULL;
-
- vimc_streamer_pipeline_terminate(stream);
- }
-
- return 0;
-}
diff --git a/drivers/media/platform/vimc/vimc-streamer.h b/drivers/media/platform/vimc/vimc-streamer.h
deleted file mode 100644
index fe3c51f15fad..000000000000
--- a/drivers/media/platform/vimc/vimc-streamer.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * vimc-streamer.h Virtual Media Controller Driver
- *
- * Copyright (C) 2018 Lucas A. M. Magalhães <lucmaga@gmail.com>
- *
- */
-
-#ifndef _VIMC_STREAMER_H_
-#define _VIMC_STREAMER_H_
-
-#include <media/media-device.h>
-
-#include "vimc-common.h"
-
-#define VIMC_STREAMER_PIPELINE_MAX_SIZE 16
-
-/**
- * struct vimc_stream - struct that represents a stream in the pipeline
- *
- * @pipe: the media pipeline object associated with this stream
- * @ved_pipeline: array containing all the entities participating in the
- * stream. The order is from a video device (usually a capture device) where
- * stream_on was called, to the entity generating the first base image to be
- * processed in the pipeline.
- * @pipe_size: size of @ved_pipeline
- * @kthread: thread that generates the frames of the stream.
- *
- * When the user call stream_on in a video device, struct vimc_stream is
- * used to keep track of all entities and subdevices that generates and
- * process frames for the stream.
- */
-struct vimc_stream {
- struct media_pipeline pipe;
- struct vimc_ent_device *ved_pipeline[VIMC_STREAMER_PIPELINE_MAX_SIZE];
- unsigned int pipe_size;
- struct task_struct *kthread;
-};
-
-int vimc_streamer_s_stream(struct vimc_stream *stream,
- struct vimc_ent_device *ved,
- int enable);
-
-#endif //_VIMC_STREAMER_H_