diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index b9f4d7867854..ce3a790f00ee 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -54,6 +54,7 @@ public:
 	V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
 				      const Size &size) const;
 	int setFormat(V4L2SubdeviceFormat *format);
+	int tryFormat(V4L2SubdeviceFormat *format) const;
 
 	const ControlInfoMap &controls() const;
 	ControlList getControls(const std::vector<uint32_t> &ids);
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index a210aa4fa370..dfe593033def 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -757,6 +757,20 @@ int CameraSensor::setFormat(V4L2SubdeviceFormat *format)
 	return 0;
 }
 
+/**
+ * \brief Try the sensor output format
+ * \param[in] format The desired sensor output format
+ *
+ * The ranges of any controls associated with the sensor are not updated.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int CameraSensor::tryFormat(V4L2SubdeviceFormat *format) const
+{
+	return subdev_->setFormat(pad_, format,
+				  V4L2Subdevice::Whence::TryFormat);
+}
+
 /**
  * \brief Retrieve the supported V4L2 controls and their information
  *
diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
index 5976a63d27dd..0e1e87c7a2aa 100644
--- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
+++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
@@ -145,6 +145,10 @@ private:
 
 	Pipe *pipeFromStream(Camera *camera, const Stream *stream);
 
+	StreamConfiguration generateYUVConfiguration(Camera *camera,
+						     const Size &size);
+	StreamConfiguration generateRawConfiguration(Camera *camera);
+
 	void bufferReady(FrameBuffer *buffer);
 
 	MediaDevice *isiDev_;
@@ -705,6 +709,129 @@ PipelineHandlerISI::PipelineHandlerISI(CameraManager *manager)
 {
 }
 
+/*
+ * Generate a StreamConfiguration for YUV/RGB use case.
+ *
+ * Verify it the sensor can produce a YUV/RGB media bus format and collect
+ * all the processed pixel formats the ISI can generate as supported stream
+ * configurations.
+ */
+StreamConfiguration PipelineHandlerISI::generateYUVConfiguration(Camera *camera,
+								 const Size &size)
+{
+	ISICameraData *data = cameraData(camera);
+	PixelFormat pixelFormat = formats::YUYV;
+	unsigned int mbusCode;
+
+	mbusCode = data->getYuvMediaBusFormat(&pixelFormat);
+	if (!mbusCode)
+		return {};
+
+	/* Adjust the requested size to the sensor's capabilities. */
+	const CameraSensor *sensor = data->sensor_.get();
+
+	V4L2SubdeviceFormat sensorFmt;
+	sensorFmt.mbus_code = mbusCode;
+	sensorFmt.size = size;
+
+	int ret = sensor->tryFormat(&sensorFmt);
+	if (ret) {
+		LOG(ISI, Error) << "Failed to try sensor format.";
+		return {};
+	}
+
+	Size sensorSize = sensorFmt.size;
+
+	/*
+	 * Populate the StreamConfiguration.
+	 *
+	 * As the sensor supports at least one YUV/RGB media bus format all the
+	 * processed ones in formatsMap_ can be generated from it.
+	 */
+	std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
+
+	for (const auto &[pixFmt, pipeFmt] : ISICameraConfiguration::formatsMap_) {
+		const PixelFormatInfo &info = PixelFormatInfo::info(pixFmt);
+		if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
+			continue;
+
+		streamFormats[pixFmt] = { { kMinISISize, sensorSize } };
+	}
+
+	StreamFormats formats(streamFormats);
+
+	StreamConfiguration cfg(formats);
+	cfg.pixelFormat = pixelFormat;
+	cfg.size = sensorSize;
+	cfg.bufferCount = 4;
+
+	return cfg;
+}
+
+/*
+ * Generate a StreamConfiguration for Raw Bayer use case. Verify if the sensor
+ * can produce the requested RAW bayer format and eventually adjust it to
+ * the one with the largest bit-depth the sensor can produce.
+ */
+StreamConfiguration PipelineHandlerISI::generateRawConfiguration(Camera *camera)
+{
+	const std::map<unsigned int, PixelFormat> rawFormats = {
+		{ MEDIA_BUS_FMT_SBGGR8_1X8, formats::SBGGR8 },
+		{ MEDIA_BUS_FMT_SGBRG8_1X8, formats::SGBRG8 },
+		{ MEDIA_BUS_FMT_SGRBG8_1X8, formats::SGRBG8 },
+		{ MEDIA_BUS_FMT_SRGGB8_1X8, formats::SRGGB8 },
+		{ MEDIA_BUS_FMT_SBGGR10_1X10, formats::SBGGR10 },
+		{ MEDIA_BUS_FMT_SGBRG10_1X10, formats::SGBRG10 },
+		{ MEDIA_BUS_FMT_SGRBG10_1X10, formats::SGRBG10 },
+		{ MEDIA_BUS_FMT_SRGGB10_1X10, formats::SRGGB10 },
+		{ MEDIA_BUS_FMT_SBGGR12_1X12, formats::SBGGR12 },
+		{ MEDIA_BUS_FMT_SGBRG12_1X12, formats::SGBRG12 },
+		{ MEDIA_BUS_FMT_SGRBG12_1X12, formats::SGRBG12 },
+		{ MEDIA_BUS_FMT_SRGGB12_1X12, formats::SRGGB12 },
+	};
+
+	ISICameraData *data = cameraData(camera);
+	PixelFormat pixelFormat = formats::SBGGR10;
+	unsigned int mbusCode;
+
+	/* pixelFormat will be adjusted, if the sensor can produce RAW. */
+	mbusCode = data->getRawMediaBusFormat(&pixelFormat);
+	if (!mbusCode)
+		return {};
+
+	/*
+	 * Populate the StreamConfiguration with all the supported Bayer
+	 * formats the sensor can produce.
+	 */
+	std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
+	const CameraSensor *sensor = data->sensor_.get();
+
+	for (unsigned int code : sensor->mbusCodes()) {
+		/* Find a Bayer media bus code from the sensor. */
+		const BayerFormat &bayerFormat = BayerFormat::fromMbusCode(code);
+		if (!bayerFormat.isValid())
+			continue;
+
+		auto it = rawFormats.find(code);
+		if (it == rawFormats.end()) {
+			LOG(ISI, Warning) << bayerFormat
+					  << " not supported in ISI formats map.";
+			continue;
+		}
+
+		streamFormats[it->second] = { { kMinISISize, sensor->resolution() } };
+	}
+
+	StreamFormats formats(streamFormats);
+
+	StreamConfiguration cfg(formats);
+	cfg.size = sensor->resolution();
+	cfg.pixelFormat = pixelFormat;
+	cfg.bufferCount = 4;
+
+	return cfg;
+}
+
 std::unique_ptr<CameraConfiguration>
 PipelineHandlerISI::generateConfiguration(Camera *camera,
 					  const StreamRoles &roles)
