diff --git a/src/libcamera/pipeline/ipu3/frames.h b/src/libcamera/pipeline/ipu3/frames.h
index 3ef7e445..614701e2 100644
--- a/src/libcamera/pipeline/ipu3/frames.h
+++ b/src/libcamera/pipeline/ipu3/frames.h
@@ -14,6 +14,8 @@
 
 #include <libcamera/base/signal.h>
 
+#include <libcamera/controls.h>
+
 namespace libcamera {
 
 class FrameBuffer;
@@ -34,6 +36,8 @@ public:
 		FrameBuffer *paramBuffer;
 		FrameBuffer *statBuffer;
 
+		ControlList effectiveSensorControls;
+
 		bool paramDequeued;
 		bool metadataProcessed;
 	};
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 8816efc5..3fcfa777 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -767,6 +767,12 @@ int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] const ControlLis
 	if (ret)
 		goto error;
 
+	/*
+	 * Reset the delayed controls with the gain and exposure values set by
+	 * the IPA.
+	 */
+	data->delayedCtrls_->reset();
+
 	/*
 	 * Start the ImgU video devices, buffers will be queued to the
 	 * ImgU output and viewfinder when requests will be queued.
@@ -1363,6 +1369,8 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
 	request->metadata().set(controls::SensorTimestamp,
 				buffer->metadata().timestamp);
 
+	info->effectiveSensorControls = delayedCtrls_->get(buffer->metadata().sequence);
+
 	if (request->findBuffer(&rawStream_))
 		pipe()->completeBuffer(request, buffer);
 
@@ -1419,6 +1427,7 @@ void IPU3CameraData::statBufferReady(FrameBuffer *buffer)
 	ev.frame = info->id;
 	ev.bufferId = info->statBuffer->cookie();
 	ev.frameTimestamp = request->metadata().get(controls::SensorTimestamp);
+	ev.sensorControls = info->effectiveSensorControls;
 	ipa_->processEvent(ev);
 }
 
