From c7cc1f7f0dd0fe444b8593a9f572a45bfd111f83 Mon Sep 17 00:00:00 2001 From: Stefan Klug Date: Fri, 19 Sep 2025 11:40:29 +0200 Subject: [PATCH] pipeline: rkisp1: Query kernel for available params blocks Query the params device for RKISP1_CID_SUPPORTED_PARAMS_BLOCKS and inject the information into the IPA hardware context for use by the algorithms. To be able to modify the hardware configuration at runtime, replace the pointer with an instance and create a copy of the static hardware specific data. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham Reviewed-by: Daniel Scally Reviewed-by: Paul Elder Signed-off-by: Kieran Bingham --- include/libcamera/ipa/rkisp1.mojom | 2 +- src/ipa/rkisp1/algorithms/agc.cpp | 10 ++++---- src/ipa/rkisp1/algorithms/blc.cpp | 4 ++-- src/ipa/rkisp1/algorithms/compress.cpp | 2 +- src/ipa/rkisp1/algorithms/goc.cpp | 4 ++-- src/ipa/rkisp1/algorithms/lux.cpp | 2 +- src/ipa/rkisp1/ipa_context.h | 5 ++-- src/ipa/rkisp1/rkisp1.cpp | 12 +++++++--- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 29 ++++++++++++++++++++---- 9 files changed, 49 insertions(+), 21 deletions(-) diff --git a/include/libcamera/ipa/rkisp1.mojom b/include/libcamera/ipa/rkisp1.mojom index 043ad27e..068e8988 100644 --- a/include/libcamera/ipa/rkisp1.mojom +++ b/include/libcamera/ipa/rkisp1.mojom @@ -16,7 +16,7 @@ struct IPAConfigInfo { interface IPARkISP1Interface { init(libcamera.IPASettings settings, - uint32 hwRevision, + uint32 hwRevision, uint32 supportedBlocks, libcamera.IPACameraSensorInfo sensorInfo, libcamera.ControlInfoMap sensorControls) => (int32 ret, libcamera.ControlInfoMap ipaControls); diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 174d810e..d0337fd0 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -56,7 +56,7 @@ int Agc::parseMeteringModes(IPAContext &context, const YamlObject &tuningData) std::vector weights = value.getList().value_or(std::vector{}); - if (weights.size() != context.hw->numHistogramWeights) { + if (weights.size() != context.hw.numHistogramWeights) { LOG(RkISP1Agc, Warning) << "Failed to read metering mode'" << key << "'"; continue; @@ -68,7 +68,7 @@ int Agc::parseMeteringModes(IPAContext &context, const YamlObject &tuningData) if (meteringModes_.empty()) { LOG(RkISP1Agc, Warning) << "No metering modes read from tuning file; defaulting to matrix"; - std::vector weights(context.hw->numHistogramWeights, 1); + std::vector weights(context.hw.numHistogramWeights, 1); meteringModes_[controls::MeteringMatrix] = weights; } @@ -418,7 +418,7 @@ void Agc::prepare(IPAContext &context, const uint32_t frame, Span weights{ hstConfig->hist_weight, - context.hw->numHistogramWeights + context.hw.numHistogramWeights }; std::vector &modeWeights = meteringModes_.at(frameContext.agc.meteringMode); std::copy(modeWeights.begin(), modeWeights.end(), weights.begin()); @@ -556,9 +556,9 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, const rkisp1_cif_isp_stat *params = &stats->params; /* The lower 4 bits are fractional and meant to be discarded. */ - Histogram hist({ params->hist.hist_bins, context.hw->numHistogramBins }, + Histogram hist({ params->hist.hist_bins, context.hw.numHistogramBins }, [](uint32_t x) { return x >> 4; }); - expMeans_ = { params->ae.exp_mean, context.hw->numAeCells }; + expMeans_ = { params->ae.exp_mean, context.hw.numAeCells }; std::vector &modeWeights = meteringModes_.at(frameContext.agc.meteringMode); weights_ = { modeWeights.data(), modeWeights.size() }; diff --git a/src/ipa/rkisp1/algorithms/blc.cpp b/src/ipa/rkisp1/algorithms/blc.cpp index 98cb7145..32fc44ff 100644 --- a/src/ipa/rkisp1/algorithms/blc.cpp +++ b/src/ipa/rkisp1/algorithms/blc.cpp @@ -114,7 +114,7 @@ int BlackLevelCorrection::configure(IPAContext &context, * of the extensible parameters format. */ supported_ = context.configuration.paramFormat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS || - !context.hw->compand; + !context.hw.compand; if (!supported_) LOG(RkISP1Blc, Warning) @@ -140,7 +140,7 @@ void BlackLevelCorrection::prepare(IPAContext &context, if (!supported_) return; - if (context.hw->compand) { + if (context.hw.compand) { auto config = params->block(); config.setEnabled(true); diff --git a/src/ipa/rkisp1/algorithms/compress.cpp b/src/ipa/rkisp1/algorithms/compress.cpp index 6445cd14..2afa4496 100644 --- a/src/ipa/rkisp1/algorithms/compress.cpp +++ b/src/ipa/rkisp1/algorithms/compress.cpp @@ -51,7 +51,7 @@ int Compress::configure(IPAContext &context, [[maybe_unused]] const IPACameraSensorInfo &configInfo) { if (context.configuration.paramFormat != V4L2_META_FMT_RK_ISP1_EXT_PARAMS || - !context.hw->compand) { + !context.hw.compand) { LOG(RkISP1Compress, Warning) << "Compression is not supported by the hardware or kernel."; return 0; diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp index a9493678..a0e7030f 100644 --- a/src/ipa/rkisp1/algorithms/goc.cpp +++ b/src/ipa/rkisp1/algorithms/goc.cpp @@ -50,7 +50,7 @@ const float kDefaultGamma = 2.2f; */ int GammaOutCorrection::init(IPAContext &context, const YamlObject &tuningData) { - if (context.hw->numGammaOutSamples != + if (context.hw.numGammaOutSamples != RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10) { LOG(RkISP1Gamma, Error) << "Gamma is not implemented for RkISP1 V12"; @@ -101,7 +101,7 @@ void GammaOutCorrection::prepare(IPAContext &context, IPAFrameContext &frameContext, RkISP1Params *params) { - ASSERT(context.hw->numGammaOutSamples == + ASSERT(context.hw.numGammaOutSamples == RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10); if (!frameContext.goc.update) diff --git a/src/ipa/rkisp1/algorithms/lux.cpp b/src/ipa/rkisp1/algorithms/lux.cpp index dd05f18d..e8da6981 100644 --- a/src/ipa/rkisp1/algorithms/lux.cpp +++ b/src/ipa/rkisp1/algorithms/lux.cpp @@ -61,7 +61,7 @@ void Lux::process(IPAContext &context, /* \todo Deduplicate the histogram calculation from AGC */ const rkisp1_cif_isp_stat *params = &stats->params; - Histogram yHist({ params->hist.hist_bins, context.hw->numHistogramBins }, + Histogram yHist({ params->hist.hist_bins, context.hw.numHistogramBins }, [](uint32_t x) { return x >> 4; }); double lux = lux_.estimateLux(exposureTime, gain, 1.0, yHist); diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 35d25d55..67427c01 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -36,6 +36,7 @@ struct IPAHwSettings { unsigned int numHistogramBins; unsigned int numHistogramWeights; unsigned int numGammaOutSamples; + uint32_t supportedBlocks; bool compand; }; @@ -201,11 +202,11 @@ struct IPAFrameContext : public FrameContext { struct IPAContext { IPAContext(unsigned int frameContextSize) - : hw(nullptr), frameContexts(frameContextSize) + : frameContexts(frameContextSize) { } - const IPAHwSettings *hw; + IPAHwSettings hw; IPACameraSensorInfo sensorInfo; IPASessionConfiguration configuration; IPAActiveState activeState; diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index cf66d555..fa22bfc3 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -52,6 +52,7 @@ public: IPARkISP1(); int init(const IPASettings &settings, unsigned int hwRevision, + uint32_t supportedBlocks, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls) override; @@ -94,6 +95,7 @@ const IPAHwSettings ipaHwSettingsV10{ RKISP1_CIF_ISP_HIST_BIN_N_MAX_V10, RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE_V10, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10, + 0, false, }; @@ -102,6 +104,7 @@ const IPAHwSettings ipaHwSettingsIMX8MP{ RKISP1_CIF_ISP_HIST_BIN_N_MAX_V10, RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE_V10, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10, + 0, true, }; @@ -110,6 +113,7 @@ const IPAHwSettings ipaHwSettingsV12{ RKISP1_CIF_ISP_HIST_BIN_N_MAX_V12, RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE_V12, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V12, + 0, false, }; @@ -132,6 +136,7 @@ std::string IPARkISP1::logPrefix() const } int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision, + uint32_t supportedBlocks, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls) @@ -139,13 +144,13 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision, /* \todo Add support for other revisions */ switch (hwRevision) { case RKISP1_V10: - context_.hw = &ipaHwSettingsV10; + context_.hw = ipaHwSettingsV10; break; case RKISP1_V_IMX8MP: - context_.hw = &ipaHwSettingsIMX8MP; + context_.hw = ipaHwSettingsIMX8MP; break; case RKISP1_V12: - context_.hw = &ipaHwSettingsV12; + context_.hw = ipaHwSettingsV12; break; default: LOG(IPARkISP1, Error) @@ -153,6 +158,7 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision, << " is currently not supported"; return -ENODEV; } + context_.hw.supportedBlocks = supportedBlocks; LOG(IPARkISP1, Debug) << "Hardware revision is " << hwRevision; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index a91a443a..ecd13831 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -100,7 +100,7 @@ public: PipelineHandlerRkISP1 *pipe(); const PipelineHandlerRkISP1 *pipe() const; - int loadIPA(unsigned int hwRevision); + int loadIPA(unsigned int hwRevision, uint32_t supportedBlocks); Stream mainPathStream_; Stream selfPathStream_; @@ -383,7 +383,7 @@ const PipelineHandlerRkISP1 *RkISP1CameraData::pipe() const return static_cast(Camera::Private::pipe()); } -int RkISP1CameraData::loadIPA(unsigned int hwRevision) +int RkISP1CameraData::loadIPA(unsigned int hwRevision, uint32_t supportedBlocks) { ipa_ = IPAManager::createIPA(pipe(), 1, 1); if (!ipa_) @@ -405,7 +405,8 @@ int RkISP1CameraData::loadIPA(unsigned int hwRevision) } ret = ipa_->init({ ipaTuningFile, sensor_->model() }, hwRevision, - sensorInfo, sensor_->controls(), &ipaControls_); + supportedBlocks, sensorInfo, sensor_->controls(), + &ipaControls_); if (ret < 0) { LOG(RkISP1, Error) << "IPA initialization failure"; return ret; @@ -1313,6 +1314,12 @@ int PipelineHandlerRkISP1::updateControls(RkISP1CameraData *data) return 0; } +/* + * By default we assume all the blocks that were included in the first + * extensible parameters series are available. That is the lower 20bits. + */ +const uint32_t kDefaultExtParamsBlocks = 0xfffff; + int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) { int ret; @@ -1350,7 +1357,21 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) isp_->frameStart.connect(data->delayedCtrls_.get(), &DelayedControls::applyControls); - ret = data->loadIPA(media_->hwRevision()); + uint32_t supportedBlocks = kDefaultExtParamsBlocks; + + auto &controls = param_->controls(); + if (controls.find(RKISP1_CID_SUPPORTED_PARAMS_BLOCKS) != controls.end()) { + auto list = param_->getControls({ { RKISP1_CID_SUPPORTED_PARAMS_BLOCKS } }); + if (!list.empty()) + supportedBlocks = static_cast( + list.get(RKISP1_CID_SUPPORTED_PARAMS_BLOCKS) + .get()); + } else { + LOG(RkISP1, Error) + << "Failed to query supported params blocks. Falling back to defaults."; + } + + ret = data->loadIPA(media_->hwRevision(), supportedBlocks); if (ret) return ret;