From nobody Sat Feb 7 17:55:07 2026 Received: from mail-pg1-f171.google.com (mail-pg1-f171.google.com [209.85.215.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4C55B1BF58 for ; Sat, 1 Nov 2025 05:27:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761974881; cv=none; b=A4De8tdj3L3xZvITqkinhQVA+rv2BttCCjVKlZlcCmNHI+i3xbS0Llao1658RQaHhUsMkcT4gkqaxre7WJ+ylVQQuVqn3dM0JyaxsLSxoBDbn6xi8leiE10Y7Q2EMvHDvlXnI9F/4Thw+/Au51PfhWFigzSwodELMO1T9Xmxic8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761974881; c=relaxed/simple; bh=+GZ9/pl+8tJmcSAdMKK7yphZtxzKGCjQy/GcNEI0V8c=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=hFMMOjzzBiM8XnOG6mWRe3uFS9dyRnjAe2MI8SVAzNt3v0GhFantje+nHgYGXw37Dirz2ckdxFFlSzFch8tzwNa80ZhA2422MWCPP8s2M5kfmKtxv8rgLa0++I1c9fNY3zKMrWbuKQxIngHRkxECWsgE+csLb9KuYa8RvZn8d1E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=X9Bxb1Z/; arc=none smtp.client-ip=209.85.215.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="X9Bxb1Z/" Received: by mail-pg1-f171.google.com with SMTP id 41be03b00d2f7-b8aa14e5ed9so2252634a12.0 for ; Fri, 31 Oct 2025 22:27:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1761974878; x=1762579678; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=z/ptnNT0Ywe4s6PcYyycXyPs8DpHI02oawu5aekCWR0=; b=X9Bxb1Z/0QXoU8q3d9yG78L+a5bNqc8F+1sNinz6pRbRvmqpwSkIInKT9C7mwhm5Zk OIHmYD03+YjBtcARD+Ewh7CjzkqzaMWThZJiKx1uKlBRgot4/9FO/X2GXz6Cli/0gv70 2TR8F0bf1szviSuxLGsrVPFEWP+GF86qJ9UAIJ9exgmSIpWBkF8DSu1smfEPypN9C8xl nC6KxC4JOhwCreC8KK2ugSYyt/vZtYaRgFvvhXYp3Em6WaPHHmqB7bKpNnKPm4/hx9Pj eBj5JOJFV09iABW3AgdjJ293mOxSe+VIgzGgEUs0nRGNHuyB+4ilwmGjTDPyi1Efr+oN sUFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761974878; x=1762579678; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=z/ptnNT0Ywe4s6PcYyycXyPs8DpHI02oawu5aekCWR0=; b=ktrQnO+F/Z/7Qsqy5j4egXWdlywC+MRkw5QZbgFWvWPwdY7XM3Z/517BUXz9ZwClmx OMcIKHSKZ0bBbAU36/0aT9CYVbOkJ+kl/iGjLNdfDdXgPWt0QZQC5R3fVMG2l7ZHB2ZW 6wjU8sbpartH/e3x/XsID0ErAf1md0BuuX2xOdxyh+JZyjZa0a4rRQOvTY2pin01QaXp aAQs9of1sqfrgtJA1HbX7xnXE3IReXmlGhePuzk/wlKZ8ymhVynfj99gj6uD3iyIS4GI MUqtAaUrzn7c6yCP9SG1CeOlSThLgEeE4Fu6Br99c2cSsEkmbEt9wGZENMQ4+3bOajIC UsAA== X-Forwarded-Encrypted: i=1; AJvYcCUopNrdHzzhj+y162qB65iqj+opzySVXj2n+0V+YW9pJlSSRC9mxjGN/8TNY7IPv2Ayv/rWYwX1dvuQu1Q=@vger.kernel.org X-Gm-Message-State: AOJu0YxGg0dnIm8PunUoROpSas1deRICLn9qjit1sFPSD5K4IN779fM6 ndosEYUdb+xwp2iR9DchF+H1pBuSjGEz1umpt72ucpZbHoA6ogzoVvYp X-Gm-Gg: ASbGncspyiC/7+gt1DaxNyuSQZ02UvsrBYMBnyu+90vXMM1d4sFIfeNE9PH5qeGT+87 FL3s2eq9ozUjUvrlh/c3121p4PBedUFsx3k33HUWHJnsMg4NgJs/I1XgOw5diILkBDF+RlNKflT XB3yywmQfYMqMDu+LWv5D6qOhIzJw96715McHGjzWMgK4AfmesIlifPl9ELVEMNta52+/xqKwdW rRzb+e0C3lk3rGjIdFI6yZN8cSZR+uOl06QPmcRwZyv5UuxleCO+/HcndeyvpHi95nJKpnBjLhE jpcri+T9BDEwt5QNEFNoEBgKQXS85CWt0cWt7sEPbTExm4a9eNRJlxuejTHPkNsz3wJK7cgiVyO /Bp8M+O7Pvro0olJek8hl31p4cZ4jKsz6ku0XPiy4cqiJ3PCw38jS6F7vkkG6nm4/UGzartWptA dhY+pROp1xbVhbB6pVqUAY+P32winlTeAKxxrVokxOMs9Z6GKPuiGCkXZCDQ4sr3MSdGvcFez4S tl/eWkfrG1He35fo9BqshaU3g== X-Google-Smtp-Source: AGHT+IGsr0iWlw76pddp4ckfx5jyzC4ernwO/7Dv/NG7LUkw/+6xWR4R4woGmK7aLj+ui0CQBbPtug== X-Received: by 2002:a17:903:3c23:b0:294:7048:643 with SMTP id d9443c01a7336-2951a3981fcmr77796005ad.15.1761974878463; Fri, 31 Oct 2025 22:27:58 -0700 (PDT) Received: from opensource206.. ([106.222.234.180]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3407f24ee93sm2041158a91.9.2025.10.31.22.27.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 31 Oct 2025 22:27:58 -0700 (PDT) From: Pavan Bobba To: skhan@linuxfoundation.org, kieran.bingham@ideasonboard.com, mchehab@kernel.org Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Pavan Bobba Subject: [PATCH] media: vimc: add RGB/YUV input entity implementation Date: Sat, 1 Nov 2025 10:56:51 +0530 Message-ID: <20251101052651.6197-1-opensource206@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a new vimc-input entity to simulate a color frame source in the Virtual Media Controller (VIMC) pipeline. This entity outputs RGB888 frames and allows testing of pipelines that start from a pre-processed RGB/YUV source instead of a raw Bayer sensor. The patch adds vimc-input.c with basic pad operations for format enumeration, get/set, and stream enable/disable handlers. The entity is registered in the VIMC core configuration, replacing the previous temporary use of vimc-sensor. Frame generation is not yet implemented and remains a TODO for future work. This change enables link validation and format negotiation for the RGB/YUV input path, paving the way for software frame injection and test-pattern generation. Signed-off-by: Pavan Bobba --- drivers/media/test-drivers/vimc/Makefile | 3 +- drivers/media/test-drivers/vimc/vimc-common.h | 1 + drivers/media/test-drivers/vimc/vimc-core.c | 3 +- drivers/media/test-drivers/vimc/vimc-input.c | 210 ++++++++++++++++++ 4 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 drivers/media/test-drivers/vimc/vimc-input.c 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 :=3D 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 =20 obj-$(CONFIG_VIDEO_VIMC) +=3D vimc.o =20 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; =20 /** * 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/te= st-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[] =3D { .type =3D &vimc_capture_type }, [RGB_YUV_INPUT] =3D { - /* TODO: change this to vimc-input when it is implemented */ .name =3D "RGB/YUV Input", - .type =3D &vimc_sensor_type + .type =3D &vimc_input_type }, [SCALER] =3D { .name =3D "Scaler", diff --git a/drivers/media/test-drivers/vimc/vimc-input.c b/drivers/media/t= est-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 +#include + +#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 =3D { + .width =3D 640, + .height =3D 480, + .code =3D MEDIA_BUS_FMT_RGB888_1X24, + .field =3D V4L2_FIELD_NONE, + .colorspace =3D 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 =3D 0; i < sd->entity.num_pads; i++) { + mf =3D v4l2_subdev_state_get_format(sd_state, i); + *mf =3D 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 =3D 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 =3D vimc_pix_map_by_code(fse->code); + if (!vpix) + return -EINVAL; + + fse->min_width =3D VIMC_FRAME_MIN_WIDTH; + fse->max_width =3D VIMC_FRAME_MAX_WIDTH; + fse->min_height =3D VIMC_FRAME_MIN_HEIGHT; + fse->max_height =3D 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 =3D v4l2_subdev_state_get_format(sd_state, fmt->pad); + + fmt->format =3D *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 =3D v4l2_subdev_state_get_format(sd_state, fmt->pad); + + /* Set the new format */ + *mf =3D 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 =3D { + .enum_mbus_code =3D vimc_input_enum_mbus_code, + .enum_frame_size =3D vimc_input_enum_frame_size, + .get_fmt =3D vimc_input_get_fmt, + .set_fmt =3D vimc_input_set_fmt, + .enable_streams =3D vimc_input_enable_streams, + .disable_streams =3D vimc_input_disable_streams, +}; + +static const struct v4l2_subdev_ops vimc_input_ops =3D { + .pad =3D &vimc_input_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops vimc_input_internal_ops =3D { + .init_state =3D vimc_input_init_state, +}; + +static void vimc_input_release(struct vimc_ent_device *ved) +{ + struct vimc_input_device *vinput =3D + 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 =3D &vimc->v4l2_dev; + struct vimc_input_device *vinput; + int ret; + + /* Allocate the vinput struct */ + vinput =3D kzalloc(sizeof(*vinput), GFP_KERNEL); + if (!vinput) + return ERR_PTR(-ENOMEM); + + /* Initialize the media pad */ + vinput->pad.flags =3D MEDIA_PAD_FL_SOURCE; + + ret =3D 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 =3D vimc_input_process_frame; + vinput->ved.dev =3D vimc->mdev.dev; + + return &vinput->ved; + +err_free_vinput: + kfree(vinput); + + return ERR_PTR(ret); +} + +const struct vimc_ent_type vimc_input_type =3D { + .add =3D vimc_input_add, + .release =3D vimc_input_release +}; --=20 2.43.0