[GIT PULL] Linux Media vimc update for 6.20-rc1

From: Shuah Khan

Date: Thu Jan 08 2026 - 16:42:31 EST


Hi Mauro,

Please pull the vimc next update for Linux 6.20-rc1.

Adds
RGB/YUV input entity implementation
support for V4L2_FIELD_ALTERNATE in vimc-sensor
support for multiple RGB formats in vimc-debayer
support custom bytesperline values in vimc-capture
document RGB/YUV input entity

diff is attached.

thanks,
-- Shuah

----------------------------------------------------------------

The following changes since commit 8f0b4cce4481fb22653697cced8d0d04027cb1e8:

Linux 6.19-rc1 (2025-12-14 16:05:07 +1200)

are available in the Git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux tags/linux-vimc-6.20-rc1

for you to fetch changes up to c3a017646b770b76f0f08c96aa74fbc4404ef674:

docs: media: vimc: document RGB/YUV input entity (2025-12-15 12:43:25 -0700)

----------------------------------------------------------------
linux-vimc-6.20-rc1

Adds
RGB/YUV input entity implementation
support for V4L2_FIELD_ALTERNATE in vimc-sensor
support for multiple RGB formats in vimc-debayer
support custom bytesperline values in vimc-capture
document RGB/YUV input entity

----------------------------------------------------------------
Pavan Bobba (5):
media: vimc: add RGB/YUV input entity implementation
media: vimc: add support for V4L2_FIELD_ALTERNATE in vimc-sensor
media: vimc: debayer: add support for multiple RGB formats
media: vimc: capture: support custom bytesperline values
docs: media: vimc: document RGB/YUV input entity

Documentation/admin-guide/media/vimc.rst | 39 +++--
drivers/media/test-drivers/vimc/Makefile | 3 +-
drivers/media/test-drivers/vimc/vimc-capture.c | 15 +-
drivers/media/test-drivers/vimc/vimc-common.h | 1 +
drivers/media/test-drivers/vimc/vimc-core.c | 3 +-
drivers/media/test-drivers/vimc/vimc-debayer.c | 113 ++++++++++---
drivers/media/test-drivers/vimc/vimc-input.c | 210 +++++++++++++++++++++++++
drivers/media/test-drivers/vimc/vimc-sensor.c | 9 +-
8 files changed, 352 insertions(+), 41 deletions(-)
create mode 100644 drivers/media/test-drivers/vimc/vimc-input.c

----------------------------------------------------------------diff --git a/Documentation/admin-guide/media/vimc.rst b/Documentation/admin-guide/media/vimc.rst
index 29d843a8ddb1..a1b7de769e23 100644
--- a/Documentation/admin-guide/media/vimc.rst
+++ b/Documentation/admin-guide/media/vimc.rst
@@ -4,7 +4,7 @@ The Virtual Media Controller Driver (vimc)
==========================================

The vimc driver emulates complex video hardware using the V4L2 API and the Media
-API. It has a capture device and three subdevices: sensor, debayer and scaler.
+API. It has a capture device and three subdevices: sensor, debayer, scaler and RGB/YUV input entity.

Topology
--------
@@ -29,17 +29,28 @@ configuration on each linked subdevice to stream frames through the pipeline.
If the configuration doesn't match, the stream will fail. The ``v4l-utils``
package is a bundle of user-space applications, that comes with ``media-ctl`` and
``v4l2-ctl`` that can be used to configure the vimc configuration. This sequence
-of commands fits for the default topology:
+-of commands fits for the default topology:

.. code-block:: bash

