{"id":26089,"url":"https://patchwork.libcamera.org/api/patches/26089/?format=json","web_url":"https://patchwork.libcamera.org/patch/26089/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260204203726.1820226-3-faizel.kb@gmail.com>","date":"2026-02-04T20:37:25","name":"[v3,2/3] media: vimc: sensor: Add pixel_rate, vblank and hblank configuration","commit_ref":null,"pull_url":null,"state":"not-applicable","archived":false,"hash":"f25383595aba87f6a9cd56b9c79bd6ffd179b774","submitter":{"id":258,"url":"https://patchwork.libcamera.org/api/people/258/?format=json","name":"Faizel K B","email":"faizel.kb@gmail.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/26089/mbox/","series":[{"id":5771,"url":"https://patchwork.libcamera.org/api/series/5771/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5771","date":"2026-02-04T20:37:23","name":"media: vimc: Add timing controls for fps config","version":3,"mbox":"https://patchwork.libcamera.org/series/5771/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/26089/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/26089/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 53833BD78E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  4 Feb 2026 20:38:15 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0133762048;\n\tWed,  4 Feb 2026 21:38:15 +0100 (CET)","from mail-pl1-x630.google.com (mail-pl1-x630.google.com\n\t[IPv6:2607:f8b0:4864:20::630])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E526262043\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  4 Feb 2026 21:38:12 +0100 (CET)","by mail-pl1-x630.google.com with SMTP id\n\td9443c01a7336-2a097cc08d5so572565ad.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 04 Feb 2026 12:38:12 -0800 (PST)","from FAIZEL-KB.. ([2001:569:5999:dc00:876b:c389:85e5:7957])\n\tby smtp.googlemail.com with ESMTPSA id\n\td9443c01a7336-2a933974884sm31136955ad.83.2026.02.04.12.38.10\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 04 Feb 2026 12:38:10 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"i9ex0h32\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20230601; t=1770237491; x=1770842291;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=+YiPQWXH9LfFe5Ipw86gccMFuVs2bYaP/flxUeZTgEw=;\n\tb=i9ex0h32t/IeSVCPcVS6hqEHj/1TdN+wC9B4qpNhaUr4ZABLqvrHDr+BetyOoV6cbD\n\t+jxwmqIDx8Mz5AlOGBO7EniQUsC7Cr07Jow4v9l8wvPhnQKJpVOLx019+epGeu9zhVAw\n\taLHy5J4o0lqVyb5bDWIUp0fC8DSfoW032HfURinei5ed9H+JwjiO3r1UZTM6US5+iEN0\n\tMqhQlEnbs5wmv0ytVUJ00kV7vnSOkf4EN7oDcdZNRfRNJx9WMuFA4zm5EFvYT5KQtjT9\n\th4flx5dbBwWQXmKZDeYm4ofe6INsnE5O9PnbwT8qJPV8Z8YnDbJeE1t4Ldm6mVaZl20E\n\tpTXw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1770237491; x=1770842291;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n\t:to:cc:subject:date:message-id:reply-to;\n\tbh=+YiPQWXH9LfFe5Ipw86gccMFuVs2bYaP/flxUeZTgEw=;\n\tb=w25ldTcKYLJajZZvrZn39lnemvnLwnOZkZEHAIR7ePgqnAK5etVe2cOO9pqHjss+H+\n\t7Nli+pwFOXj53AQzSt0sks1ry+iK9m7dvR9oa9G1MHWPnFOPC20PGJ7+h0xT1G7hCCGK\n\tQF/GSqtX17/U55TGfj2CttU299sNNApJuyRqGo4lUPJhQ7vr9xInYwN0XLtFt1QGqL2M\n\t1vKemu+iqvVV2Qw53QqG/b3VVTZHuf6L4HBpZMWmRe3EhFB0LV2xLDOUcYXGknt3j8ni\n\tS7+EAgCxXzi5WwotnGdezqxOVDaxJ5RRSvGVkJ0FiwyoumbtS9zqTA5MR598RlbeG9rJ\n\twF5g==","X-Forwarded-Encrypted":"i=1;\n\tAJvYcCXzrnllGdbKJ6EdCtdG214x0DoMzH+Z81PME/mYlfBQUJ/AX2kYwXcFmEbQYlrqZSIr3EJd6QbgiFXBlqmifTQ=@lists.libcamera.org","X-Gm-Message-State":"AOJu0Yx5bI3JWg0M7d2TbZaAHrzNBAaxJd18rQ3zYnz/DclbC4ftPZcV\n\thCnghJWY5MOBOyKQqerzfhrfU2GprFzoBt6t4YjhP/1q93NSXKfTvZjS","X-Gm-Gg":"AZuq6aJam2F6Re42qJTH8T2cXrQLjQv0vUMa5Ma79ze7WCNR0V7nYPuvVhdQka6m8+H\n\t9VmDxgdg1nChDam8HnNetgRrK2PWM7Y+OLTkIdqHCrI+r9hDUm0sRj0aT3VQPBM+Vw3lUEqBBtU\n\tUwC0KD5CgkKFc0yiQM30zOOukHKlR1xWRqQ0fNseA2ZH5zih6ANwm22vwPtIV97ndgZeRllCtgA\n\tvkmbCHivcqgiqWuIVfCfbT/y50Kyvtz+Ie5gIL1bjp5p0kO/8yc7ovwNSAPWYq0jP8C1d/pDpM3\n\t+nJtBWMiEQkZK82IkLiaPEOvKKNrAzKnrxVSDCbMI7mJhaagqtTbkcTlCqQw/NOzcWLod0OPopm\n\tDj9UI5ZrEwhQk0JJJhDx6kqjx0eTIkn9VIB9wUM9LqzFBC8A6pLFBPf8DMmEuQCRJ2zUwm5cTtQ\n\tQ6t2sSSyWb8qAL8+mA1mn7REIuokzjRQR9Xaq/FKbwzIfL","X-Received":"by 2002:a17:902:cf07:b0:29a:56a:8b81 with SMTP id\n\td9443c01a7336-2a93400b5c5mr30910985ad.8.1770237491410; \n\tWed, 04 Feb 2026 12:38:11 -0800 (PST)","From":"Faizel K B <faizel.kb@gmail.com>","To":"Shuah Khan <skhan@linuxfoundation.org>,\n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlinux-media@vger.kernel.org","Cc":"Mauro Carvalho Chehab <mchehab@kernel.org>,\n\tlibcamera-devel@lists.libcamera.org, Faizel K B <faizel.kb@gmail.com>","Subject":"[PATCH v3 2/3] media: vimc: sensor: Add pixel_rate,\n\tvblank and hblank configuration","Date":"Wed,  4 Feb 2026 12:37:25 -0800","Message-ID":"<20260204203726.1820226-3-faizel.kb@gmail.com>","X-Mailer":"git-send-email 2.43.0","In-Reply-To":"<20260204203726.1820226-1-faizel.kb@gmail.com>","References":"<20260204203726.1820226-1-faizel.kb@gmail.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"pixel_rate and hblank as read only parameter. vblank can be configured\nto match the desired frame rate.\n\nDefault values are, pixel_rate - 160 MHz, hblank - 800.\nvblank defaults to an equivalent value of 30 fps for resolutions less than\nor equal to 1920x1080 and 10 fps for higher resolutions. For higher\nresolutions, modify pixel_rate in the driver code.\nfps = pixel_rate / ((width + hblank) * (height + vblank))\nminimum vblank - 4, maximum vblank - 65535\n\nThe configured fps delay is pre-calculated into jiffies and\nstored in the sensor's hw structure for efficient access by the\nstreamer thread.\n\nSigned-off-by: Faizel K B <faizel.kb@gmail.com>\n---\n drivers/media/test-drivers/vimc/vimc-common.h | 13 +++\n drivers/media/test-drivers/vimc/vimc-sensor.c | 88 +++++++++++++++++++\n 2 files changed, 101 insertions(+)","diff":"diff --git a/drivers/media/test-drivers/vimc/vimc-common.h b/drivers/media/test-drivers/vimc/vimc-common.h\nindex 35789add6b4a..861b334ffc65 100644\n--- a/drivers/media/test-drivers/vimc/vimc-common.h\n+++ b/drivers/media/test-drivers/vimc/vimc-common.h\n@@ -29,6 +29,15 @@\n #define VIMC_FRAME_MIN_WIDTH 16\n #define VIMC_FRAME_MIN_HEIGHT 16\n \n+#define VIMC_PIXEL_RATE_FIXED\t\t160000000\t/* 160 MHz */\n+#define VIMC_HBLANK_FIXED\t\t800\n+/* VBLANK - vertical blanking (primary FPS control) */\n+#define VIMC_VBLANK_MIN\t\t\t4\n+#define VIMC_VBLANK_MAX\t\t\t65535\n+#define VIMC_VBLANK_STEP\t\t1\n+#define VIMC_VBLANK_DEFAULT\t        3223           /* 30fps vga */\n+#define VIMC_PIXELS_THRESHOLD_30FPS\t(1920 * 1080) /* 2073600 pixels */\n+\n #define VIMC_FRAME_INDEX(lin, col, width, bpp) ((lin * width + col) * bpp)\n \n /* Source and sink pad checks */\n@@ -173,6 +182,9 @@ struct vimc_sensor_device {\n \tstruct tpg_data tpg;\n \tstruct v4l2_ctrl_handler hdl;\n \tstruct media_pad pad;\n+\tstruct v4l2_ctrl *pixel_rate;\n+\tstruct v4l2_ctrl *hblank;\n+\tstruct v4l2_ctrl *vblank;\n \n \tu8 *frame;\n \n@@ -184,6 +196,7 @@ struct vimc_sensor_device {\n \t\tstruct v4l2_area size;\n \t\tenum vimc_sensor_osd_mode osd_value;\n \t\tu64 start_stream_ts;\n+\t\tunsigned long fps_jiffies;\n \t} hw;\n };\n \ndiff --git a/drivers/media/test-drivers/vimc/vimc-sensor.c b/drivers/media/test-drivers/vimc/vimc-sensor.c\nindex 2b07dc1f1278..6c3e6066eaa5 100644\n--- a/drivers/media/test-drivers/vimc/vimc-sensor.c\n+++ b/drivers/media/test-drivers/vimc/vimc-sensor.c\n@@ -25,10 +25,15 @@ static const struct v4l2_mbus_framefmt fmt_default = {\n static int vimc_sensor_init_state(struct v4l2_subdev *sd,\n \t\t\t\t  struct v4l2_subdev_state *sd_state)\n {\n+\tstruct vimc_sensor_device *vsensor =\n+\t\tcontainer_of(sd, struct vimc_sensor_device, sd);\n+\n \tstruct v4l2_mbus_framefmt *mf;\n \n \tmf = v4l2_subdev_state_get_format(sd_state, 0);\n \t*mf = fmt_default;\n+\tvsensor->hw.size.width = fmt_default.width;\n+\tvsensor->hw.size.height = fmt_default.height;\n \n \treturn 0;\n }\n@@ -87,6 +92,26 @@ static void vimc_sensor_tpg_s_format(struct vimc_sensor_device *vsensor,\n \ttpg_s_xfer_func(&vsensor->tpg, format->xfer_func);\n }\n \n+static int vimc_sensor_update_frame_timing(struct v4l2_subdev *sd,\n+\t\t\t\t\t   u32 width, u32 height)\n+{\n+\tstruct vimc_sensor_device *vsensor =\n+\t\tcontainer_of(sd, struct vimc_sensor_device, sd);\n+\tu64 pixel_rate = vsensor->pixel_rate->val;\n+\tu32 hts = width + vsensor->hblank->val;\n+\tu32 vts = height + vsensor->vblank->val;\n+\tu64 total_pixels = (u64)hts * vts;\n+\tu64 frame_interval_ns;\n+\n+\tframe_interval_ns = total_pixels * NSEC_PER_SEC;\n+\tdo_div(frame_interval_ns, pixel_rate);\n+\tvsensor->hw.fps_jiffies = nsecs_to_jiffies(frame_interval_ns);\n+\tif (vsensor->hw.fps_jiffies == 0)\n+\t\tvsensor->hw.fps_jiffies = 1;\n+\n+\treturn 0;\n+}\n+\n static void vimc_sensor_adjust_fmt(struct v4l2_mbus_framefmt *fmt)\n {\n \tconst struct vimc_pix_map *vpix;\n@@ -108,6 +133,24 @@ static void vimc_sensor_adjust_fmt(struct v4l2_mbus_framefmt *fmt)\n \tvimc_colorimetry_clamp(fmt);\n }\n \n+static u32 vimc_calc_vblank(u32 width, u32 height,\n+\t\t\t    s64 pixel_rate, s32 hblank)\n+{\n+\tu32 hts = width + hblank;\n+\tu32 target_fps;\n+\tu64 vts;\n+\n+\ttarget_fps = (width * height <= VIMC_PIXELS_THRESHOLD_30FPS) ? 30 : 10;\n+\n+\tvts = (u64)pixel_rate;\n+\tdo_div(vts, target_fps * hts);\n+\n+\tif (vts > height)\n+\t\treturn clamp((u32)(vts - height), VIMC_VBLANK_MIN, VIMC_VBLANK_MAX);\n+\n+\treturn VIMC_VBLANK_MIN;\n+}\n+\n static int vimc_sensor_set_fmt(struct v4l2_subdev *sd,\n \t\t\t       struct v4l2_subdev_state *sd_state,\n \t\t\t       struct v4l2_subdev_format *fmt)\n@@ -137,6 +180,20 @@ static int vimc_sensor_set_fmt(struct v4l2_subdev *sd,\n \t\tfmt->format.xfer_func, fmt->format.ycbcr_enc);\n \n \t*mf = fmt->format;\n+\tif (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {\n+\t\tu32 vblank_def = vimc_calc_vblank(fmt->format.width,\n+\t\t\t\t\t\t  fmt->format.height,\n+\t\t\t\t\t\t  vsensor->pixel_rate->val,\n+\t\t\t\t\t\t  vsensor->hblank->val);\n+\t\tvsensor->hw.size.width = fmt->format.width;\n+\t\tvsensor->hw.size.height = fmt->format.height;\n+\t\t__v4l2_ctrl_modify_range(vsensor->vblank,\n+\t\t\t\t\t VIMC_VBLANK_MIN,\n+\t\t\t\t\t VIMC_VBLANK_MAX,\n+\t\t\t\t\t VIMC_VBLANK_STEP,\n+\t\t\t\t\t vblank_def);\n+\t\t__v4l2_ctrl_s_ctrl(vsensor->vblank, vblank_def);\n+\t}\n \n \treturn 0;\n }\n@@ -222,6 +279,8 @@ static int vimc_sensor_s_stream(struct v4l2_subdev *sd, int enable)\n \n \t\tvsensor->hw.size.width = format->width;\n \t\tvsensor->hw.size.height = format->height;\n+\t\tvimc_sensor_update_frame_timing(sd, format->width,\n+\t\t\t\t\t\tformat->height);\n \n \t\tv4l2_subdev_unlock_state(state);\n \n@@ -293,6 +352,15 @@ static int vimc_sensor_s_ctrl(struct v4l2_ctrl *ctrl)\n \tcase VIMC_CID_OSD_TEXT_MODE:\n \t\tvsensor->hw.osd_value = ctrl->val;\n \t\tbreak;\n+\tcase V4L2_CID_PIXEL_RATE:\n+\t\tbreak;\n+\tcase V4L2_CID_HBLANK:\n+\t\tbreak;\n+\tcase V4L2_CID_VBLANK:\n+\t\tvimc_sensor_update_frame_timing(&vsensor->sd,\n+\t\t\t\t\t\tvsensor->hw.size.width,\n+\t\t\t\t\t\tvsensor->hw.size.height);\n+\t\tbreak;\n \tdefault:\n \t\treturn -EINVAL;\n \t}\n@@ -377,6 +445,26 @@ static struct vimc_ent_device *vimc_sensor_add(struct vimc_device *vimc,\n \t\t\t  V4L2_CID_HUE, -128, 127, 1, 0);\n \tv4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,\n \t\t\t  V4L2_CID_SATURATION, 0, 255, 1, 128);\n+\t/* Timing controls for frame interval configuration */\n+\tvsensor->pixel_rate = v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,\n+\t\t\t\t\t\tV4L2_CID_PIXEL_RATE,\n+\t\t\t\t\t\tVIMC_PIXEL_RATE_FIXED, VIMC_PIXEL_RATE_FIXED,\n+\t\t\t\t\t\t1, VIMC_PIXEL_RATE_FIXED);\n+\tif (vsensor->pixel_rate)\n+\t\tvsensor->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;\n+\n+\tvsensor->hblank = v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,\n+\t\t\t\t\t    V4L2_CID_HBLANK,\n+\t\t\t\t\t    VIMC_HBLANK_FIXED, VIMC_HBLANK_FIXED,\n+\t\t\t\t\t    1, VIMC_HBLANK_FIXED);\n+\tif (vsensor->hblank)\n+\t\tvsensor->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;\n+\n+\tvsensor->vblank = v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,\n+\t\t\t\t\t    V4L2_CID_VBLANK,\n+\t\t\t\t\t    VIMC_VBLANK_MIN, VIMC_VBLANK_MAX,\n+\t\t\t\t\t    VIMC_VBLANK_STEP, VIMC_VBLANK_DEFAULT);\n+\n \tvsensor->sd.ctrl_handler = &vsensor->hdl;\n \tif (vsensor->hdl.error) {\n \t\tret = vsensor->hdl.error;\n","prefixes":["v3","2/3"]}