[RFC,12/19] ipa: rkisp2: algo: csm: Implement color space conversion
diff mbox series

Message ID 20260703122543.1991189-13-paul.elder@ideasonboard.com
State New
Headers show
Series
  • Add support for rkisp2
Related show

Commit Message

Paul Elder July 3, 2026, 12:25 p.m. UTC
Implement a static color space conversion algorithm for the rkisp2 IPA.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
---
 src/ipa/rkisp2/algorithms/csm.cpp     | 177 ++++++++++++++++++++++++++
 src/ipa/rkisp2/algorithms/csm.h       |  34 +++++
 src/ipa/rkisp2/algorithms/meson.build |   1 +
 3 files changed, 212 insertions(+)
 create mode 100644 src/ipa/rkisp2/algorithms/csm.cpp
 create mode 100644 src/ipa/rkisp2/algorithms/csm.h

Patch
diff mbox series

diff --git a/src/ipa/rkisp2/algorithms/csm.cpp b/src/ipa/rkisp2/algorithms/csm.cpp
new file mode 100644
index 000000000000..1733c2938d23
--- /dev/null
+++ b/src/ipa/rkisp2/algorithms/csm.cpp
@@ -0,0 +1,177 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2026, Ideas On Board
+ *
+ * RkISP2 Color space conversion
+ */
+
+#include "csm.h"
+
+#include <array>
+#include <cmath>
+
+#include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
+
+#include <libcamera/color_space.h>
+#include <libcamera/control_ids.h>
+
+#include "linux/rkisp2-config.h"
+
+/**
+ * \file csm.h
+ */
+
+namespace libcamera {
+
+namespace ipa::rkisp2::algorithms {
+
+/**
+ * \class ColorSpaceConversion
+ * \brief RkISP2 Color space conversion
+ *
+ * This algorithm implements the color space conversion for the RkISP2.
+ */
+
+LOG_DEFINE_CATEGORY(RkISP2Csm)
+
+namespace {
+	struct CsmCoeffs {
+		uint16_t limited[9];
+		uint16_t full[9];
+	};
+
+	static const struct CsmCoeffs rec601Coeffs = {
+		{
+			0x0021, 0x0042, 0x000d,
+			0x01ed, 0x01db, 0x0038,
+			0x0038, 0x01d1, 0x01f7,
+		},
+		{
+			0x0026, 0x004b, 0x000f,
+			0x01ea, 0x01d6, 0x0040,
+			0x0040, 0x01ca, 0x01f6,
+		},
+	};
+
+	static const struct CsmCoeffs rec709Coeffs = {
+		{
+			0x0018, 0x0050, 0x0008,
+			0x01f3, 0x01d5, 0x0038,
+			0x0038, 0x01cd, 0x01fb,
+		},
+		{
+			0x001b, 0x005c, 0x0009,
+			0x01f1, 0x01cf, 0x0040,
+			0x0040, 0x01c6, 0x01fa,
+		},
+	};
+
+	static const struct CsmCoeffs rec2020Coeffs = {
+		{
+			0x001d, 0x004c, 0x0007,
+			0x01f0, 0x01d8, 0x0038,
+			0x0038, 0x01cd, 0x01fb,
+		},
+		{
+			0x0022, 0x0057, 0x0008,
+			0x01ee, 0x01d2, 0x0040,
+			0x0040, 0x01c5, 0x01fb,
+		},
+	};
+
+	static const struct CsmCoeffs smpte240mCoeffs = {
+		{
+			0x0018, 0x004f, 0x000a,
+			0x01f3, 0x01d5, 0x0038,
+			0x0038, 0x01ce, 0x01fa,
+		},
+		{
+			0x001b, 0x005a, 0x000b,
+			0x01f1, 0x01cf, 0x0040,
+			0x0040, 0x01c7, 0x01f9,
+		},
+	};
+
+	uint16_t identityCsm[9] = {
+		1, 0, 0,
+		0, 1, 0,
+		0, 0, 1,
+	};
+} /* namespace */
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
+int ColorSpaceConversion::init([[maybe_unused]] IPAContext &context,
+			       [[maybe_unused]] const ValueNode &tuningData)
+{
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::configure
+ */
+int ColorSpaceConversion::configure(IPAContext &context,
+				    [[maybe_unused]] const IPACameraSensorInfo &configInfo)
+{
+	const CsmCoeffs *coeffs;
+	switch (context.configuration.csm.colorSpaceEncoding) {
+	case static_cast<int>(ColorSpace::YcbcrEncoding::Rec601):
+		coeffs = &rec601Coeffs;
+		break;
+	case static_cast<int>(ColorSpace::YcbcrEncoding::Rec709):
+		coeffs = &rec709Coeffs;
+		break;
+	case static_cast<int>(ColorSpace::YcbcrEncoding::Rec2020):
+		coeffs = &rec2020Coeffs;
+		break;
+	default:
+		coeffs = nullptr;
+		break;
+	}
+
+	if (!coeffs) {
+		context.activeState.csm.csm = Matrix<uint16_t, 3, 3>(identityCsm);
+		return 0;
+	}
+
+	if (context.configuration.csm.colorSpaceRange == static_cast<int>(ColorSpace::Range::Limited))
+		context.activeState.csm.csm = Matrix<uint16_t, 3, 3>(coeffs->limited);
+	else
+		context.activeState.csm.csm = Matrix<uint16_t, 3, 3>(coeffs->full);
+	context.activeState.csm.update = true;
+
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::prepare
+ */
+void ColorSpaceConversion::prepare(IPAContext &context,
+				   [[maybe_unused]] const uint32_t frame,
+				   [[maybe_unused]] IPAFrameContext &frameContext,
+				   RkISP2Params *params)
+{
+	if (!context.activeState.csm.update)
+		return;
+
+	auto config = params->block<RkISP2Blocks::Csm>();
+	config.setEnabled(true);
+
+	/*
+	 * We'll use the active state directly as we don't support runtime
+	 * configuration of the csm
+	 */
+	for (size_t i = 0; i < 3; i++)
+		for (size_t j = 0; j < 3; j++)
+			config->coeff[i][j] = context.activeState.csm.csm[i][j];
+
+	context.activeState.csm.update = false;
+}
+
+REGISTER_IPA_ALGORITHM(ColorSpaceConversion, "ColorSpaceConversion")
+
+} /* namespace ipa::rkisp2::algorithms */
+
+} /* namespace libcamera */
diff --git a/src/ipa/rkisp2/algorithms/csm.h b/src/ipa/rkisp2/algorithms/csm.h
new file mode 100644
index 000000000000..d34e4d3959e8
--- /dev/null
+++ b/src/ipa/rkisp2/algorithms/csm.h
@@ -0,0 +1,34 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2026, Ideas On Board
+ *
+ * RkISP2 Color space conversion
+ */
+
+#pragma once
+
+#include "libcamera/internal/matrix.h"
+
+#include "algorithm.h"
+
+namespace libcamera {
+
+namespace ipa::rkisp2::algorithms {
+
+class ColorSpaceConversion : public Algorithm
+{
+public:
+	ColorSpaceConversion() = default;
+	~ColorSpaceConversion() = default;
+
+	int init(IPAContext &context, const ValueNode &tuningData) override;
+	int configure(IPAContext &context,
+		      const IPACameraSensorInfo &configInfo) override;
+	void prepare(IPAContext &context, const uint32_t frame,
+		     IPAFrameContext &frameContext,
+		     RkISP2Params *params) override;
+};
+
+} /* namespace ipa::rkisp2::algorithms */
+
+} /* namespace libcamera */
diff --git a/src/ipa/rkisp2/algorithms/meson.build b/src/ipa/rkisp2/algorithms/meson.build
index e7ae3d163bfb..01829e25d254 100644
--- a/src/ipa/rkisp2/algorithms/meson.build
+++ b/src/ipa/rkisp2/algorithms/meson.build
@@ -5,5 +5,6 @@  rkisp2_ipa_algorithms = files([
     'awb.cpp',
     'bls.cpp',
     'ccm.cpp',
+    'csm.cpp',
 ])