diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index f1329ffb0463..381524bb3499 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -66,6 +66,7 @@ public:
 	Stream rawStream_;
 
 	int32_t exposureTime_;
+	Rectangle scalerCrop_;
 };
 
 class IPU3CameraConfiguration : public CameraConfiguration
@@ -75,6 +76,7 @@ public:
 
 	Status validate() override;
 
+	const Size &cio2Size() const { return cio2Configuration_.size; }
 	const StreamConfiguration &cio2Format() const { return cio2Configuration_; }
 	const ImgUDevice::PipeConfig imguConfig() const { return pipeConfig_; }
 
@@ -468,12 +470,19 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)
 	 * Pass the requested stream size to the CIO2 unit and get back the
 	 * adjusted format to be propagated to the ImgU output devices.
 	 */
-	const Size &sensorSize = config->cio2Format().size;
 	V4L2DeviceFormat cio2Format;
-	ret = cio2->configure(sensorSize, &cio2Format);
+	ret = cio2->configure(config->cio2Size(), &cio2Format);
 	if (ret)
 		return ret;
 
+	/* Initialize the scaler crop using the sensor's analogue crop. */
+	CameraSensorInfo sensorInfo;
+	ret = cio2->sensor()->sensorInfo(&sensorInfo);
+	if (ret)
+		/* Use the requested CIO2 output size as fallback. */
+		sensorInfo.analogCrop = Rectangle(config->cio2Size());
+	data->scalerCrop_ = sensorInfo.analogCrop;
+
 	/*
 	 * If the ImgU gets configured, its driver seems to expect that
 	 * buffers will be queued to its outputs, as otherwise the next
@@ -656,6 +665,14 @@ int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request)
 	IPU3CameraData *data = cameraData(camera);
 	int error = 0;
 
+	ControlList &controls = request->controls();
+	if (controls.contains(controls::ScalerCrop))
+		/*
+		 * \todo No scaling is applied. Just return the value in the
+		 * request metadata as it is.
+		 */
+		data->scalerCrop_ = controls.get(controls::ScalerCrop);
+
 	/*
 	 * Queue a buffer on the CIO2, using the raw stream buffer provided in
 	 * the request, if any, or a CIO2 internal buffer otherwise.
@@ -991,6 +1008,7 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)
 	/* Mark the request as complete. */
 	request->metadata().set(controls::draft::PipelineDepth, 3);
 	request->metadata().set(controls::ExposureTime, exposureTime_);
+	request->metadata().set(controls::ScalerCrop, scalerCrop_);
 	pipe_->completeRequest(request);
 }
 
