[RFC,v1] ipa: mali-c55: Add support for RGB Gamma
diff mbox series

Message ID 20261030172600.567803-1-barnabas.pocze@ideasonboard.com
State New
Headers show
Series
  • [RFC,v1] ipa: mali-c55: Add support for RGB Gamma
Related show

Commit Message

Barnabás Pőcze Oct. 30, 2026, 5:26 p.m. UTC
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

Add an algorithm to support the RGB Gamma encoding correction engine.

The RGB Gamma ISP engine supports configurable gains and offsets which
are currently programmed with fixed bypass values.

The gamma curve correction is implemented as an LUT with 129 nodes with
coefficients expressed as 12-bits unsigned values.

Also add it to the uncalibrated tuning file.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
[Use libipa GammaAlgorithm.]
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 src/ipa/mali-c55/algorithms/gamma.cpp   | 111 ++++++++++++++++++++++++
 src/ipa/mali-c55/algorithms/gamma.h     |  42 +++++++++
 src/ipa/mali-c55/algorithms/meson.build |   1 +
 src/ipa/mali-c55/data/uncalibrated.yaml |   1 +
 src/ipa/mali-c55/ipa_context.h          |   3 +
 src/ipa/mali-c55/params.h               |   4 +
 6 files changed, 162 insertions(+)
 create mode 100644 src/ipa/mali-c55/algorithms/gamma.cpp
 create mode 100644 src/ipa/mali-c55/algorithms/gamma.h

Patch
diff mbox series