@@ -722,79 +849,45 @@ PipelineHandlerISI::generateConfiguration(Camera *camera,
 		return nullptr;
 	}
 
-	bool isRaw = false;
 	for (const auto &role : roles) {
 		/*
-		 * Prefer the following formats
+		 * Prefer the following formats:
 		 * - Still Capture: Full resolution YUYV
 		 * - ViewFinder/VideoRecording: 1080p YUYV
-		 * - RAW: sensor's native format and resolution
+		 * - RAW: Full resolution Bayer
 		 */
-		std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
-		PixelFormat pixelFormat;
-		Size size;
+		StreamConfiguration cfg;
 
 		switch (role) {
 		case StreamRole::StillCapture:
-			/*
-			 * \todo Make sure the sensor can produce non-RAW formats
-			 * compatible with the ones supported by the pipeline.
-			 */
-			size = data->sensor_->resolution();
-			pixelFormat = formats::YUYV;
+			cfg = generateYUVConfiguration(camera,
+						       data->sensor_->resolution());
+			if (!cfg.pixelFormat.isValid()) {
+				/*
+				 * Fallback to use a Bayer format if that's what
+				 * the sensor supports.
+				 */
+				cfg = generateRawConfiguration(camera);
+			}
+
 			break;
 
 		case StreamRole::Viewfinder:
 		case StreamRole::VideoRecording:
-			/*
-			 * \todo Make sure the sensor can produce non-RAW formats
-			 * compatible with the ones supported by the pipeline.
-			 */
-			size = PipelineHandlerISI::kPreviewSize;
-			pixelFormat = formats::YUYV;
-			break;
-
-		case StreamRole::Raw: {
-			/*
-			 * Make sure the sensor can generate a RAW format and
-			 * prefer the ones with a larger bitdepth.
-			 */
-			const ISICameraConfiguration::FormatMap::value_type *rawPipeFormat = nullptr;
-			unsigned int maxDepth = 0;
-
-			for (unsigned int code : data->sensor_->mbusCodes()) {
-				const BayerFormat &bayerFormat = BayerFormat::fromMbusCode(code);
-				if (!bayerFormat.isValid())
-					continue;
-
-				/* Make sure the format is supported by the pipeline handler. */
-				auto it = std::find_if(ISICameraConfiguration::formatsMap_.begin(),
-						       ISICameraConfiguration::formatsMap_.end(),
-						       [code](auto &isiFormat) {
-							        auto &pipe = isiFormat.second;
-							        return pipe.sensorCode == code;
-						       });
-				if (it == ISICameraConfiguration::formatsMap_.end())
-					continue;
-
-				if (bayerFormat.bitDepth > maxDepth) {
-					maxDepth = bayerFormat.bitDepth;
-					rawPipeFormat = &(*it);
-				}
-			}
-
-			if (!rawPipeFormat) {
-				LOG(ISI, Error)
-					<< "Cannot generate a configuration for RAW stream";
-				return nullptr;
+			cfg = generateYUVConfiguration(camera,
+						       PipelineHandlerISI::kPreviewSize);
+			if (!cfg.pixelFormat.isValid()) {
+				/*
+				 * Fallback to use a Bayer format if that's what
+				 * the sensor supports.
+				 */
+				cfg = generateRawConfiguration(camera);
 			}
 
-			size = data->sensor_->resolution();
-			pixelFormat = rawPipeFormat->first;
-
-			streamFormats[pixelFormat] = { { kMinISISize, size } };
-			isRaw = true;
+			break;
 
+		case StreamRole::Raw: {
+			cfg = generateRawConfiguration(camera);
 			break;
 		}
 
@@ -803,26 +896,12 @@ PipelineHandlerISI::generateConfiguration(Camera *camera,
 			return nullptr;
 		}
 
-		/*
-		 * For non-RAW configurations the ISI can perform colorspace
-		 * conversion. List all the supported output formats here.
-		 */
-		if (!isRaw) {
-			for (const auto &[pixFmt, pipeFmt] : ISICameraConfiguration::formatsMap_) {
-				const PixelFormatInfo &info = PixelFormatInfo::info(pixFmt);
-				if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
-					continue;
-
-				streamFormats[pixFmt] = { { kMinISISize, size } };
-			}
+		if (!cfg.pixelFormat.isValid()) {
+			LOG(ISI, Error)
+				<< "Cannot generate configuration for role: " << role;
+			return nullptr;
 		}
 
-		StreamFormats formats(streamFormats);
-
-		StreamConfiguration cfg(formats);
-		cfg.pixelFormat = pixelFormat;
-		cfg.size = size;
-		cfg.bufferCount = 4;
 		config->addConfiguration(cfg);
 	}
 
