LKML Archive mirror
 help / color / mirror / Atom feed
From: Benjamin Bara <bbara93@gmail.com>
To: Mauro Carvalho Chehab <mchehab@kernel.org>,
	Manivannan Sadhasivam <mani@kernel.org>
Cc: laurent.pinchart@ideasonboard.com, jacopo.mondi@ideasonboard.com,
	linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
	Benjamin Bara <benjamin.bara@skidata.com>
Subject: [PATCH 2/2] media: i2c: imx290: Add support for V4L2_CID_VTOTAL
Date: Fri, 09 Jun 2023 15:15:56 +0200	[thread overview]
Message-ID: <20230609-v4l2-vtotal-v1-2-4b7dee7e073e@skidata.com> (raw)
In-Reply-To: <20230609-v4l2-vtotal-v1-0-4b7dee7e073e@skidata.com>

From: Benjamin Bara <benjamin.bara@skidata.com>

The new V4L2_CID_VTOTAL control represents the VMAX register.
Implementing it simplifies calculations in user space, as it is
independent of the current mode (format height), meaning its value does
not change with format changes.

Signed-off-by: Benjamin Bara <benjamin.bara@skidata.com>
---
 drivers/media/i2c/imx290.c | 47 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 5ea25b7acc55..42938400efb0 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -255,6 +255,7 @@ struct imx290 {
 	struct v4l2_ctrl *link_freq;
 	struct v4l2_ctrl *hblank;
 	struct v4l2_ctrl *vblank;
+	struct v4l2_ctrl *vtotal;
 	struct v4l2_ctrl *exposure;
 	struct {
 		struct v4l2_ctrl *hflip;
@@ -782,8 +783,7 @@ static void imx290_exposure_update(struct imx290 *imx290,
 {
 	unsigned int exposure_max;
 
-	exposure_max = imx290->vblank->val + mode->height -
-		       IMX290_EXPOSURE_OFFSET;
+	exposure_max = imx290->vtotal->val - IMX290_EXPOSURE_OFFSET;
 	__v4l2_ctrl_modify_range(imx290->exposure, 1, exposure_max, 1,
 				 exposure_max);
 }
@@ -794,7 +794,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 					     struct imx290, ctrls);
 	const struct v4l2_mbus_framefmt *format;
 	struct v4l2_subdev_state *state;
-	int ret = 0, vmax;
+	int ret = 0;
 
 	/*
 	 * Return immediately for controls that don't need to be applied to the
@@ -803,10 +803,22 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 	if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
 		return 0;
 
-	if (ctrl->id == V4L2_CID_VBLANK) {
-		/* Changing vblank changes the allowed range for exposure. */
+	/* Changing vtotal changes the allowed range for exposure. */
+	if (ctrl->id == V4L2_CID_VTOTAL)
 		imx290_exposure_update(imx290, imx290->current_mode);
-	}
+
+	/*
+	 * vblank and vtotal depend on each other, therefore also update the
+	 * other one.
+	 */
+	if (ctrl->id == V4L2_CID_VBLANK &&
+	    imx290->vtotal->val != ctrl->val + imx290->current_mode->height)
+		__v4l2_ctrl_s_ctrl(imx290->vtotal,
+				   ctrl->val + imx290->current_mode->height);
+	if (ctrl->id == V4L2_CID_VTOTAL &&
+	    imx290->vblank->val != ctrl->val - imx290->current_mode->height)
+		__v4l2_ctrl_s_ctrl(imx290->vblank,
+				   ctrl->val - imx290->current_mode->height);
 
 	/* V4L2 controls values will be applied only when power is already up */
 	if (!pm_runtime_get_if_in_use(imx290->dev))
@@ -821,9 +833,14 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 
 	case V4L2_CID_VBLANK:
-		ret = imx290_write(imx290, IMX290_VMAX,
-				   ctrl->val + imx290->current_mode->height,
-				   NULL);
+		/* vblank is updated by vtotal. */
+		break;
+
+	case V4L2_CID_VTOTAL:
+		ret = imx290_write(imx290, IMX290_VMAX, ctrl->val, NULL);
+		if (ret)
+			goto err;
+
 		/*
 		 * Due to the way that exposure is programmed in this sensor in
 		 * relation to VMAX, we have to reprogramme it whenever VMAX is
@@ -834,9 +851,8 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 		ctrl = imx290->exposure;
 		fallthrough;
 	case V4L2_CID_EXPOSURE:
-		vmax = imx290->vblank->val + imx290->current_mode->height;
 		ret = imx290_write(imx290, IMX290_SHS1,
-				   vmax - ctrl->val - 1, NULL);
+				   imx290->vtotal->val - ctrl->val - 1, NULL);
 		break;
 
 	case V4L2_CID_TEST_PATTERN:
@@ -880,6 +896,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 	}
 
+err:
 	pm_runtime_mark_last_busy(imx290->dev);
 	pm_runtime_put_autosuspend(imx290->dev);
 
@@ -911,11 +928,14 @@ static void imx290_ctrl_update(struct imx290 *imx290,
 	unsigned int vblank_max = IMX290_VMAX_MAX - mode->height;
 
 	__v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);
+	__v4l2_ctrl_s_ctrl(imx290->vblank, imx290->vtotal->val - mode->height);
 
 	__v4l2_ctrl_modify_range(imx290->hblank, hblank_min, hblank_max, 1,
 				 hblank_min);
 	__v4l2_ctrl_modify_range(imx290->vblank, vblank_min, vblank_max, 1,
 				 vblank_min);
+	__v4l2_ctrl_modify_range(imx290->vtotal, mode->vmax_min,
+				 IMX290_VMAX_MAX, 1, mode->vmax_min);
 }
 
 static int imx290_ctrl_init(struct imx290 *imx290)
@@ -947,7 +967,7 @@ static int imx290_ctrl_init(struct imx290 *imx290)
 
 	/*
 	 * Correct range will be determined through imx290_ctrl_update setting
-	 * V4L2_CID_VBLANK.
+	 * V4L2_CID_VTOTAL.
 	 */
 	imx290->exposure = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
 					     V4L2_CID_EXPOSURE, 1, 65535, 1,
@@ -983,6 +1003,9 @@ static int imx290_ctrl_init(struct imx290 *imx290)
 
 	imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
 					   V4L2_CID_VBLANK, 1, 1, 1, 1);
+	imx290->vtotal = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+					   V4L2_CID_VTOTAL, 1, IMX290_VMAX_MAX,
+					   1, 1);
 
 	imx290->hflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
 					  V4L2_CID_HFLIP, 0, 1, 1, 0);

-- 
2.34.1


  parent reply	other threads:[~2023-06-09 13:16 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-09 13:15 [PATCH 0/2] media: uapi: Add V4L2_CID_VTOTAL control Benjamin Bara
2023-06-09 13:15 ` [PATCH 1/2] " Benjamin Bara
2023-06-09 14:03   ` Dave Stevenson
2023-06-09 13:15 ` Benjamin Bara [this message]
2023-06-09 14:21   ` [PATCH 2/2] media: i2c: imx290: Add support for V4L2_CID_VTOTAL Dave Stevenson
2023-06-09 14:56     ` Benjamin Bara
2023-06-09 15:41       ` Dave Stevenson
2023-06-23 23:28         ` Laurent Pinchart

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230609-v4l2-vtotal-v1-2-4b7dee7e073e@skidata.com \
    --to=bbara93@gmail.com \
    --cc=benjamin.bara@skidata.com \
    --cc=jacopo.mondi@ideasonboard.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=mani@kernel.org \
    --cc=mchehab@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).