diff --git a/src/ipa/mali-c55/algorithms/gamma.cpp b/src/ipa/mali-c55/algorithms/gamma.cpp
new file mode 100644
index 0000000000..31cb45cfa5
--- /dev/null
+++ b/src/ipa/mali-c55/algorithms/gamma.cpp
@@ -0,0 +1,111 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2026, Ideas On Board
+ *
+ * MaliC55 RGB Gamma control
+ */
+
+#include "gamma.h"
+
+#include <algorithm>
+
+#include <libcamera/controls.h>
+
+#include <libipa/fixedpoint.h>
+
+namespace libcamera {
+
+namespace ipa::mali_c55::algorithms {
+
+/**
+ * \class RGBGamma
+ * \brief MaliC55 Gamma out correction
+ *
+ * This algorithm implements the output gamma correction using the libipa
+ * GammaAlgorithm class.
+ *
+ * The hardware uses 129 evenly spaced points for its lookup table, and
+ * applies linear interpolation between them.
+ *
+ * The same module is also capable of applying an offset and gain to each channel.
+ * \todo Implement support for global contrast adjustments.
+ */
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
+int RGBGamma::init(IPAContext &context, const ValueNode &tuningData)
+{
+	return gamma_.init(context.ctrlMap, tuningData);
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::configure
+ */
+int RGBGamma::configure(IPAContext &context,
+			[[maybe_unused]] const IPACameraSensorInfo &configInfo)
+{
+	gamma_.configure(context.activeState.gamma);
+
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::queueRequest
+ */
+void RGBGamma::queueRequest(IPAContext &context, const uint32_t frame,
+			    IPAFrameContext &frameContext,
+			    const ControlList &controls)
+{
+	gamma_.queueRequest(context.activeState.gamma, frame, frameContext.gamma, controls);
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::prepare
+ */
+void RGBGamma::prepare([[maybe_unused]] IPAContext &context,
+		       [[maybe_unused]] const uint32_t frame,
+		       IPAFrameContext &frameContext,
+		       MaliC55Params *params)
+{
+	if (!frameContext.gamma.update)
+		return;
+
+	auto frConfig = params->block<MaliC55Blocks::GammaFr>();
+	frConfig.setEnabled(true);
+
+	gamma_.prepare(frameContext.gamma, std::span(frConfig->lut));
+
+	/*
+	 * Fixed offsets and gains: 0 and 1x.
+	 * \todo Implement global contrast adjustment using offsets and gains.
+	 */
+	std::fill(frConfig->gains, std::end(frConfig->gains), UQ<4, 8>(1.f).quantized());
+	std::fill(frConfig->offs, std::end(frConfig->offs), UQ<0, 12>(0.f).quantized());
+
+	/* Enable the same gamma correction on the "downscale" pipeline as well. */
+	auto dsConfig = params->block<MaliC55Blocks::GammaDs>();
+	dsConfig.setEnabled(true);
+
+	std::copy(frConfig->gains, std::end(frConfig->gains), dsConfig->gains);
+	std::copy(frConfig->offs, std::end(frConfig->offs), dsConfig->offs);
+	std::copy(frConfig->lut, std::end(frConfig->lut), dsConfig->lut);
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::process
+ */
+void RGBGamma::process([[maybe_unused]] IPAContext &context,
+		       [[maybe_unused]] const uint32_t frame,
+		       IPAFrameContext &frameContext,
+		       [[maybe_unused]] const mali_c55_stats_buffer *stats,
+		       ControlList &metadata)
+{
+	gamma_.process(frameContext.gamma, metadata);
+}
+
+REGISTER_IPA_ALGORITHM(RGBGamma, "RGBGamma")
+
+} /* namespace ipa::mali_c55::algorithms */
+
+} /* namespace libcamera */
diff --git a/src/ipa/mali-c55/algorithms/gamma.h b/src/ipa/mali-c55/algorithms/gamma.h
new file mode 100644
index 0000000000..d498ae6785
--- /dev/null
+++ b/src/ipa/mali-c55/algorithms/gamma.h
@@ -0,0 +1,42 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2026, Ideas On Board
+ *
+ * MaliC55 RGB Gamma control
+ */
+
+#pragma once
+
+#include <libipa/fixedpoint.h>
+#include <libipa/gamma.h>
+
+#include "algorithm.h"
+
+namespace libcamera {
+
+namespace ipa::mali_c55::algorithms {
+
+class RGBGamma : public Algorithm
+{
+public:
+	int init(IPAContext &context, const ValueNode &tuningData) override;
+	int configure(IPAContext &context,
+		      const IPACameraSensorInfo &configInfo) override;
+	void queueRequest(IPAContext &context,
+			  const uint32_t frame,
+			  IPAFrameContext &frameContext,
+			  const ControlList &controls) override;
+	void prepare(IPAContext &context, const uint32_t frame,
+		     IPAFrameContext &frameContext,
+		     MaliC55Params *params) override;
+	void process(IPAContext &context, const uint32_t frame,
+		     IPAFrameContext &frameContext,
+		     const mali_c55_stats_buffer *stats,
+		     ControlList &metadata) override;
+
+private:
+	GammaAlgorithm<129, UQ<0, 12>> gamma_;
+};
+
+} /* namespace ipa::mali_c55::algorithms */
+} /* namespace libcamera */
diff --git a/src/ipa/mali-c55/algorithms/meson.build b/src/ipa/mali-c55/algorithms/meson.build
index 24a27ce665..65fb1baba9 100644
--- a/src/ipa/mali-c55/algorithms/meson.build
+++ b/src/ipa/mali-c55/algorithms/meson.build
@@ -5,5 +5,6 @@  mali_c55_ipa_algorithms = files([
     'awb.cpp',
     'blc.cpp',
     'ccm.cpp',
+    'gamma.cpp',
     'lsc.cpp',
 ])
diff --git a/src/ipa/mali-c55/data/uncalibrated.yaml b/src/ipa/mali-c55/data/uncalibrated.yaml
index ea44c58c9e..f4508fb913 100644
--- a/src/ipa/mali-c55/data/uncalibrated.yaml
+++ b/src/ipa/mali-c55/data/uncalibrated.yaml
@@ -7,4 +7,5 @@  algorithms:
   - Awb:
   - BlackLevelCorrection:
   - Ccm:
+  - RGBGamma:
 ...
diff --git a/src/ipa/mali-c55/ipa_context.h b/src/ipa/mali-c55/ipa_context.h
index cd370e25fc..030e0052ad 100644
--- a/src/ipa/mali-c55/ipa_context.h
+++ b/src/ipa/mali-c55/ipa_context.h
@@ -21,6 +21,7 @@ 
 #include "libipa/awb.h"
 #include "libipa/ccm.h"
 #include "libipa/fixedpoint.h"
+#include "libipa/gamma.h"
 #include "libipa/lsc.h"
 
 namespace libcamera {
@@ -43,6 +44,7 @@  struct IPAActiveState {
 
 	ipa::awb::ActiveState awb;
 	ipa::ccm::ActiveState ccm;
+	ipa::gamma::ActiveState gamma;
 	ipa::lsc::ActiveState lsc;
 };
 
@@ -56,6 +58,7 @@  struct IPAFrameContext : public FrameContext {
 
 	ipa::awb::FrameContext awb;
 	ipa::ccm::FrameContext ccm;
+	ipa::gamma::FrameContext gamma;
 	ipa::lsc::FrameContext lsc;
 };
 
diff --git a/src/ipa/mali-c55/params.h b/src/ipa/mali-c55/params.h
index dc4d199402..00c388c9ed 100644
--- a/src/ipa/mali-c55/params.h
+++ b/src/ipa/mali-c55/params.h
@@ -30,6 +30,8 @@  enum class MaliC55Blocks : uint16_t {
 	MeshShadingConfig,
 	MeshShadingSel,
 	Ccm,
+	GammaFr,
+	GammaDs,
 };
 
 namespace details {
@@ -57,6 +59,8 @@  MALI_C55_DEFINE_BLOCK_TYPE(AwbConfig,		awb_config,		BLOCK_AWB_CONFIG);
 MALI_C55_DEFINE_BLOCK_TYPE(MeshShadingConfig,	mesh_shading_config,	MESH_SHADING_CONFIG);
 MALI_C55_DEFINE_BLOCK_TYPE(MeshShadingSel,	mesh_shading_selection,	MESH_SHADING_SELECTION);
 MALI_C55_DEFINE_BLOCK_TYPE(Ccm,			ccm,			BLOCK_CCM);
+MALI_C55_DEFINE_BLOCK_TYPE(GammaFr,		gamma,			BLOCK_GAMMA_FR);
+MALI_C55_DEFINE_BLOCK_TYPE(GammaDs,		gamma,			BLOCK_GAMMA_DS);
 
 struct param_traits {
 	using id_type = MaliC55Blocks;