diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 329b9d51cf1b..50b03008c0fb 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -754,6 +754,7 @@ int PipelineHandlerIPU3::initControls(IPU3CameraData *data)
 		return ret;
 
 	ControlInfoMap::Map controls = IPU3Controls;
+	const ControlInfoMap &sensorControls = sensor->controls();
 
 	/*
 	 * Compute exposure time limits.
@@ -766,7 +767,6 @@ int PipelineHandlerIPU3::initControls(IPU3CameraData *data)
 	 */
 	double lineDuration = sensorInfo.lineLength
 			    / (sensorInfo.pixelRate / 1e6f);
-	const ControlInfoMap &sensorControls = sensor->controls();
 	const ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;
 	int32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;
 	int32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;
@@ -781,6 +781,39 @@ int PipelineHandlerIPU3::initControls(IPU3CameraData *data)
 	controls[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure,
 							defExposure);
 
+	/*
+	 * Compute the frame duration limits.
+	 *
+	 * \todo The frame duration limits depend on the sensor configuration.
+	 * Initialize the control using the frame sizes and pixel rate of the
+	 * current configuration.
+	 *
+	 * The frame length is computed assuming a fixed line length combined
+	 * with the vertical frame sizes.
+	 */
+	const ControlInfo &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second;
+	uint32_t hblank = v4l2HBlank.def().get<int32_t>();
+	uint32_t lineLength = sensorInfo.outputSize.width + hblank;
+
+	const ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second;
+	std::array<uint32_t, 3> frameHeights{
+		(v4l2VBlank.min().get<int32_t>() + sensorInfo.outputSize.height),
+		(v4l2VBlank.max().get<int32_t>() + sensorInfo.outputSize.height),
+		(v4l2VBlank.def().get<int32_t>() + sensorInfo.outputSize.height),
+	};
+
+	std::vector<int64_t> frameDurations;
+	frameDurations.reserve(3);
+	std::transform(frameHeights.begin(), frameHeights.end(),
+		       std::back_inserter(frameDurations),
+		       [&](int32_t frameHeight) {
+			       int64_t frameSize = lineLength * frameHeight;
+			       return frameSize / (sensorInfo.pixelRate / 1000000U);
+		       });
+	controls[&controls::FrameDurations] = ControlInfo(frameDurations[0],
+							  frameDurations[1],
+							  frameDurations[2]);
+
 	/*
 	 * Compute the scaler crop limits.
 	 *