- media-ctl -d platform:vimc -V '"Sensor A":0[fmt:SBGGR8_1X8/640x480]'
- media-ctl -d platform:vimc -V '"Debayer A":0[fmt:SBGGR8_1X8/640x480]'
- media-ctl -d platform:vimc -V '"Scaler":0[fmt:RGB888_1X24/640x480]'
- media-ctl -d platform:vimc -V '"Scaler":0[crop:(100,50)/400x150]'
- media-ctl -d platform:vimc -V '"Scaler":1[fmt:RGB888_1X24/300x700]'
- v4l2-ctl -z platform:vimc -d "RGB/YUV Capture" -v width=300,height=700
- v4l2-ctl -z platform:vimc -d "Raw Capture 0" -v pixelformat=BA81
+ media-ctl -d platform:vimc.0 -V '"Sensor A":0[fmt:SBGGR8_1X8/640x480]'
+ media-ctl -d platform:vimc.0 -V '"Debayer A":0[fmt:SBGGR8_1X8/640x480]'
+ media-ctl -d platform:vimc.0 -V '"Scaler":0[fmt:RGB888_1X24/640x480]'
+ media-ctl -d platform:vimc.0 -V '"Scaler":0[crop:(100,50)/400x150]'
+ media-ctl -d platform:vimc.0 -V '"Scaler":1[fmt:RGB888_1X24/300x700]'
+ v4l2-ctl -z platform:vimc.0 -d "RGB/YUV Capture" -v width=300,height=700
+ v4l2-ctl -z platform:vimc.0 -d "Raw Capture 0" -v pixelformat=BA81
+
+The following commands switch the scaler input to the RGB/YUV entity and request
+ARGB output with a padded capture stride.
+
+.. code-block:: bash
+
+ media-ctl -d platform:vimc.0 -V '"RGB/YUV Input":0[fmt:RGB888_1X24/640x480]'
+ media-ctl -d platform:vimc.0 -V '"Scaler":0[fmt:RGB888_1X24/640x480]'
+ media-ctl -d platform:vimc.0 -V '"Scaler":1[fmt:ARGB8888_1X32/640x480]'
+ v4l2-ctl -z platform:vimc.0 -d "RGB/YUV Capture" \
+ -v pixelformat=RGB3,width=640,height=480,bytesperline=4096

Subdevices
----------
@@ -53,6 +64,16 @@ vimc-sensor:

* 1 Pad source

+vimc-input:
+ Simulates an RGB/YUV frame source for pipelines that start after a real
+ debayer stage. It exposes a single source pad that initially advertises
+ ``MEDIA_BUS_FMT_RGB888_1X24`` and accepts the usual width/height updates via
+ ``media-ctl``, which is useful for software-driven frame injection
+ experiments.
+ Exposes:
+
+ * 1 Pad source
+
vimc-lens:
Ancillary lens for a sensor. Supports auto focus control. Linked to
a vimc-sensor using an ancillary link. The lens supports FOCUS_ABSOLUTE
diff --git a/drivers/media/test-drivers/vimc/Makefile b/drivers/media/test-drivers/vimc/Makefile
index 9b9631562473..7e1fdb2f2a78 100644
--- a/drivers/media/test-drivers/vimc/Makefile
+++ b/drivers/media/test-drivers/vimc/Makefile
@@ -1,6 +1,7 @@
# 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 vimc-lens.o
+ vimc-debayer.o vimc-scaler.o vimc-sensor.o vimc-lens.o \
+ vimc-input.o

obj-$(CONFIG_VIDEO_VIMC) += vimc.o

