From patchwork Wed Jan 14 17:39:13 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 25808 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 32283C32E0 for ; Wed, 14 Jan 2026 17:39:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AD96C61FD3; Wed, 14 Jan 2026 18:39:40 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Nq2Bu8rQ"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5F91B61FD3 for ; Wed, 14 Jan 2026 18:39:26 +0100 (CET) Received: from Monstersaurus.infra.iob (cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7395A287D; Wed, 14 Jan 2026 18:38:59 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1768412339; bh=G4tGhqZOlaCD71sTSW2BmCA+2eytL6hyl6sEqgU4aHo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Nq2Bu8rQ+Yz5F71lNDwORrLTFLT5uyEtWU4fodyphw9GwZZZVJ0NzOmHGvhkTFoqE Hg6KVFUBhx+CTfiPvNqjpCKay5kPEUxS5AfqxxCkxP6/7tSUoPN9ZTCxtaJlDaE464 ijDqoXIkWZiU57zPVKSUOE6y1t8qV7RvK8m6XW2A= From: Kieran Bingham To: libcamera devel Cc: Kieran Bingham , Isaac Scott Subject: [PATCH v5 13/16] ipa: mali-c55: agc: Quantise the ISP Digital Gain Date: Wed, 14 Jan 2026 17:39:13 +0000 Message-ID: <20260114173918.1744023-14-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260114173918.1744023-1-kieran.bingham@ideasonboard.com> References: <20260114173918.1744023-1-kieran.bingham@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" The Mali-C55 ISP has a digital gain block which allows setting gain in Q5.8 format, a range of 0.0 to (very nearly) 32.0. Convert usage to the new UQ<5, 8> FixedPoint Quantised type which will support the conversion, clamping and quantisation so that the metadata and debug prints can now report the effective gain applied instead of the potentially inaccurate float. As the UQ<5, 8> type already clamps values, remove the explicit clamping. This removes the clamping to a minimum of 1.0 gain, so we rely on calculateNewEv to provide a valid gain. Reviewed-by: Isaac Scott Signed-off-by: Kieran Bingham --- v5: - Use UQ<5, 8> type directly. - Use operator<< to report the UQ<5, 8> value. Signed-off-by: Kieran Bingham --- src/ipa/mali-c55/algorithms/agc.cpp | 18 +++++++++--------- src/ipa/mali-c55/ipa_context.h | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index 014fd12452ac..075717f44ea6 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -38,8 +38,8 @@ static constexpr unsigned int kNumHistogramBins = 256; * format, a range of 0.0 to (very nearly) 32.0. We clamp from 1.0 to the actual * max value which is 8191 * 2^-8. */ -static constexpr double kMinDigitalGain = 1.0; -static constexpr double kMaxDigitalGain = 31.99609375; +static constexpr float kMinDigitalGain = 1.0; +static constexpr float kMaxDigitalGain = UQ<5, 8>::TraitsType::max; uint32_t AgcStatistics::decodeBinValue(uint16_t binVal) { @@ -245,7 +245,7 @@ void Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContext, MaliC55Params *params) { IPAActiveState &activeState = context.activeState; - double gain; + UQ<5, 8> gain; if (activeState.agc.autoEnabled) gain = activeState.agc.automatic.ispGain; @@ -253,7 +253,7 @@ void Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContext, gain = activeState.agc.manual.ispGain; auto block = params->block(); - block->gain = floatingToFixedPoint<5, 8, uint16_t, double>(gain); + block->gain = gain.quantized(); frameContext.agc.ispGain = gain; } @@ -358,7 +358,7 @@ void Agc::process(IPAContext &context, */ uint32_t exposure = frameContext.agc.exposure; double analogueGain = frameContext.agc.sensorGain; - double digitalGain = frameContext.agc.ispGain; + double digitalGain = frameContext.agc.ispGain.value(); double totalGain = analogueGain * digitalGain; utils::Duration currentShutter = exposure * configuration.sensor.lineDuration; utils::Duration effectiveExposureValue = currentShutter * totalGain; @@ -370,19 +370,19 @@ void Agc::process(IPAContext &context, activeState.agc.exposureMode, statistics_.yHist, effectiveExposureValue); - dGain = std::clamp(dGain, kMinDigitalGain, kMaxDigitalGain); + UQ<5, 8> dGainQ = static_cast(dGain); LOG(MaliC55Agc, Debug) << "Divided up shutter, analogue gain and digital gain are " - << shutterTime << ", " << aGain << " and " << dGain; + << shutterTime << ", " << aGain << " and " << dGainQ; activeState.agc.automatic.exposure = shutterTime / configuration.sensor.lineDuration; activeState.agc.automatic.sensorGain = aGain; - activeState.agc.automatic.ispGain = dGain; + activeState.agc.automatic.ispGain = dGainQ; metadata.set(controls::ExposureTime, currentShutter.get()); metadata.set(controls::AnalogueGain, frameContext.agc.sensorGain); - metadata.set(controls::DigitalGain, frameContext.agc.ispGain); + metadata.set(controls::DigitalGain, frameContext.agc.ispGain.value()); metadata.set(controls::ColourTemperature, context.activeState.agc.temperatureK); } diff --git a/src/ipa/mali-c55/ipa_context.h b/src/ipa/mali-c55/ipa_context.h index 08f78e4f74ce..ac4b83773803 100644 --- a/src/ipa/mali-c55/ipa_context.h +++ b/src/ipa/mali-c55/ipa_context.h @@ -41,12 +41,12 @@ struct IPAActiveState { struct { uint32_t exposure; double sensorGain; - double ispGain; + UQ<5, 8> ispGain; } automatic; struct { uint32_t exposure; double sensorGain; - double ispGain; + UQ<5, 8> ispGain; } manual; bool autoEnabled; uint32_t constraintMode; @@ -64,7 +64,7 @@ struct IPAFrameContext : public FrameContext { struct { uint32_t exposure; double sensorGain; - double ispGain; + UQ<5, 8> ispGain; } agc; struct {