diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp
index 195de2f2e93ce229b8047909b949e1d06ef8d5bf..1098865519ca9ca2679331edd9441720366c717d 100644
--- a/src/ipa/libipa/agc_mean_luminance.cpp
+++ b/src/ipa/libipa/agc_mean_luminance.cpp
@@ -453,6 +453,7 @@ int AgcMeanLuminance::parseTuningData(const YamlObject &tuningData)
  * \brief Set the ExposureModeHelper limits for this class
  * \param[in] minExposureTime Minimum exposure time to allow
  * \param[in] maxExposureTime Maximum ewposure time to allow
+ * \param[in] maxFrameDuration Maximum frame duration
  * \param[in] minGain Minimum gain to allow
  * \param[in] maxGain Maximum gain to allow
  * \param[in] constraints Additional constraints to apply
@@ -462,11 +463,13 @@ int AgcMeanLuminance::parseTuningData(const YamlObject &tuningData)
  */
 void AgcMeanLuminance::setLimits(utils::Duration minExposureTime,
 				 utils::Duration maxExposureTime,
+				 utils::Duration maxFrameDuration,
 				 double minGain, double maxGain,
 				 std::vector<AgcMeanLuminance::AgcConstraint> constraints)
 {
 	for (auto &[id, helper] : exposureModeHelpers_)
-		helper->setLimits(minExposureTime, maxExposureTime, minGain, maxGain);
+		helper->setLimits(minExposureTime, maxExposureTime, maxFrameDuration,
+				  minGain, maxGain);
 
 	additionalConstraints_ = std::move(constraints);
 }
diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h
index c3d52c0b1cba23af14135dace8b3c13da4ae3e4b..0f7a4f53188d8d2759076c37d186efc088ddd279 100644
--- a/src/ipa/libipa/agc_mean_luminance.h
+++ b/src/ipa/libipa/agc_mean_luminance.h
@@ -61,7 +61,8 @@ public:
 	}
 
 	void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime,
-		       double minGain, double maxGain, std::vector<AgcConstraint> constraints);
+		       utils::Duration maxFrameDuration, double minGain, double maxGain,
+		       std::vector<AgcConstraint> constraints);
 
 	std::map<int32_t, std::vector<AgcConstraint>> constraintModes()
 	{
diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp
index 8f40290959e24294ead008c7228e2f67ffc5adf8..d1d94cf46d5ef2c077508fd94dfe9715fdbc6f03 100644
--- a/src/ipa/libipa/exposure_mode_helper.cpp
+++ b/src/ipa/libipa/exposure_mode_helper.cpp
@@ -79,6 +79,33 @@ ExposureModeHelper::ExposureModeHelper(const Span<std::pair<utils::Duration, dou
 	}
 }
 
