diff --git a/src/apps/common/dng_writer.cpp b/src/apps/common/dng_writer.cpp
index 0d9b725b939f..ab2b244b1cdf 100644
--- a/src/apps/common/dng_writer.cpp
+++ b/src/apps/common/dng_writer.cpp
@@ -8,13 +8,16 @@
 #include "dng_writer.h"
 
 #include <algorithm>
+#include <array>
 #include <endian.h>
 #include <iostream>
 #include <map>
+#include <optional>
 #include <vector>
 
 #include <tiffio.h>
 
+#include <libcamera/color_filter_array.h>
 #include <libcamera/control_ids.h>
 #include <libcamera/formats.h>
 #include <libcamera/property_ids.h>
@@ -27,9 +30,10 @@ enum CFAPatternColour : uint8_t {
 	CFAPatternBlue = 2,
 };
 
+typedef std::array<CFAPatternColour, 4> CFAPattern;
+
 struct FormatInfo {
 	uint8_t bitsPerSample;
-	CFAPatternColour pattern[4];
 	void (*packScanline)(void *output, const void *input,
 			     unsigned int width);
 	void (*thumbScanline)(const FormatInfo &info, void *output,
@@ -347,176 +351,63 @@ void thumbScanlineIPU3([[maybe_unused]] const FormatInfo &info, void *output,
 }
 
 const std::map<PixelFormat, FormatInfo> formatInfo = {
-	{ formats::SBGGR8, {
+	{ formats::RAW8, {
 		.bitsPerSample = 8,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw8,
 		.thumbScanline = thumbScanlineRaw_CSI2P,
 	} },
-	{ formats::SGBRG8, {
-		.bitsPerSample = 8,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw8,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SGRBG8, {
-		.bitsPerSample = 8,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw8,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SRGGB8, {
-		.bitsPerSample = 8,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw8,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SBGGR10, {
+	{ formats::RAW10, {
 		.bitsPerSample = 10,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw10,
 		.thumbScanline = thumbScanlineRaw,
 	} },
-	{ formats::SGBRG10, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw10,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SGRBG10, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw10,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SRGGB10, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw10,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SBGGR12, {
+	{ formats::RAW12, {
 		.bitsPerSample = 12,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw12,
 		.thumbScanline = thumbScanlineRaw,
 	} },
-	{ formats::SGBRG12, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw12,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SGRBG12, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw12,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SRGGB12, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw12,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SBGGR16, {
+	{ formats::RAW16, {
 		.bitsPerSample = 16,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw16,
 		.thumbScanline = thumbScanlineRaw,
 	} },
-	{ formats::SGBRG16, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw16,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SGRBG16, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw16,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SRGGB16, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw16,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SBGGR10_CSI2P, {
+	{ formats::RAW10_CSI2P, {
 		.bitsPerSample = 10,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw10_CSI2P,
 		.thumbScanline = thumbScanlineRaw_CSI2P,
 	} },
-	{ formats::SGBRG10_CSI2P, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw10_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SGRBG10_CSI2P, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw10_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SRGGB10_CSI2P, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw10_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SBGGR12_CSI2P, {
+	{ formats::RAW12_CSI2P, {
 		.bitsPerSample = 12,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw12_CSI2P,
 		.thumbScanline = thumbScanlineRaw_CSI2P,
 	} },
-	{ formats::SGBRG12_CSI2P, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw12_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SGRBG12_CSI2P, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw12_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SRGGB12_CSI2P, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw12_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SBGGR10_IPU3, {
+	{ formats::RAW10_IPU3, {
 		.bitsPerSample = 16,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
-		.packScanline = packScanlineIPU3,
-		.thumbScanline = thumbScanlineIPU3,
-	} },
-	{ formats::SGBRG10_IPU3, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineIPU3,
-		.thumbScanline = thumbScanlineIPU3,
-	} },
-	{ formats::SGRBG10_IPU3, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineIPU3,
-		.thumbScanline = thumbScanlineIPU3,
-	} },
-	{ formats::SRGGB10_IPU3, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
 		.packScanline = packScanlineIPU3,
 		.thumbScanline = thumbScanlineIPU3,
 	} },
 };
 
+static constexpr std::pair<ColorFilterArray, CFAPattern> patterns[] = {
+	{ ColorFilterArray::BGGR, { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed } },
+	{ ColorFilterArray::GBRG, { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen } },
+	{ ColorFilterArray::GRBG, { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen } },
+	{ ColorFilterArray::RGGB, { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue } },
+};
+
+static std::optional<CFAPattern> findCfaPattern(const std::optional<ColorFilterArray> cfa)
+{
+	if (!cfa)
+		return std::nullopt;
+
+	for (const auto &[key, pattern] : patterns) {
+		if (key.order == cfa.value().order)
+			return pattern;
+	}
+
+	return std::nullopt;
+}
+
 } /* namespace */
 
 int DNGWriter::write(const char *filename, const Camera *camera,
@@ -534,6 +425,12 @@ int DNGWriter::write(const char *filename, const Camera *camera,
 	}
 	const FormatInfo *info = &it->second;
 
+	const auto pattern = findCfaPattern(config.bayerOrder);
+	if (!pattern) {
+		std::cerr << "Unknown color filter array pattern" << std::endl;
+		return -EINVAL;
+	}
+
 	TIFF *tif = TIFFOpen(filename, "w");
 	if (!tif) {
 		std::cerr << "Failed to open tiff file" << std::endl;
@@ -696,9 +593,9 @@ int DNGWriter::write(const char *filename, const Camera *camera,
 	TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
 	TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, cfaRepeatPatternDim);
 	if (TIFFLIB_VERSION < 20201219)
-		TIFFSetField(tif, TIFFTAG_CFAPATTERN, info->pattern);
+		TIFFSetField(tif, TIFFTAG_CFAPATTERN, pattern.value().data());
 	else
-		TIFFSetField(tif, TIFFTAG_CFAPATTERN, 4, info->pattern);
+		TIFFSetField(tif, TIFFTAG_CFAPATTERN, 4, pattern.value().data());
 	TIFFSetField(tif, TIFFTAG_CFAPLANECOLOR, 3, cfaPlaneColor);
 	TIFFSetField(tif, TIFFTAG_CFALAYOUT, 1);
 
@@ -715,14 +612,14 @@ int DNGWriter::write(const char *filename, const Camera *camera,
 		 * Map it to the TIFF tag that is specified in CFA pattern
 		 * order.
 		 */
-		unsigned int green = (info->pattern[0] == CFAPatternRed ||
-				      info->pattern[1] == CFAPatternRed)
+		unsigned int green = (pattern.value()[0] == CFAPatternRed ||
+				      pattern.value()[1] == CFAPatternRed)
 				   ? 0 : 1;
 
 		for (unsigned int i = 0; i < 4; ++i) {
 			unsigned int level;
 
-			switch (info->pattern[i]) {
+			switch (pattern.value()[i]) {
 			case CFAPatternRed:
 				level = levels[0];
 				break;
