From patchwork Fri Oct 30 17:26:00 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 28723 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 32195C3261 for ; Fri, 30 Oct 2026 17:26:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3A1BD69109; Fri, 30 Oct 2026 18:26:05 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="U0pmASn1"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6C61869075 for ; Fri, 30 Oct 2026 18:26:03 +0100 (CET) Received: from pb-laptop.local (185.221.143.99.nat.pool.zt.hu [185.221.143.99]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id F034763C; Fri, 30 Oct 2026 18:23:48 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1793381029; bh=0ysbnxqLOME9M5mcQemAN5sSYjp8tLmtLeYjxJL2264=; h=From:To:Cc:Subject:Date:From; b=U0pmASn1pZORs0WLN87YLtVPvIxDwwLSHRGHil2Gx9V5H3ly8DRC7rRu7I+KojmJl PZ7tGr9WuXDagTjbefiXIeJ2q7LU8bv4LOfi/lOi3hD9b/BJLWL5420kjBzU2/dXZc 2LMim9aY8NAm8tPhRStG3V6X2ufNA7Unp0Y+iMlM= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi Subject: [RFC PATCH v1] ipa: mali-c55: Add support for RGB Gamma Date: Fri, 30 Oct 2026 18:26:00 +0100 Message-ID: <20261030172600.567803-1-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.56.0 MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Jacopo Mondi 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 [Use libipa GammaAlgorithm.] Signed-off-by: Barnabás Pőcze --- 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 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 + +#include + +#include + +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(); + 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(); + 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 +#include + +#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;