+void ExposureModeHelper::setMaxExposure(utils::Duration minExposureTime,
+					utils::Duration maxExposureTime,
+					utils::Duration maxFrameDuration)
+{
+	/*
+	 * Compute the maximum exposure time.
+	 *
+	 * If maxExposureTime is equal to minExposureTime then we use them
+	 * to fix the exposure time.
+	 *
+	 * Otherwise, if the exposure can range between a min and max, use the
+	 * maxFrameDuration minus the margin as upper limit for exposure
+	 * (capped to the provided max exposure).
+	 */
+	minExposureTime_ = minExposureTime;
+	auto margin = sensorHelper_->exposureMargin();
+	if (!margin.has_value()) {
+		LOG(ExposureModeHelper, Warning)
+			<< "Exposure margin not known. Default to 4";
+		margin = { 4 };
+	}
+
+	maxExposureTime_ = minExposureTime != maxExposureTime
+			 ? maxFrameDuration - margin.value() * lineDuration_
+			 : minExposureTime;
+}
+
 /**
  * \brief Configure sensor details
  * \param[in] lineDuration The current line length of the sensor
@@ -111,34 +138,14 @@ void ExposureModeHelper::configure(utils::Duration lineDuration,
 	maxGain_ = maxGain;
 	sensorHelper_ = sensorHelper;
 
-	minExposureTime_ = minExposureTime;
-
-	/*
-	 * Compute the maximum exposure time.
-	 *
-	 * If maxExposureTime is equal to minExposureTime then we use them
-	 * to fix the exposure time.
-	 *
-	 * Otherwise, if the exposure can range between a min and max, use the
-	 * maxFrameDuration minus the margin as upper limit for exposure
-	 * (capped to the provided max exposure).
-	 */
-	auto margin = sensorHelper_->exposureMargin();
-	if (!margin.has_value()) {
-		LOG(ExposureModeHelper, Warning)
-			<< "Exposure margin not known. Default to 4";
-		margin = { 4 };
-	}
-
-	maxExposureTime_ = minExposureTime != maxExposureTime
-			 ? maxFrameDuration - margin.value() * lineDuration
-			 : minExposureTime;
+	setMaxExposure(minExposureTime, maxExposureTime, maxFrameDuration);
 }
 
 /**
  * \brief Set the exposure time and gain limits
  * \param[in] minExposureTime The minimum exposure time supported
  * \param[in] maxExposureTime The maximum exposure time supported
+ * \param[in] maxFrameDuration The maximum frame duration
  * \param[in] minGain The minimum analogue gain supported
  * \param[in] maxGain The maximum analogue gain supported
  *
@@ -150,15 +157,19 @@ void ExposureModeHelper::configure(utils::Duration lineDuration,
  * If the algorithm using the helpers needs to indicate that either exposure time
  * or analogue gain or both should be fixed it can do so by setting both the
  * minima and maxima to the same value.
+ *
+ * The exposure time limits are calculated using \a maxFrameDuration as the
+ * upper bound, the \a maxExposureTime paramter effectivelly only serves
+ * to indicate that the caller wants a fixed exposure value.
  */
 void ExposureModeHelper::setLimits(utils::Duration minExposureTime,
 				   utils::Duration maxExposureTime,
+				   utils::Duration maxFrameDuration,
 				   double minGain, double maxGain)
 {
-	minExposureTime_ = minExposureTime;
-	maxExposureTime_ = maxExposureTime;
 	minGain_ = minGain;
 	maxGain_ = maxGain;
+	setMaxExposure(minExposureTime, maxExposureTime, maxFrameDuration);
 }
 
 utils::Duration ExposureModeHelper::clampExposureTime(utils::Duration exposureTime,
diff --git a/src/ipa/libipa/exposure_mode_helper.h b/src/ipa/libipa/exposure_mode_helper.h
index 8a7d2161912d318c2d1c5c8d009edc8a2d0c0427..b1de96d4a3a13e3771ff2162f11201e5f9253265 100644
--- a/src/ipa/libipa/exposure_mode_helper.h
+++ b/src/ipa/libipa/exposure_mode_helper.h
@@ -31,7 +31,7 @@ public:
 		       double minGain, double maxGain,
 		       const CameraSensorHelper *sensorHelper);
 	void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime,
-		       double minGain, double maxGain);
+		       utils::Duration maxFrameDuration, double minGain, double maxGain);
 
 	std::tuple<utils::Duration, double, double, double>
 	splitExposure(utils::Duration exposure) const;
@@ -43,6 +43,9 @@ public:
 	double maxGain() const { return maxGain_; }
 
 private:
+	void setMaxExposure(utils::Duration minExposureTime,
+			    utils::Duration maxExposureTime,
+			    utils::Duration maxFrameDuration);
 	utils::Duration clampExposureTime(utils::Duration exposureTime,
 					  double *quantizationGain = nullptr) const;
 	double clampGain(double gain, double *quantizationGain = nullptr) const;
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index 121e75449a6985f951c50fdc85b0298026344297..96189254885c47d29b92f3fb40f0e86d10e2a7fc 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -579,9 +579,7 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 
 	if (frameContext.agc.autoExposureEnabled) {
 		minExposureTime = context.configuration.sensor.minExposureTime;
-		maxExposureTime = std::clamp(frameContext.agc.maxFrameDuration,
-					     context.configuration.sensor.minExposureTime,
-					     context.configuration.sensor.maxExposureTime);
+		maxExposureTime = context.configuration.sensor.maxExposureTime;
 	} else {
 		minExposureTime = context.configuration.sensor.lineDuration
 				* frameContext.agc.exposure;
@@ -600,8 +598,8 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 	if (context.activeState.wdr.mode != controls::WdrOff)
 		additionalConstraints.push_back(context.activeState.wdr.constraint);
 
-	setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain,
-		  std::move(additionalConstraints));
+	setLimits(minExposureTime, maxExposureTime, frameContext.agc.maxFrameDuration,
+		  minAnalogueGain, maxAnalogueGain, std::move(additionalConstraints));
 
 	/*
 	 * The Agc algorithm needs to know the effective exposure value that was
