From patchwork Fri Sep 19 09:40:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24423 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 D22CAC328C for ; Fri, 19 Sep 2025 09:41:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 16FA769369; Fri, 19 Sep 2025 11:41:40 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="P7+IFXD/"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 104146B5B9 for ; Fri, 19 Sep 2025 11:41:35 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:4d54:eab8:98ca:163b]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id B0299EFF; Fri, 19 Sep 2025 11:40:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1758274815; bh=bmSsIku7p9XKWO8vu2+aB9z0rvtjj+9wtxaELrf2Sl8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P7+IFXD/6ux4tKQY19wDhBMq9s3DQNrzBSNaR30M2/O5Gn5ZqTpqH5pklBdgtUWoD aiKyejvqaFAhDYooAR5+mU2UbLuh1d3kH/YCFeWOvVJiqS9L+v91P4mWudCX4b1NTX Ik1BFtQVMW+BqBSP6wIP86r/RmYZ7mmD9klLvBNA= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Kieran Bingham , Daniel Scally , Paul Elder Subject: [PATCH v5 14/19] pipeline: rkisp1: Query kernel for available params blocks Date: Fri, 19 Sep 2025 11:40:29 +0200 Message-ID: <20250919094041.183031-15-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250919094041.183031-1-stefan.klug@ideasonboard.com> References: <20250919094041.183031-1-stefan.klug@ideasonboard.com> 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" 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 --- Changes in v4: - Keep the static data const and create a copy of the configuration to be able to modify it. Changes in v3: - Removed unnecessary log statement - Collected tags - Added case for getControls() failing internally --- 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 043ad27ea199..068e898848c4 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 174d810edc65..d0337fd0027f 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 98cb7145e164..32fc44ffff92 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 6445cd14bae3..2afa449608b7 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 a9493678dba7..a0e7030fe5db 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 dd05f18d5e94..e8da69810008 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 35d25d555e65..67427c01ac68 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 cf66d5553dcd..fa22bfc34904 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 a91a443aeaf7..ecd13831539f 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;