diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 418301b33a5e..f1329ffb0463 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -41,6 +41,7 @@ static constexpr unsigned int IMGU_OUTPUT_WIDTH_ALIGN = 64;
 static constexpr unsigned int IMGU_OUTPUT_HEIGHT_ALIGN = 4;
 static constexpr unsigned int IMGU_OUTPUT_WIDTH_MARGIN = 64;
 static constexpr unsigned int IMGU_OUTPUT_HEIGHT_MARGIN = 32;
+static constexpr Size IPU3ViewfinderSize(1280, 720);
 
 static const ControlInfoMap::Map IPU3Controls = {
 	{ &controls::draft::PipelineDepth, ControlInfo(2, 3) },
@@ -378,7 +379,7 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,
 			 * capped to the maximum sensor resolution and aligned
 			 * to the ImgU output constraints.
 			 */
-			size = sensorResolution.boundedTo({ 1280, 720 })
+			size = sensorResolution.boundedTo(IPU3ViewfinderSize)
 					       .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,
 							      IMGU_OUTPUT_HEIGHT_ALIGN);
 			pixelFormat = formats::NV12;
@@ -785,7 +786,7 @@ int PipelineHandlerIPU3::initProperties(IPU3CameraData *data)
  */
 int PipelineHandlerIPU3::initControls(IPU3CameraData *data)
 {
-	const CameraSensor *sensor = data->cio2_.sensor();
+	CameraSensor *sensor = data->cio2_.sensor();
 	CameraSensorInfo sensorInfo{};
 
 	int ret = sensor->sensorInfo(&sensorInfo);
@@ -822,6 +823,54 @@ int PipelineHandlerIPU3::initControls(IPU3CameraData *data)
 	controls[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure,
 							defExposure);
 
+	/*
+	 * Compute the scaler crop limits.
+	 *
+	 * \todo The scaler crop limits depend on the sensor configuration.  It
+	 * should be updated when a new configuration is applied.  To initialize
+	 * the control use the 'Viewfinder' configuration (1280x720) as the
+	 * pipeline output resolution and the full sensor size as input frame
+	 * (see the todo note in the validation function).
+	 */
+
+	/*
+	 * The maximum scaler crop rectangle is the analogue crop used to
+	 * produce the maximum frame size.
+	 */
+	V4L2SubdeviceFormat sensorFormat;
+	sensorFormat.size = sensor->resolution();
+	ret = sensor->setFormat(&sensorFormat);
+	if (ret)
+		return ret;
+
+	/* Re-fetch the sensor info updated to use the largest resolution. */
+	ret = sensor->sensorInfo(&sensorInfo);
+	if (ret)
+		return ret;
+
+	const Rectangle &analogueCrop = sensorInfo.analogCrop;
+	Rectangle maxCrop = analogueCrop;
+
+	/*
+	 * The minimum crop rectangle is the default viewfinder configuration
+	 * (or the sensor resolution, if smaller) re-scaled in the sensor's pixel
+	 * array coordinates. As the ImgU cannot up-scale, the minimum selection
+	 * rectangle has to be as large as the desired pipeline output size.
+	 *
+	 * The top-left corner position is not relevant as the minimum crop
+	 * rectangle can be placed anywhere inside the analogue crop region.
+	 */
+	const Size &sensorOutput = sensorInfo.outputSize;
+	Size minCropSize = sensorOutput.boundedTo(IPU3ViewfinderSize)
+				       .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,
+						      IMGU_OUTPUT_HEIGHT_ALIGN);
+	Rectangle minCrop(minCropSize);
+	minCrop.scaledBy(analogueCrop.size(), sensorOutput);
+	minCrop.x = analogueCrop.x;
+	minCrop.y = analogueCrop.y;
+
+	controls[&controls::ScalerCrop] = ControlInfo(minCrop, maxCrop, maxCrop);
+
 	data->controlInfo_ = std::move(controls);
 
 	return 0;