diff --git a/drivers/media/test-drivers/vimc/vimc-capture.c b/drivers/media/test-drivers/vimc/vimc-capture.c
index 7f6124025fc9..7164ec51eb80 100644
--- a/drivers/media/test-drivers/vimc/vimc-capture.c
+++ b/drivers/media/test-drivers/vimc/vimc-capture.c
@@ -85,6 +85,7 @@ static int vimc_capture_try_fmt_vid_cap(struct file *file, void *priv,
{
struct v4l2_pix_format *format = &f->fmt.pix;
const struct vimc_pix_map *vpix;
+ u32 min_bpl, max_bpl;

format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH,
VIMC_FRAME_MAX_WIDTH) & ~1;
@@ -97,8 +98,18 @@ static int vimc_capture_try_fmt_vid_cap(struct file *file, void *priv,
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;
+
+ /* Calculate the minimum supported bytesperline value */
+ min_bpl = format->width * vpix->bpp;
+ /* Calculate the maximum supported bytesperline value */
+ max_bpl = VIMC_FRAME_MAX_WIDTH * vpix->bpp;
+
+ /* Clamp bytesperline to the valid range */
+ if (format->bytesperline > max_bpl)
+ format->bytesperline = max_bpl;
+ if (format->bytesperline < min_bpl)
+ format->bytesperline = min_bpl;
+
format->sizeimage = format->bytesperline * format->height;

if (format->field == V4L2_FIELD_ANY)
diff --git a/drivers/media/test-drivers/vimc/vimc-common.h b/drivers/media/test-drivers/vimc/vimc-common.h
index 7a45a2117748..6c94b1635fa8 100644
--- a/drivers/media/test-drivers/vimc/vimc-common.h
+++ b/drivers/media/test-drivers/vimc/vimc-common.h
@@ -172,6 +172,7 @@ extern const struct vimc_ent_type vimc_debayer_type;
extern const struct vimc_ent_type vimc_scaler_type;
extern const struct vimc_ent_type vimc_capture_type;
extern const struct vimc_ent_type vimc_lens_type;
+extern const struct vimc_ent_type vimc_input_type;

/**
* vimc_pix_map_by_index - get vimc_pix_map struct by its index
diff --git a/drivers/media/test-drivers/vimc/vimc-core.c b/drivers/media/test-drivers/vimc/vimc-core.c
index f632c77e52f5..2f6846facb23 100644
--- a/drivers/media/test-drivers/vimc/vimc-core.c
+++ b/drivers/media/test-drivers/vimc/vimc-core.c
@@ -107,9 +107,8 @@ static const struct vimc_ent_config ent_config[] = {
.type = &vimc_capture_type
},
[RGB_YUV_INPUT] = {
- /* TODO: change this to vimc-input when it is implemented */
.name = "RGB/YUV Input",
- .type = &vimc_sensor_type
+ .type = &vimc_input_type
},
[SCALER] = {
.name = "Scaler",
diff --git a/drivers/media/test-drivers/vimc/vimc-debayer.c b/drivers/media/test-drivers/vimc/vimc-debayer.c
index bbb7c7a86df0..0fa1cb8d3be1 100644
--- a/drivers/media/test-drivers/vimc/vimc-debayer.c
+++ b/drivers/media/test-drivers/vimc/vimc-debayer.c
@@ -15,9 +15,6 @@

#include "vimc-common.h"

-/* TODO: Add support for more output formats, we only support RGB888 for now. */
-#define VIMC_DEBAYER_SOURCE_MBUS_FMT MEDIA_BUS_FMT_RGB888_1X24
-
enum vimc_debayer_rgb_colors {
VIMC_DEBAYER_RED = 0,
VIMC_DEBAYER_GREEN = 1,
@@ -73,6 +70,7 @@ static const u32 vimc_debayer_src_mbus_codes[] = {
MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
MEDIA_BUS_FMT_RGB888_1X32_PADHI,
+ MEDIA_BUS_FMT_ARGB8888_1X32,
};

static const struct vimc_debayer_pix_map vimc_debayer_pix_map_list[] = {
@@ -170,7 +168,7 @@ static int vimc_debayer_init_state(struct v4l2_subdev *sd,

mf = v4l2_subdev_state_get_format(sd_state, 1);
*mf = sink_fmt_default;
- mf->code = VIMC_DEBAYER_SOURCE_MBUS_FMT;
+ mf->code = vimc_debayer_src_mbus_codes[0];

return 0;
}
@@ -239,6 +237,14 @@ static void vimc_debayer_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
vimc_colorimetry_clamp(fmt);
}

+static void vimc_debayer_set_rgb_mbus_fmt_default(struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ fmt->xfer_func = V4L2_XFER_FUNC_SRGB;
+ fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+}
+
static int vimc_debayer_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
@@ -250,12 +256,30 @@ static int vimc_debayer_set_fmt(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && vdebayer->src_frame)
return -EBUSY;

- /*
- * Do not change the format of the source pad, it is propagated from
- * the sink.
- */
- if (VIMC_IS_SRC(fmt->pad))
- return v4l2_subdev_get_fmt(sd, sd_state, fmt);
+ if (VIMC_IS_SRC(fmt->pad)) {
+ struct v4l2_mbus_framefmt *source_fmt;
+ struct v4l2_mbus_framefmt *sink_fmt;
+
+ /* Validate the requested source format */
+ if (!vimc_debayer_src_code_is_valid(fmt->format.code))
+ return -EINVAL;
+
+ /* Get current formats */
+ source_fmt = v4l2_subdev_state_get_format(sd_state, 1);
+ sink_fmt = v4l2_subdev_state_get_format(sd_state, 0);
+
+ /* Update source format with appropriate properties for RGB output */
+ source_fmt->code = fmt->format.code;
+ source_fmt->width = sink_fmt->width; /* Size should match */
+ source_fmt->height = sink_fmt->height; /* Size should match */
+ source_fmt->field = sink_fmt->field; /* Field handling should match */
+
+ /* Set appropriate colorimetry for RGB output */
+ vimc_debayer_set_rgb_mbus_fmt_default(source_fmt);
+
+ fmt->format = *source_fmt;
+ return 0;
+ }

/* Set the new format in the sink pad. */
vimc_debayer_adjust_sink_fmt(&fmt->format);
@@ -278,8 +302,25 @@ static int vimc_debayer_set_fmt(struct v4l2_subdev *sd,

/* Propagate the format to the source pad. */
format = v4l2_subdev_state_get_format(sd_state, 1);
- *format = fmt->format;
- format->code = VIMC_DEBAYER_SOURCE_MBUS_FMT;
+
+ /* Propagate size and field from sink, but maintain source code */
+ format->width = fmt->format.width;
+ format->height = fmt->format.height;
+ format->field = fmt->format.field;
+
+ /*
+ * Source code should always be valid (set during init or via set_fmt).
+ * If somehow it's not, this is a bug - log warning and fix it.
+ */
+ if (!vimc_debayer_src_code_is_valid(format->code)) {
+ dev_warn(vdebayer->ved.dev,
+ "%s: Invalid source code 0x%x, resetting to default\n",
+ vdebayer->sd.name, format->code);
+ format->code = vimc_debayer_src_mbus_codes[0];
+ }
+
+ /* Set appropriate colorimetry for RGB output */
+ vimc_debayer_set_rgb_mbus_fmt_default(format);

return 0;
}
@@ -297,19 +338,45 @@ static void vimc_debayer_process_rgb_frame(struct vimc_debayer_device *vdebayer,
unsigned int rgb[3])
{
const struct vimc_pix_map *vpix;
- unsigned int i, index;
+ unsigned int index;

vpix = vimc_pix_map_by_code(vdebayer->hw.src_code);
- index = VIMC_FRAME_INDEX(lin, col, vdebayer->hw.size.width, 3);
- for (i = 0; i < 3; i++) {
- switch (vpix->pixelformat) {
- case V4L2_PIX_FMT_RGB24:
- vdebayer->src_frame[index + i] = rgb[i];
- break;
- case V4L2_PIX_FMT_BGR24:
- vdebayer->src_frame[index + i] = rgb[2 - i];
- break;
- }
+ if (!vpix) {
+ dev_dbg(vdebayer->ved.dev, "Invalid source code: 0x%x\n",
+ vdebayer->hw.src_code);
+ return;
+ }
+
+ index = VIMC_FRAME_INDEX(lin, col, vdebayer->hw.size.width, vpix->bpp);
+
+ switch (vpix->pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ /* RGB24: R-G-B */
+ vdebayer->src_frame[index + 0] = rgb[0]; /* Red */
+ vdebayer->src_frame[index + 1] = rgb[1]; /* Green */
+ vdebayer->src_frame[index + 2] = rgb[2]; /* Blue */
+ break;
+
+ case V4L2_PIX_FMT_BGR24:
+ /* BGR24: B-G-R */
+ vdebayer->src_frame[index + 0] = rgb[2]; /* Blue */
+ vdebayer->src_frame[index + 1] = rgb[1]; /* Green */
+ vdebayer->src_frame[index + 2] = rgb[0]; /* Red */
+ break;
+
+ case V4L2_PIX_FMT_ARGB32:
+ /* ARGB32: A-R-G-B (set alpha to 255) */
+ vdebayer->src_frame[index + 0] = 255; /* Alpha */
+ vdebayer->src_frame[index + 1] = rgb[0]; /* Red */
+ vdebayer->src_frame[index + 2] = rgb[1]; /* Green */
+ vdebayer->src_frame[index + 3] = rgb[2]; /* Blue */
+ break;
+
+ default:
+ dev_dbg(vdebayer->ved.dev,
+ "Unsupported pixel format for debayer: 0x%x\n",
+ vpix->pixelformat);
+ break;
}
}

diff --git a/drivers/media/test-drivers/vimc/vimc-input.c b/drivers/media/test-drivers/vimc/vimc-input.c
new file mode 100644
index 000000000000..cedcc450d59e
--- /dev/null
+++ b/drivers/media/test-drivers/vimc/vimc-input.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * vimc-input.c Virtual Media Controller Driver
+ *
+ * Copyright (C) 2025 Virtual Input Entity Implementation
+ */
+
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-subdev.h>
+
+#include "vimc-common.h"
+
+struct vimc_input_device {
+ struct vimc_ent_device ved;
+ struct v4l2_subdev sd;
+ 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_SRGB,
+};
+
+static int vimc_input_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ struct v4l2_mbus_framefmt *mf;
+ unsigned int i;
+
+ for (i = 0; i < sd->entity.num_pads; i++) {
+ mf = v4l2_subdev_state_get_format(sd_state, i);
+ *mf = fmt_default;
+ }
+
+ return 0;
+}
+
+static int vimc_input_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_RGB888_1X24;
+
+ return 0;
+}
+
+static int vimc_input_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ 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_input_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct v4l2_mbus_framefmt *mf;
+
+ mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
+
+ fmt->format = *mf;
+
+ return 0;
+}
+
+static int vimc_input_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct v4l2_mbus_framefmt *mf;
+
+ mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
+
+ /* Set the new format */
+ *mf = fmt->format;
+
+ return 0;
+}
+
+static int vimc_input_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
+{
+ /* For input entity, we don't allocate frames since we expect
+ * external frame injection. Just mark that streaming is active.
+ *
+ * TODO: For future enhancement, consider implementing frame generation
+ * or userspace frame injection mechanism. This would require:
+ * - Frame buffer allocation (similar to vimc-sensor.c)
+ * - Interface for userspace to inject frames (e.g., via sysfs/debugfs)
+ * - Frame rate control for generated test patterns
+ * - Integration with VIMC's streaming infrastructure
+ * This would make the input entity suitable for more testing scenarios.
+ */
+ return 0;
+}
+
+static int vimc_input_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
+{
+ /* Streaming stopped - no cleanup needed for input entity */
+ return 0;
+}
+
+static const struct v4l2_subdev_pad_ops vimc_input_pad_ops = {
+ .enum_mbus_code = vimc_input_enum_mbus_code,
+ .enum_frame_size = vimc_input_enum_frame_size,
+ .get_fmt = vimc_input_get_fmt,
+ .set_fmt = vimc_input_set_fmt,
+ .enable_streams = vimc_input_enable_streams,
+ .disable_streams = vimc_input_disable_streams,
+};
+
+static const struct v4l2_subdev_ops vimc_input_ops = {
+ .pad = &vimc_input_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops vimc_input_internal_ops = {
+ .init_state = vimc_input_init_state,
+};
+
+static void vimc_input_release(struct vimc_ent_device *ved)
+{
+ struct vimc_input_device *vinput =
+ container_of(ved, struct vimc_input_device, ved);
+
+ v4l2_subdev_cleanup(&vinput->sd);
+ media_entity_cleanup(vinput->ved.ent);
+ kfree(vinput);
+}
+
+/*
+ * Input process frame function
+ * For an input entity, just return the received frame unchanged
+ */
+static void *vimc_input_process_frame(struct vimc_ent_device *ved,
+ const void *frame)
+{
+ /* For an input entity, just return the received frame unchanged.
+ *
+ * TODO: Future enhancement could implement:
+ * - Frame validation and format checking
+ * - Frame transformation or processing
+ * - Frame injection from userspace buffers
+ * - Frame rate limiting or buffering
+ * Currently, this is a simple pass-through for external frame sources.
+ */
+ return (void *)frame;
+}
+
+static struct vimc_ent_device *vimc_input_add(struct vimc_device *vimc,
+ const char *vcfg_name)
+{
+ struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
+ struct vimc_input_device *vinput;
+ int ret;
+
+ /* Allocate the vinput struct */
+ vinput = kzalloc(sizeof(*vinput), GFP_KERNEL);
+ if (!vinput)
+ return ERR_PTR(-ENOMEM);
+
+ /* Initialize the media pad */
+ vinput->pad.flags = MEDIA_PAD_FL_SOURCE;
+
+ ret = vimc_ent_sd_register(&vinput->ved, &vinput->sd, v4l2_dev,
+ vcfg_name,
+ MEDIA_ENT_F_IO_V4L, 1, &vinput->pad,
+ &vimc_input_internal_ops, &vimc_input_ops);
+ if (ret)
+ goto err_free_vinput;
+
+ vinput->ved.process_frame = vimc_input_process_frame;
+ vinput->ved.dev = vimc->mdev.dev;
+
+ return &vinput->ved;
+
+err_free_vinput:
+ kfree(vinput);
+
+ return ERR_PTR(ret);
+}
+
+const struct vimc_ent_type vimc_input_type = {
+ .add = vimc_input_add,
+ .release = vimc_input_release
+};
diff --git a/drivers/media/test-drivers/vimc/vimc-sensor.c b/drivers/media/test-drivers/vimc/vimc-sensor.c
index 027767777763..900c3f329f1c 100644
--- a/drivers/media/test-drivers/vimc/vimc-sensor.c
+++ b/drivers/media/test-drivers/vimc/vimc-sensor.c
@@ -105,8 +105,10 @@ static void vimc_sensor_tpg_s_format(struct vimc_sensor_device *vsensor,
tpg_s_bytesperline(&vsensor->tpg, 0, format->width * vpix->bpp);
tpg_s_buf_height(&vsensor->tpg, format->height);
tpg_s_fourcc(&vsensor->tpg, vpix->pixelformat);
- /* TODO: add support for V4L2_FIELD_ALTERNATE */
- tpg_s_field(&vsensor->tpg, format->field, false);
+ if (format->field == V4L2_FIELD_ALTERNATE)
+ tpg_s_field(&vsensor->tpg, V4L2_FIELD_TOP, true);
+ else
+ tpg_s_field(&vsensor->tpg, format->field, false);
tpg_s_colorspace(&vsensor->tpg, format->colorspace);
tpg_s_ycbcr_enc(&vsensor->tpg, format->ycbcr_enc);
tpg_s_quantization(&vsensor->tpg, format->quantization);
@@ -127,8 +129,7 @@ static void vimc_sensor_adjust_fmt(struct v4l2_mbus_framefmt *fmt)
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)
+ if (fmt->field == V4L2_FIELD_ANY)
fmt->field = fmt_default.field;

vimc_colorimetry_clamp(fmt);