mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [GIT PULL] Linux Media vimc update for 6.20-rc1
@ 2026-01-08 21:42 Shuah Khan
  2026-01-13  9:19 ` Hans Verkuil
  0 siblings, 1 reply; 3+ messages in thread
From: Shuah Khan @ 2026-01-08 21:42 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Kieran Bingham, Hans Verkuil, linux-kernel, linux-media,
	Pavan Bobba, Shuah Khan, shuah

[-- Attachment #1: Type: text/plain, Size: 2238 bytes --]

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

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

[-- Attachment #2: linux-vimc-6.20-rc1.diff --]
[-- Type: text/x-patch, Size: 19159 bytes --]

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);

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-01-14 15:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-08 21:42 [GIT PULL] Linux Media vimc update for 6.20-rc1 Shuah Khan
2026-01-13  9:19 ` Hans Verkuil
2026-01-14 15:54   ` Shuah Khan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®