diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 75ffdc56d157..70a92783076f 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -227,36 +227,89 @@ CameraConfiguration
 PipelineHandlerIPU3::streamConfiguration(Camera *camera,
 					 const std::vector<StreamUsage> &usages)
 {
-	CameraConfiguration configs;
 	IPU3CameraData *data = cameraData(camera);
-	StreamConfiguration config = {};
+	CameraConfiguration configs;
+	std::vector<IPU3Stream *> availableStreams = {
+		&data->outStream_,
+		&data->vfStream_,
+	};
 
-	/*
-	 * FIXME: Soraka: the maximum resolution reported by both sensors
-	 * (2592x1944 for ov5670 and 4224x3136 for ov13858) are returned as
-	 * default configurations but they're not correctly processed by the
-	 * ImgU. Resolutions up tp 2560x1920 have been validated.
-	 *
-	 * \todo Clarify ImgU alignement requirements.
-	 */
-	config.width = 2560;
-	config.height = 1920;
-	config.pixelFormat = V4L2_PIX_FMT_NV12;
-	config.bufferCount = IPU3_BUFFER_COUNT;
-
-	configs[&data->outStream_] = config;
-	LOG(IPU3, Debug)
-		<< "Stream 'output' format set to " << config.width << "x"
-		<< config.height << "-0x" << std::hex << std::setfill('0')
-		<< std::setw(8) << config.pixelFormat;
-
-	configs[&data->vfStream_] = config;
-	LOG(IPU3, Debug)
-		<< "Stream 'viewfinder' format set to " << config.width << "x"
-		<< config.height << "-0x" << std::hex << std::setfill('0')
-		<< std::setw(8) << config.pixelFormat;
+	for (const StreamUsage &usage : usages) {
+		std::vector<IPU3Stream *>::iterator found;
+		enum StreamUsage::Role r = usage.role();
+		StreamConfiguration config = {};
+		IPU3Stream *stream = nullptr;
+
+		std::vector<IPU3Stream *>::iterator s = availableStreams.begin();
+		if (r == StreamUsage::Role::StillCapture) {
+			for (; s < availableStreams.end(); ++s) {
+				/*
+				 * We can use the viewfinder stream in case
+				 * the 'StillCapture' usage is required
+				 * multiple times.
+				 */
+				if (*s == &data->outStream_) {
+					stream = &data->outStream_;
+					found = s;
+					break;
+				} else {
+					stream = &data->vfStream_;
+					found = s;
+				}
+			}
+
+			/*
+			 * FIXME: Soraka: the maximum resolution reported by
+			 * both sensors (2592x1944 for ov5670 and 4224x3136 for
+			 * ov13858) are returned as default configurations but
+			 * they're not correctly processed by the ImgU.
+			 * Resolutions up tp 2560x1920 have been validated.
+			 *
+			 * \todo Clarify ImgU alignment requirements.
+			 */
+			config.width = 2560;
+			config.height = 1920;
+		} else if (r == StreamUsage::Role::Viewfinder ||
+			   r == StreamUsage::Role::VideoRecording) {
+			for (; s < availableStreams.end(); ++s) {
+				/*
+				 * We can't use the 'output' stream for
+				 * viewfinder or video capture usages.
+				 */
+				if (*s != &data->vfStream_)
+					continue;
+
+				stream = &data->vfStream_;
+				found = s;
+				break;
+			}
+
+			config.width = 640;
+			config.height = 480;
+		}
+
+		if (stream == nullptr)
+			goto error;
+
+		availableStreams.erase(found);
+
+		config.pixelFormat = V4L2_PIX_FMT_NV12;
+		config.bufferCount = IPU3_BUFFER_COUNT;
+
+		configs[stream] = config;
+
+		LOG(IPU3, Debug)
+			<< "Stream " << stream->name_ << " format set to "
+			<< config.width << "x" << config.height
+			<< "-0x" << std::hex << std::setfill('0')
+			<< std::setw(8) << config.pixelFormat;
+	}
 
 	return configs;
+
+error:
+	LOG(IPU3, Error) << "Requested stream roles not supported";
+	return CameraConfiguration{};
 }
 
 int PipelineHandlerIPU3::configureStreams(Camera *camera,
