[1/3] ipa: rkisp1: Update exposure limits on vblank change
diff mbox series

Message ID 20251017-exposure-limits-v1-1-6288cd86e719@ideasonboard.com
State New
Headers show
Series
  • rkisp1: Update exposure limits on vblank change
Related show

Commit Message

Jacopo Mondi Oct. 17, 2025, 9 a.m. UTC
The AGC algorithm implementation of the RkISP1 IPA is implemented
deriving the generic AgcMeanLuminance class, which limits the
achievable exposure time using a maxExposureTime parameter provided by
the IPA module.

The RkISP1 IPA fetches the maxExposureTime value from the IPAContext
sensor.maxExposureTime value, which is initialized at IPA init()
and configure() time, but never updated later on, effectively limiting
the achievable exposure time to the frame duration programmed at
startup time.

Whenever the frame duration is changed, the maximum exposure time
should change accordingly, but in the current implementation this
doesn't happen.

Fix this by updating the sensor.maxExposureTime value when a new set of
controls is sent to the pipeline handler. Store the current VBLANK value
in the IPAContext by replacing 'defVBlank' which is never used and use
it to detect changes in the blanking value. Whenever the blanking
changes, update the maximum exposure limit accordingly.

As reported in a comment in the code, even if the new sensor controls
will be programmed in the sensor with a delay of a few frames on the
pipeline handler side, the limits for the algorithms should be updated
immediately.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 src/ipa/rkisp1/ipa_context.h |  2 +-
 src/ipa/rkisp1/rkisp1.cpp    | 31 ++++++++++++++++++++++++++++---
 2 files changed, 29 insertions(+), 4 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index f85a130d9c23dba7987f388e395239e4b141d776..af66a749052bc82bbbe7fbb0c4626f2422700926 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -65,7 +65,7 @@  struct IPASessionConfiguration {
 		double minAnalogueGain;
 		double maxAnalogueGain;
 
-		int32_t defVBlank;
+		unsigned int vBlank;
 		utils::Duration lineDuration;
 		Size size;
 	} sensor;
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index fa22bfc349043002345d275b11a60ac983e329d7..54bd1434e0f4e34834beb1f9e9c39b77590f8b34 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -250,7 +250,7 @@  int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
 
 	const IPACameraSensorInfo &info = ipaConfig.sensorInfo;
 	const ControlInfo vBlank = sensorControls_.find(V4L2_CID_VBLANK)->second;
-	context_.configuration.sensor.defVBlank = vBlank.def().get<int32_t>();
+	context_.configuration.sensor.vBlank = vBlank.def().get<int32_t>();
 	context_.configuration.sensor.size = info.outputSize;
 	context_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate;
 
@@ -261,8 +261,6 @@  int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
 	 * When the AGC computes the new exposure values for a frame, it needs
 	 * to know the limits for exposure time and analogue gain. As it depends
 	 * on the sensor, update it with the controls.
-	 *
-	 * \todo take VBLANK into account for maximum exposure time
 	 */
 	context_.configuration.sensor.minExposureTime =
 		minExposure * context_.configuration.sensor.lineDuration;
@@ -457,6 +455,33 @@  void IPARkISP1::setControls(unsigned int frame)
 	uint32_t gain = context_.camHelper->gainCode(frameContext.agc.gain);
 	uint32_t vblank = frameContext.agc.vblank;
 
+	/*
+	 * Update the exposure limits if vblank has changed. Even if the controls
+	 * will actually be applied to the sensor with some frames of latency
+	 * by DelayedControls, all the algorithms calculations from now on should
+	 * use the new limits.
+	 *
+	 * \todo Sensors usually have a margin that limits the max exposure to
+	 * be shorter by the full frame length:
+	 *
+	 * (max_exposure_lines = height + vblank - margin)
+	 *
+	 * As the margin is a sensor-specific parameter either:
+	 * - Ignore the margin and rely on the driver clamping the exposure
+	 *   value correctly
+	 * - Defer to the sensor helpers by creating an exposure() function that
+	 *   subtract the margin from the frame length
+	 *
+	 * For the time being ignore the margins and rely on the driver doing
+	 * the adjustment.
+	 */
+	if (vblank != context_.configuration.sensor.vBlank) {
+		context_.configuration.sensor.vBlank = vblank;
+		context_.configuration.sensor.maxExposureTime =
+			(vblank + context_.configuration.sensor.size.height) *
+			context_.configuration.sensor.lineDuration;
+	}
+
 	LOG(IPARkISP1, Debug)
 		<< "Set controls for frame " << frame << ": exposure " << exposure
 		<< ", gain " << frameContext.agc.gain << ", vblank " << vblank;