{"id":26081,"url":"https://patchwork.libcamera.org/api/1.1/patches/26081/?format=json","web_url":"https://patchwork.libcamera.org/patch/26081/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/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":"<20260202194645.1287757-3-faizel.kb@gmail.com>","date":"2026-02-02T19:46:44","name":"[v2,2/3] media: vimc: sensor: Add pixel_rate, vblank and hblank configuration","commit_ref":null,"pull_url":null,"state":"not-applicable","archived":false,"hash":"d2195b19818020e39d373ba622f66b41f32c4199","submitter":{"id":258,"url":"https://patchwork.libcamera.org/api/1.1/people/258/?format=json","name":"Faizel K B","email":"faizel.kb@gmail.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/26081/mbox/","series":[{"id":5767,"url":"https://patchwork.libcamera.org/api/1.1/series/5767/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5767","date":"2026-02-02T19:46:42","name":"media: vimc: Add timing controls for fps config","version":2,"mbox":"https://patchwork.libcamera.org/series/5767/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/26081/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/26081/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 1AF63C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  2 Feb 2026 19:47:12 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B62D562007;\n\tMon,  2 Feb 2026 20:47:11 +0100 (CET)","from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com\n\t[IPv6:2607:f8b0:4864:20::52c])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3E9CA62000\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  2 Feb 2026 20:47:10 +0100 (CET)","by mail-pg1-x52c.google.com with SMTP id\n\t41be03b00d2f7-c634be422b2so304832a12.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 02 Feb 2026 11:47:10 -0800 (PST)","from FAIZEL-KB.. ([2001:569:5999:dc00:af0:4465:b482:1e01])\n\tby smtp.googlemail.com with ESMTPSA id\n\td2e1a72fcca58-82379b1bc68sm16667416b3a.2.2026.02.02.11.47.07\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 02 Feb 2026 11:47:08 -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=\"BnE7XNCs\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20230601; t=1770061629; x=1770666429;\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=BkX201pGc8zZ3+cPLNIedhLkaj9hw8wjTG/zVIPjTJE=;\n\tb=BnE7XNCsnCd1QsvwWzyIt83vDeoTKaEztJCdpo224RezJao6SIsYzpeyUOVQWIoFJK\n\t0ZvJlCoFqMvBYoPaprHRSAMI3hjAjFX2SL8VvBpA70dHNE8ArT9TdVzjDxe1e4Rs0Kej\n\texhEffIT9EdOIhh323WAcynkLnnvmyxwMLLQTBVQOM6AqVeQrPVJdWWkred+QDanIpRq\n\t3zOGkPIKtfvIsIAccxpFRP7LUC8ev3qsCyEHWhNmUDuJMkM1l082+3R/0QUEIZFhc/vp\n\tirKT8OkBdGAG1W9amqmqi1fWpmQnEJ5V8qXE/vpSwJEjcKiFvHgzx9qx767sWqxrAxOP\n\tDKog==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1770061629; x=1770666429;\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=BkX201pGc8zZ3+cPLNIedhLkaj9hw8wjTG/zVIPjTJE=;\n\tb=gcwixGtNZrbw4t4K+b+MTFMqga1apVNbZzEmH/M0JUUi9kQJqg0lNHS/edxgwh901t\n\t5KfTEFFzHtN9WDMZGcD/PAx7dshAAHpJUVc3CQAfn6LMUaTI5oQ34X1I6eSeRRW6lfpb\n\tLQKjSwea1j/PlRFUNXxeOnfKpnyYGPl+EV63dNWDdNwvk2FbnF/4gppIP10PLkiIP7oQ\n\t/aCm9EFaGHK3lfsc6YcatR1ST+qBNKwD+cYRTydKmKBKMk8clX1py8IEcMiX401IK1Fj\n\t3hK458u0f6tzC8whD0n5eKxrhZ5YnxPt/J7XvDPG4aPNjTdIR4OJrHdv1LUsOli7eO0t\n\tJGeA==","X-Forwarded-Encrypted":"i=1;\n\tAJvYcCXcBLmsx5K2FkvUNtrrLvxsNa/fbiwFIfzUlRVve22c9t5ibyZj80SWDkTNXeqxITx7qAOkTpl8ZDWOwEYEMLQ=@lists.libcamera.org","X-Gm-Message-State":"AOJu0Yxdxf/YIc/BvRve26Fs2ZHV9SPt0COUyza7rOjDNG5BopuqUgC+\n\tBc04jBYU47L/GkiMAE2y4yBYN7esbcMUqytO2b/Yc2TtWJYgINoNMEcq","X-Gm-Gg":"AZuq6aLHHl7J1wlP7KdioGQLm07MwMhVGwZrPzx8ICj4eRyuY+SSY4Jey9UeWUfGjE+\n\tmGqtSRs2+oaMAPEGwPByCe5fScbymtdI4dbE2ThZJMXAfIpvcdKNSzGsb+BhnrtCaYu6kYy6s/g\n\tPMWR0u4b1mP5jcXBsOzRG0KSEQDkUhavjmzHM8x+/XKMV/E1tQR0Ktyj+sv8obE53GJpAhZXiho\n\tygmsP/VW390oBTDtqtjUYvd5SR7okpSVEcPminlikTcg6y1W3LaqIYnCT7EUvadqmJ1+2gNLcov\n\tWXvA3JMr41/AiIUKRhLcNuERCmW9ig3COvfQLgvXm9sDJfN+0Lj+yzwwd6tAbfCi7fVqXB06PrT\n\tZuKmcLhBAaUWS/xGKLmnOJQB+vZR8m/H0rJpL68b5GtkdDJbjX+S/VBl+EQ4Go1x2HF6RR9a+5j\n\tDOt+pGr1Y2k8VjoY8SEpmGWOwjWkq6UBEPDWvHCevhtweM2wPZXM6EaQ==","X-Received":"by 2002:a05:6a20:734b:b0:38e:9a8b:248d with SMTP id\n\tadf61e73a8af0-392e0163a22mr9055261637.5.1770061628779; \n\tMon, 02 Feb 2026 11:47:08 -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 v2 2/3] media: vimc: sensor: Add pixel_rate,\n\tvblank and hblank configuration","Date":"Mon,  2 Feb 2026 11:46:44 -0800","Message-ID":"<20260202194645.1287757-3-faizel.kb@gmail.com>","X-Mailer":"git-send-email 2.43.0","In-Reply-To":"<20260202194645.1287757-1-faizel.kb@gmail.com>","References":"<20260202194645.1287757-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 | 82 +++++++++++++++++++\n 2 files changed, 95 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..84cef55b68f8 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,18 @@ 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+\tu32 vblank_def;\n+\n+\ttarget_fps = (width * height <= VIMC_PIXELS_THRESHOLD_30FPS) ? 30 : 10;\n+\tvblank_def = (pixel_rate / (target_fps * hts)) - height;\n+\treturn clamp(vblank_def, VIMC_VBLANK_MIN, VIMC_VBLANK_MAX);\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 +174,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 +273,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 +346,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 +439,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":["v2","2/3"]}