media: i2c: ov9282: dynamic flash_duration maximum

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>
This commit is contained in:
Richard Leitner
2025-12-09 23:44:43 +01:00
committed by Hans Verkuil
parent b95d8058a2
commit df60764ea5

View 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) {