diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index cd18c6f31023..ed2360347fb4 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -33,6 +33,9 @@ LOG_DEFINE_CATEGORY(IPU3)
 
 static constexpr unsigned int IPU3_BUFFER_COUNT = 4;
 static constexpr unsigned int IPU3_MAX_STREAMS = 3;
+static constexpr unsigned int IPU3_OUTPUT_MAX_WIDTH = 4480;
+static constexpr unsigned int IPU3_OUTPUT_MAX_HEIGHT = 34004;
+static const Size minIPU3OutputSize = { 2, 2 };
 
 class IPU3CameraData : public CameraData
 {
@@ -295,15 +298,19 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,
 {
 	IPU3CameraData *data = cameraData(camera);
 	IPU3CameraConfiguration *config = new IPU3CameraConfiguration(camera, data);
+	CIO2Device *cio2 = &data->cio2_;
 
 	if (roles.empty())
 		return config;
 
-	Size sensorResolution = data->cio2_.sensor()->resolution();
+	Size sensorResolution = cio2->sensor()->resolution();
 	unsigned int rawCount = 0;
 	unsigned int outCount = 0;
 	for (const StreamRole role : roles) {
-		StreamConfiguration cfg = {};
+		std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
+		unsigned int bufferCount;
+		PixelFormat pixelFormat;
+		Size size;
 
 		switch (role) {
 		case StreamRole::StillCapture:
@@ -311,19 +318,29 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,
 			 * Use the sensor resolution adjusted to respect the
 			 * ImgU output alignement contraints.
 			 */
-			cfg.pixelFormat = formats::NV12;
-			cfg.size = sensorResolution;
-			cfg.size.width &= ~7;
-			cfg.size.height &= ~3;
-			cfg.bufferCount = IPU3_BUFFER_COUNT;
+			pixelFormat = formats::NV12;
+			size.width = std::min(sensorResolution.width,
+					      IPU3_OUTPUT_MAX_WIDTH);
+			size.height = std::min(sensorResolution.height,
+					       IPU3_OUTPUT_MAX_HEIGHT);
+			size.width &= ~7;
+			size.height &= ~3;
+			bufferCount = IPU3_BUFFER_COUNT;
+			streamFormats[pixelFormat] = { { minIPU3OutputSize, size } };
 
 			outCount++;
 
 			break;
 
 		case StreamRole::StillCaptureRaw: {
-			cfg = data->cio2_.generateConfiguration(sensorResolution);
-			cfg.bufferCount = 1;
+			StreamConfiguration cio2Config =
+				cio2->generateConfiguration(sensorResolution);
+			pixelFormat = cio2Config.pixelFormat;
+			size = cio2Config.size;
+			bufferCount = cio2Config.bufferCount;
+
+			for (const PixelFormat &format : cio2->formats())
+				streamFormats[format] = cio2->sizes();
 
 			rawCount++;
 
@@ -339,9 +356,10 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,
 			 */
 			unsigned int width = std::min(1280U, sensorResolution.width);
 			unsigned int height = std::min(720U, sensorResolution.height);
-			cfg.size = { width & ~7, height & ~3 };
-			cfg.pixelFormat = formats::NV12;
-			cfg.bufferCount = IPU3_BUFFER_COUNT;
+			size = { width & ~7, height & ~3 };
+			pixelFormat = formats::NV12;
+			bufferCount = IPU3_BUFFER_COUNT;
+			streamFormats[pixelFormat] = { { minIPU3OutputSize, size } };
 
 			outCount++;
 
@@ -361,6 +379,11 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,
 			return nullptr;
 		}
 
+		StreamFormats formats(streamFormats);
+		StreamConfiguration cfg(formats);
+		cfg.size = size;
+		cfg.pixelFormat = pixelFormat;
+		cfg.bufferCount = bufferCount;
 		config->addConfiguration(cfg);
 	}
 
