diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h
index a52a5f2c99f9..f7ec3c7004a6 100644
--- a/include/libcamera/internal/v4l2_device.h
+++ b/include/libcamera/internal/v4l2_device.h
@@ -55,6 +55,7 @@ protected:
 	int setFd(UniqueFD fd);
 
 	int ioctl(unsigned long request, void *argp);
+	int ioctl(unsigned long request, void *argp) const;
 
 	int fd() const { return fd_.get(); }
 
diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h
index 29fa0bbaf670..6d8850c99afd 100644
--- a/include/libcamera/internal/v4l2_videodevice.h
+++ b/include/libcamera/internal/v4l2_videodevice.h
@@ -205,7 +205,7 @@ public:
 	int getFormat(V4L2DeviceFormat *format);
 	int tryFormat(V4L2DeviceFormat *format);
 	int setFormat(V4L2DeviceFormat *format);
-	Formats formats(uint32_t code = 0);
+	Formats formats(uint32_t code = 0) const;
 
 	int setSelection(unsigned int target, Rectangle *rect);
 
@@ -251,8 +251,8 @@ private:
 	int getFormatSingleplane(V4L2DeviceFormat *format);
 	int trySetFormatSingleplane(V4L2DeviceFormat *format, bool set);
 
-	std::vector<V4L2PixelFormat> enumPixelformats(uint32_t code);
-	std::vector<SizeRange> enumSizes(V4L2PixelFormat pixelFormat);
+	std::vector<V4L2PixelFormat> enumPixelformats(uint32_t code) const;
+	std::vector<SizeRange> enumSizes(V4L2PixelFormat pixelFormat) const;
 
 	int requestBuffers(unsigned int count, enum v4l2_memory memoryType);
 	int createBuffers(unsigned int count,
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index 3fc8438f6579..59f92403db80 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -459,6 +459,21 @@ int V4L2Device::ioctl(unsigned long request, void *argp)
 	return 0;
 }
 
+/**
+ * \copydoc ioctl()
+ */
+int V4L2Device::ioctl(unsigned long request, void *argp) const
+{
+	/*
+	 * Printing out an error message is usually better performed
+	 * in the caller, which can provide more context.
+	 */
+	if (::ioctl(fd_.get(), request, argp) < 0)
+		return -errno;
+
+	return 0;
+}
+
 /**
  * \fn V4L2Device::deviceNode()
  * \brief Retrieve the device node path
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 43c3d0f69266..a3242ba755c0 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -1045,7 +1045,7 @@ int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set)
  *
  * \return A list of the supported video device formats
  */
-V4L2VideoDevice::Formats V4L2VideoDevice::formats(uint32_t code)
+V4L2VideoDevice::Formats V4L2VideoDevice::formats(uint32_t code) const
 {
 	Formats formats;
 
@@ -1067,7 +1067,7 @@ V4L2VideoDevice::Formats V4L2VideoDevice::formats(uint32_t code)
 	return formats;
 }
 
-std::vector<V4L2PixelFormat> V4L2VideoDevice::enumPixelformats(uint32_t code)
+std::vector<V4L2PixelFormat> V4L2VideoDevice::enumPixelformats(uint32_t code) const
 {
 	std::vector<V4L2PixelFormat> formats;
 	int ret;
@@ -1101,7 +1101,7 @@ std::vector<V4L2PixelFormat> V4L2VideoDevice::enumPixelformats(uint32_t code)
 	return formats;
 }
 
-std::vector<SizeRange> V4L2VideoDevice::enumSizes(V4L2PixelFormat pixelFormat)
+std::vector<SizeRange> V4L2VideoDevice::enumSizes(V4L2PixelFormat pixelFormat) const
 {
 	std::vector<SizeRange> sizes;
 	int ret;
@@ -1990,20 +1990,37 @@ V4L2VideoDevice::fromEntityName(const MediaDevice *media,
 }
 
 /**
- * \brief Convert \a PixelFormat to its corresponding V4L2 FourCC
+ * \brief Convert \a PixelFormat to one of the device supported V4L2 FourCC
  * \param[in] pixelFormat The PixelFormat to convert
  *
+ * Convert a\ pixelformat to a V4L2 FourCC that is known to be supported by
+ * the video device.
+ *
  * For multiplanar formats, the V4L2 format variant (contiguous or
  * non-contiguous planes) is selected automatically based on the capabilities
  * of the video device. If the video device supports the V4L2 multiplanar API,
  * non-contiguous formats are preferred.
  *
- * \return The V4L2_PIX_FMT_* pixel format code corresponding to \a pixelFormat
+ * \return The V4L2PixelFormat corresponding to \a pixelFormat or an invalid
+ * PixelFormat if \a pixelFormat is not supported by the video device
  */
 V4L2PixelFormat V4L2VideoDevice::toV4L2PixelFormat(const PixelFormat &pixelFormat) const
 {
-	return V4L2PixelFormat::fromPixelFormat(pixelFormat,
-						caps_.isMultiplanar())[0];
+	std::vector<V4L2PixelFormat> deviceFormats = enumPixelformats(0);
+	std::vector<V4L2PixelFormat> v4l2PixelFormats =
+		V4L2PixelFormat::fromPixelFormat(pixelFormat, caps_.isMultiplanar());
+
+	for (const V4L2PixelFormat &v4l2Format : v4l2PixelFormats) {
+		auto it = std::find_if(deviceFormats.begin(), deviceFormats.end(),
+				       [&v4l2Format](const V4L2PixelFormat &deviceFormat) {
+					       return v4l2Format == deviceFormat;
+				       });
+
+		if (it != deviceFormats.end())
+			return v4l2Format;
+	}
+
+	return {};
 }
 
 /**
