From 949bca82ab886862a185241bd7c68cd1c2c1e7c7 Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Wed, 1 Oct 2025 12:55:46 +0100 Subject: [PATCH 1/3] ipa: rpi: Add FE globals as a parameter to applyDecompand() Don't let applyDecompand() directly change the FE global enables. Instead pass the global mask into the function and set it in the caller. This will be needed when a future commit will add setting the decompand initial values. Signed-off-by: Naushir Patuck --- src/ipa/rpi/pisp/pisp.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ipa/rpi/pisp/pisp.cpp b/src/ipa/rpi/pisp/pisp.cpp index e75c87df1..03c6c47c1 100644 --- a/src/ipa/rpi/pisp/pisp.cpp +++ b/src/ipa/rpi/pisp/pisp.cpp @@ -256,7 +256,7 @@ class IpaPiSP final : public IpaBase void applyLensShading(const AlscStatus *alscStatus, pisp_be_global_config &global); void applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global); - void applyDecompand(const DecompandStatus *decompandStatus); + void applyDecompand(const DecompandStatus *decompandStatus, pisp_fe_global_config &feGlobal); void applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global); void applyTdn(const TdnStatus *tdnStatus, const DeviceStatus *deviceStatus, pisp_be_global_config &global); @@ -368,6 +368,9 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, { /* All Frontend config goes first, we do not want to hold the FE lock for long! */ std::scoped_lock lf(*fe_); + pisp_fe_global_config feGlobal; + + fe_->GetGlobal(feGlobal); if (noiseStatus) applyFocusStats(noiseStatus); @@ -375,13 +378,14 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, DecompandStatus *decompandStatus = rpiMetadata.getLocked("decompand.status"); if (decompandStatus) - applyDecompand(decompandStatus); + applyDecompand(decompandStatus, feGlobal); BlackLevelStatus *blackLevelStatus = rpiMetadata.getLocked("black_level.status"); if (blackLevelStatus) applyBlackLevel(blackLevelStatus, global); + fe_->SetGlobal(feGlobal); } CacStatus *cacStatus = rpiMetadata.getLocked("cac.status"); @@ -728,18 +732,15 @@ void IpaPiSP::applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global be_->SetDpc(dpc); } -void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus) +void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus, pisp_fe_global_config &feGlobal) { - pisp_fe_global_config feGlobal; pisp_fe_decompand_config decompand = {}; - fe_->GetGlobal(feGlobal); - if (!generateDecompandLut(decompandStatus->decompandCurve, decompand.lut, PISP_FE_DECOMPAND_LUT_SIZE)) { fe_->SetDecompand(decompand); feGlobal.enables |= PISP_FE_ENABLE_DECOMPAND; - fe_->SetGlobal(feGlobal); - } + } else + feGlobal.enables &= ~PISP_FE_ENABLE_DECOMPAND; } void IpaPiSP::applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global) From 0cde0d0055778e09b12a4e5a5d031ffc325e7f7b Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Wed, 1 Oct 2025 13:00:01 +0100 Subject: [PATCH 2/3] ipa: rpi: pisp: Add a DecompandAlgorithm class The decompand algorithm implementation will subclass the DecompandAlgorithm class. This will be needed for setting the initial decompand values in a future commit. Signed-off-by: Naushir Patuck --- src/ipa/rpi/controller/decompand_algorithm.h | 24 ++++++++++++++++++++ src/ipa/rpi/controller/rpi/decompand.cpp | 2 +- src/ipa/rpi/controller/rpi/decompand.h | 5 ++-- 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 src/ipa/rpi/controller/decompand_algorithm.h diff --git a/src/ipa/rpi/controller/decompand_algorithm.h b/src/ipa/rpi/controller/decompand_algorithm.h new file mode 100644 index 000000000..f19f8c109 --- /dev/null +++ b/src/ipa/rpi/controller/decompand_algorithm.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2025, Raspberry Pi Ltd + * + * Decompand control algorithm interface + */ +#pragma once + +#include "libipa/pwl.h" + +#include "algorithm.h" + +namespace RPiController { + +class DecompandAlgorithm : public Algorithm +{ +public: + DecompandAlgorithm(Controller *controller = NULL) + : Algorithm(controller) + { + } +}; + +} /* namespace RPiController */ diff --git a/src/ipa/rpi/controller/rpi/decompand.cpp b/src/ipa/rpi/controller/rpi/decompand.cpp index 911b04bc0..b45043680 100644 --- a/src/ipa/rpi/controller/rpi/decompand.cpp +++ b/src/ipa/rpi/controller/rpi/decompand.cpp @@ -13,7 +13,7 @@ LOG_DEFINE_CATEGORY(RPiDecompand) #define NAME "rpi.decompand" Decompand::Decompand(Controller *controller) - : Algorithm(controller) + : DecompandAlgorithm(controller) { } diff --git a/src/ipa/rpi/controller/rpi/decompand.h b/src/ipa/rpi/controller/rpi/decompand.h index 5ef35946e..321a561ab 100644 --- a/src/ipa/rpi/controller/rpi/decompand.h +++ b/src/ipa/rpi/controller/rpi/decompand.h @@ -2,10 +2,9 @@ #include +#include "../decompand_algorithm.h" #include "../decompand_status.h" -#include "algorithm.h" - namespace RPiController { struct DecompandConfig { @@ -13,7 +12,7 @@ struct DecompandConfig { libcamera::ipa::Pwl decompandCurve; }; -class Decompand : public Algorithm +class Decompand : public DecompandAlgorithm { public: Decompand(Controller *controller = NULL); From 7b7108bc027c1bd665dbe26565be0823f162b134 Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Wed, 1 Oct 2025 13:02:35 +0100 Subject: [PATCH 3/3] ipa: rpi: pisp: Allow an initial decompand curve to be set on the FE In the current code, decompand will only set a curve in the prepare phase, which will only run after 1-2 frames pass through the FE. This is fixed by adding an initialValues() member function to the decompand algorithm, which will be called in the IPA before we start the hardware streaming. Signed-off-by: Naushir Patuck --- src/ipa/rpi/controller/decompand_algorithm.h | 2 ++ src/ipa/rpi/controller/rpi/decompand.cpp | 8 ++++++++ src/ipa/rpi/controller/rpi/decompand.h | 1 + src/ipa/rpi/pisp/pisp.cpp | 15 +++++++++++++++ 4 files changed, 26 insertions(+) diff --git a/src/ipa/rpi/controller/decompand_algorithm.h b/src/ipa/rpi/controller/decompand_algorithm.h index f19f8c109..6d2467490 100644 --- a/src/ipa/rpi/controller/decompand_algorithm.h +++ b/src/ipa/rpi/controller/decompand_algorithm.h @@ -19,6 +19,8 @@ class DecompandAlgorithm : public Algorithm : Algorithm(controller) { } + /* A decompand algorithm must provide the following: */ + virtual void initialValues(libcamera::ipa::Pwl &decompandCurve) = 0; }; } /* namespace RPiController */ diff --git a/src/ipa/rpi/controller/rpi/decompand.cpp b/src/ipa/rpi/controller/rpi/decompand.cpp index b45043680..2c3bf7ee4 100644 --- a/src/ipa/rpi/controller/rpi/decompand.cpp +++ b/src/ipa/rpi/controller/rpi/decompand.cpp @@ -39,6 +39,14 @@ void Decompand::switchMode([[maybe_unused]] CameraMode const &cameraMode, mode_ = cameraMode; } +void Decompand::initialValues(libcamera::ipa::Pwl &decompandCurve) +{ + if (config_.bitdepth == 0 || mode_.bitdepth == config_.bitdepth) { + decompandCurve = config_.decompandCurve; + } else + decompandCurve = {}; +} + void Decompand::prepare(Metadata *imageMetadata) { DecompandStatus decompandStatus; diff --git a/src/ipa/rpi/controller/rpi/decompand.h b/src/ipa/rpi/controller/rpi/decompand.h index 321a561ab..2c44b09e4 100644 --- a/src/ipa/rpi/controller/rpi/decompand.h +++ b/src/ipa/rpi/controller/rpi/decompand.h @@ -20,6 +20,7 @@ class Decompand : public DecompandAlgorithm int read(const libcamera::YamlObject ¶ms) override; void initialise() override; void switchMode(CameraMode const &cameraMode, Metadata *metadata) override; + void initialValues(libcamera::ipa::Pwl &decompandCurve) override; void prepare(Metadata *imageMetadata) override; private: diff --git a/src/ipa/rpi/pisp/pisp.cpp b/src/ipa/rpi/pisp/pisp.cpp index 03c6c47c1..134fc5aab 100644 --- a/src/ipa/rpi/pisp/pisp.cpp +++ b/src/ipa/rpi/pisp/pisp.cpp @@ -32,6 +32,7 @@ #include "controller/cac_status.h" #include "controller/ccm_status.h" #include "controller/contrast_status.h" +#include "controller/decompand_algorithm.h" #include "controller/decompand_status.h" #include "controller/denoise_algorithm.h" #include "controller/denoise_status.h" @@ -335,6 +336,20 @@ int32_t IpaPiSP::platformStart([[maybe_unused]] const ControlList &controls, /* Cause the stitch block to be reset correctly. */ lastStitchHdrStatus_ = HdrStatus(); + /* Setup a default decompand curve on startup if needed. */ + RPiController::DecompandAlgorithm *decompand = dynamic_cast( + controller_.getAlgorithm("decompand")); + if (decompand) { + std::scoped_lock l(*fe_); + pisp_fe_global_config feGlobal; + DecompandStatus decompandStatus; + + fe_->GetGlobal(feGlobal); + decompand->initialValues(decompandStatus.decompandCurve); + applyDecompand(&decompandStatus, feGlobal); + fe_->SetGlobal(feGlobal); + } + return 0; }