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;
