]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: i2c: ov9282: dynamic flash_duration maximum
authorRichard Leitner <richard.leitner@linux.dev>
Tue, 9 Dec 2025 22:44:43 +0000 (23:44 +0100)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Fri, 16 Jan 2026 13:08:53 +0000 (14:08 +0100)
This patch sets the current exposure time as maximum for the
flash_duration control. As Flash/Strobes which are longer than the
exposure time have no effect.

Signed-off-by: Richard Leitner <richard.leitner@linux.dev>
[Sakari Ailus: Some lines rewrapped.]
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/i2c/ov9282.c

index 3c74d65fe3125daf7e405f84743a37cf5e84d7a2..ded9b2044ff8fbaeaf96b6f3f923647fda36f7b8 100644 (file)
@@ -199,6 +199,7 @@ struct ov9282_mode {
  * @exp_ctrl: Pointer to exposure control
  * @again_ctrl: Pointer to analog gain control
  * @pixel_rate: Pointer to pixel rate control
+ * @flash_duration: Pointer to flash duration control
  * @vblank: Vertical blanking in lines
  * @noncontinuous_clock: Selection of CSI2 noncontinuous clock mode
  * @cur_mode: Pointer to current selected sensor mode
@@ -221,6 +222,7 @@ struct ov9282 {
                struct v4l2_ctrl *again_ctrl;
        };
        struct v4l2_ctrl *pixel_rate;
+       struct v4l2_ctrl *flash_duration;
        u32 vblank;
        bool noncontinuous_clock;
        const struct ov9282_mode *cur_mode;
@@ -612,6 +614,15 @@ static int ov9282_update_controls(struct ov9282 *ov9282,
                                        mode->vblank_max, 1, mode->vblank);
 }
 
+static u32 ov9282_exposure_to_us(struct ov9282 *ov9282, u32 exposure)
+{
+       /* calculate exposure time in µs */
+       u32 frame_width = ov9282->cur_mode->width + ov9282->hblank_ctrl->val;
+       u32 trow_us = frame_width / (ov9282->pixel_rate->val / 1000000UL);
+
+       return exposure * trow_us;
+}
+
 /**
  * ov9282_update_exp_gain() - Set updated exposure and gain
  * @ov9282: pointer to ov9282 device
@@ -623,9 +634,10 @@ static int ov9282_update_controls(struct ov9282 *ov9282,
 static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
 {
        int ret;
+       u32 exposure_us = ov9282_exposure_to_us(ov9282, exposure);
 
-       dev_dbg(ov9282->dev, "Set exp %u, analog gain %u",
-               exposure, gain);
+       dev_dbg(ov9282->dev, "Set exp %u (~%u us), analog gain %u",
+               exposure, exposure_us, gain);
 
        ret = ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 1);
        if (ret)
@@ -636,6 +648,12 @@ static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
                goto error_release_group_hold;
 
        ret = ov9282_write_reg(ov9282, OV9282_REG_AGAIN, 1, gain);
+       if (ret)
+               goto error_release_group_hold;
+
+       ret = __v4l2_ctrl_modify_range(ov9282->flash_duration,
+                                      0, exposure_us, 1,
+                                      OV9282_STROBE_FRAME_SPAN_DEFAULT);
 
 error_release_group_hold:
        ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 0);
@@ -1431,6 +1449,7 @@ static int ov9282_init_controls(struct ov9282 *ov9282)
        const struct ov9282_mode *mode = ov9282->cur_mode;
        struct v4l2_fwnode_device_properties props;
        u32 hblank_min;
+       u32 exposure_us;
        u32 lpfr;
        int ret;
 
@@ -1503,8 +1522,11 @@ static int ov9282_init_controls(struct ov9282 *ov9282)
        v4l2_ctrl_new_std(ctrl_hdlr, &ov9282_ctrl_ops,
                          V4L2_CID_FLASH_STROBE_OE, 0, 1, 1, 0);
 
-       v4l2_ctrl_new_std(ctrl_hdlr, &ov9282_ctrl_ops, V4L2_CID_FLASH_DURATION,
-                         0, 13900, 1, 8);
+       exposure_us = ov9282_exposure_to_us(ov9282, OV9282_EXPOSURE_DEFAULT);
+       ov9282->flash_duration =
+               v4l2_ctrl_new_std(ctrl_hdlr, &ov9282_ctrl_ops,
+                                 V4L2_CID_FLASH_DURATION, 0, exposure_us, 1,
+                                 OV9282_STROBE_FRAME_SPAN_DEFAULT);
 
        ret = v4l2_fwnode_device_parse(ov9282->dev, &props);
        if (!ret) {