[PATCH v2 4/4] pipeline: rkisp1: Implement gamma control

Stefan Klug stefan.klug at ideasonboard.com
Wed May 22 16:54:38 CEST 2024


Add support for the gamma control on the rkisp1. This was tested on
an imx8mp.

Signed-off-by: Stefan Klug <stefan.klug at ideasonboard.com>
---
 src/ipa/rkisp1/algorithms/goc.cpp | 77 +++++++++++++++++++++++++++----
 src/ipa/rkisp1/algorithms/goc.h   | 11 ++++-
 src/ipa/rkisp1/ipa_context.h      |  4 ++
 3 files changed, 81 insertions(+), 11 deletions(-)

diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp
index 6f313820..0b312e7a 100644
--- a/src/ipa/rkisp1/algorithms/goc.cpp
+++ b/src/ipa/rkisp1/algorithms/goc.cpp
@@ -11,6 +11,8 @@
 #include <libcamera/base/log.h>
 #include <libcamera/base/utils.h>
 
+#include <libcamera/control_ids.h>
+
 #include "libcamera/internal/yaml_parser.h"
 
 #include "linux/rkisp1-config.h"
@@ -41,6 +43,7 @@ namespace ipa::rkisp1::algorithms {
 LOG_DEFINE_CATEGORY(RkISP1Gamma)
 
 Gamma::Gamma()
+	: gamma_(0)
 {
 }
 
@@ -50,6 +53,8 @@ Gamma::Gamma()
 int Gamma::init([[maybe_unused]] IPAContext &context,
 		[[maybe_unused]] const YamlObject &tuningData)
 {
+	context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, 2.2f);
+
 	if (context.hw->numGammaOutSamples !=
 	    RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10) {
 		LOG(RkISP1Gamma, Error)
@@ -60,6 +65,41 @@ int Gamma::init([[maybe_unused]] IPAContext &context,
 	return 0;
 }
 
+/**
+ * \brief Configure the Gamma given a configInfo
+ * \param[in] context The shared IPA context
+ * \param[in] configInfo The IPA configuration data
+ *
+ * \return 0
+ */
+int Gamma::configure(IPAContext &context,
+		     [[maybe_unused]] const IPACameraSensorInfo &configInfo)
+{
+	context.activeState.gamma = 2.2;
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::queueRequest
+ */
+void Gamma::queueRequest([[maybe_unused]] IPAContext &context,
+			 [[maybe_unused]] const uint32_t frame,
+			 IPAFrameContext &frameContext,
+			 const ControlList &controls)
+{
+	const auto &gamma = controls.get(controls::Gamma);
+	if (gamma) {
+		/* \todo This is not correct as it updates the current state with a
+		 * future value. But it does no harm at the moment an allows us to
+		 * track the last active gamma
+		 */
+		context.activeState.gamma = *gamma;
+		LOG(RkISP1Gamma, Debug) << "Set gamma to " << *gamma;
+	}
+
+	frameContext.gamma = context.activeState.gamma;
+}
+
 /**
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
@@ -78,19 +118,36 @@ void Gamma::prepare([[maybe_unused]] IPAContext &context,
 	ASSERT(context.hw->numGammaOutSamples ==
 	       RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10);
 
-	if (frame > 0)
-		return;
+	if (frame == 0 || std::fabs(frameContext.gamma - gamma_) > 0.001) {
+		gamma_ = frameContext.gamma;
+
+		int x = 0;
+		for (unsigned i = 0; i < context.hw->numGammaOutSamples; i++) {
+			gamma_y[i] = std::pow(x / 4096.0, 1.0 / gamma_) * 1023.0;
+			x += segments[i];
+		}
 
-	int x = 0;
-	for (unsigned i = 0; i < context.hw->numGammaOutSamples; i++) {
-		gamma_y[i] = std::pow(x / 4096.0, 1.0 / gamma_) * 1023.0;
-		x += segments[i];
+		params->others.goc_config.mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC;
+		params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_GOC;
+
+		/* It is unclear why these bits need to be set more than once.
+		 * Setting them only on frame 0 didn't apply gamma.
+		 */
+		params->module_en_update |= RKISP1_CIF_ISP_MODULE_GOC;
+		params->module_ens |= RKISP1_CIF_ISP_MODULE_GOC;
 	}
+}
 
-	params->others.goc_config.mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC;
-	params->module_en_update |= RKISP1_CIF_ISP_MODULE_GOC;
-	params->module_ens |= RKISP1_CIF_ISP_MODULE_GOC;
-	params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_GOC;
+/**
+ * \copydoc libcamera::ipa::Algorithm::process
+ */
+void Gamma::process([[maybe_unused]] IPAContext &context,
+		    [[maybe_unused]] const uint32_t frame,
+		    IPAFrameContext &frameContext,
+		    [[maybe_unused]] const rkisp1_stat_buffer *stats,
+		    ControlList &metadata)
+{
+	metadata.set(controls::Gamma, frameContext.gamma);
 }
 
 REGISTER_IPA_ALGORITHM(Gamma, "Gamma")
diff --git a/src/ipa/rkisp1/algorithms/goc.h b/src/ipa/rkisp1/algorithms/goc.h
index fe7caba3..f2142b55 100644
--- a/src/ipa/rkisp1/algorithms/goc.h
+++ b/src/ipa/rkisp1/algorithms/goc.h
@@ -20,12 +20,21 @@ public:
 	~Gamma() = default;
 
 	int init(IPAContext &context, const YamlObject &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,
 		     rkisp1_params_cfg *params) override;
+	void process(IPAContext &context, const uint32_t frame,
+		     IPAFrameContext &frameContext,
+		     const rkisp1_stat_buffer *stats,
+		     ControlList &metadata) override;
 
 private:
-	float gamma_ = 2.2;
+	float gamma_;
 };
 
 } /* namespace ipa::rkisp1::algorithms */
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index bd02a7a2..5252e222 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -104,6 +104,8 @@ struct IPAActiveState {
 		uint8_t denoise;
 		uint8_t sharpness;
 	} filter;
+
+	double gamma;
 };
 
 struct IPAFrameContext : public FrameContext {
@@ -146,6 +148,8 @@ struct IPAFrameContext : public FrameContext {
 		uint32_t exposure;
 		double gain;
 	} sensor;
+
+	double gamma;
 };
 
 struct IPAContext {
-- 
2.40.1



More information about the libcamera-devel mailing list