From patchwork Wed Aug 27 22:20:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 24250 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 557C3BEFBE for ; Wed, 27 Aug 2025 22:20:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EC6B5692EF; Thu, 28 Aug 2025 00:20:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=ragnatech.se header.i=@ragnatech.se header.b="OmGIQv90"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="PywQtpUS"; dkim-atps=neutral Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 557D8613B9 for ; Thu, 28 Aug 2025 00:20:39 +0200 (CEST) Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfout.stl.internal (Postfix) with ESMTP id C26901D00166; Wed, 27 Aug 2025 18:20:37 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-06.internal (MEProxy); Wed, 27 Aug 2025 18:20:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ragnatech.se; h= cc:cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:message-id:mime-version:reply-to :subject:subject:to:to; s=fm3; t=1756333237; x=1756419637; bh=Qp CtEUCsbeO46fOEL+qdBFUxhJ9l7FPU+UyZNWODveE=; b=OmGIQv90MDKjNlYBDr GaEOBK0F+hWgLxupL3KULeu6iu/SgrpT8VJmtSqHLjKk+FIutMKTiAo8+/k8yKY3 KDw2Jox6lj/9x5p3xTkGfcPw3gFnAN2zhZPcGkvZT0a6cDlpXuTzD09hmgUXbi+7 kuBx81zh54DwSj4F7RsVfC2R587jzceTZxIlhDQb7G7Wc+IjVo069GJbRp2yA1Rw Stp188pmhkrxikCNsZ8Ti7bxnlkvUDLMJqTlqm4TYcR2SCtqPVEuGte+6hTSm4+5 +pxuC2Bn/Hsw4dj6D9zQDByTUU/mfdFc/joteN8/gnHdX8JMx7PZZLpcTCHZs1nE jTcw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:message-id:mime-version:reply-to:subject :subject:to:to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; t=1756333237; x=1756419637; bh=QpCtEUCsbeO46fOEL+qdBFUxhJ9l 7FPU+UyZNWODveE=; b=PywQtpUSZygi4sUDxUX2Pi7bd14liTvqkM2+VtVDNtpq etb0lP3wQDAUWty2UiySJ7F+w44II05bg3qF18khKcNqjMWJ+oqjWU/OThL7QPzO BjoW0p1b9mXhnbtSDuDBkRtCcTEbDaaeCupHuXPhQZ4Nrz4wfQOg4LXF5+6CMEtN Qr/H4s4xEOpcR4ch8WpDUd06uuNUC/ZL8o2LyjmTgwGwApdQkmfL6IXSanjuznrM WICz6n1vaKrOTp8c/pVlJy/sXVC4VVznk0pF5qmaM7Qrb9Xq3fk0NCeAGtrBAEUq OkBuQkeHEBQ4goDCKPiI+hO7GxjS4GAHnd472zQ9aQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdefgddujeelfeefucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhephffvvefufffkofggtgfgsehtkeertdertdejnecuhfhrohhmpefpihhklhgrshcu ufpnuggvrhhluhhnugcuoehnihhklhgrshdrshhouggvrhhluhhnugdorhgvnhgvshgrsh esrhgrghhnrghtvggthhdrshgvqeenucggtffrrghtthgvrhhnpeehudelteetkefgffef udefuedvjeeivdekhfevieefgeffheeltddvvefhfeetgeenucevlhhushhtvghrufhiii gvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehnihhklhgrshdrshhouggvrhhluhhn ugesrhgrghhnrghtvggthhdrshgvpdhnsggprhgtphhtthhopeefpdhmohguvgepshhmth hpohhuthdprhgtphhtthhopehprghulhdrvghluggvrhesihguvggrshhonhgsohgrrhgu rdgtohhmpdhrtghpthhtoheplhhisggtrghmvghrrgdquggvvhgvlheslhhishhtshdrlh hisggtrghmvghrrgdrohhrghdprhgtphhtthhopehnihhklhgrshdrshhouggvrhhluhhn ugdorhgvnhgvshgrshesrhgrghhnrghtvggthhdrshgv X-ME-Proxy: Feedback-ID: i80c9496c:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 27 Aug 2025 18:20:36 -0400 (EDT) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: Paul Elder , libcamera-devel@lists.libcamera.org Cc: =?utf-8?q?Niklas_S=C3=B6derlund?= Subject: [PATCH] ipa: rkisp1: agc: awb: Apply digital gain using ISP Date: Thu, 28 Aug 2025 00:20:32 +0200 Message-ID: <20250827222032.644435-1-niklas.soderlund+renesas@ragnatech.se> X-Mailer: git-send-email 2.51.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" The digital gain is already calculated in the AGC algorithm but the value is not consumed by the AWB algorithm, which is where the gain stage is located. Add the needed plumbing to carry the value between the two algorithms. This is needed to get good images from sensors such as the IMX219 where large sensor frames needs a small VBLANK value. This results in images that are so under exposed that even the sensors analog gain can't compensate. The digital gain stage of the ISP helps with this. Signed-off-by: Niklas Söderlund --- src/ipa/rkisp1/algorithms/agc.cpp | 12 ++++++++++-- src/ipa/rkisp1/algorithms/awb.cpp | 4 +++- src/ipa/rkisp1/ipa_context.h | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 35440b67e999..17aaa259244b 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -174,9 +174,11 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) { /* Configure the default exposure and gain. */ context.activeState.agc.automatic.gain = context.configuration.sensor.minAnalogueGain; + context.activeState.agc.automatic.ispGain = 1.0; context.activeState.agc.automatic.exposure = 10ms / context.configuration.sensor.lineDuration; context.activeState.agc.manual.gain = context.activeState.agc.automatic.gain; + context.activeState.agc.manual.ispGain = 1.0; context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure; context.activeState.agc.autoExposureEnabled = !context.configuration.raw; context.activeState.agc.autoGainEnabled = !context.configuration.raw; @@ -280,8 +282,10 @@ void Agc::queueRequest(IPAContext &context, if (!frameContext.agc.autoExposureEnabled) frameContext.agc.exposure = agc.manual.exposure; - if (!frameContext.agc.autoGainEnabled) + if (!frameContext.agc.autoGainEnabled) { frameContext.agc.gain = agc.manual.gain; + frameContext.agc.ispGain = agc.manual.ispGain; + } const auto &meteringMode = controls.get(controls::AeMeteringMode); if (meteringMode) { @@ -336,12 +340,15 @@ void Agc::prepare(IPAContext &context, const uint32_t frame, { uint32_t activeAutoExposure = context.activeState.agc.automatic.exposure; double activeAutoGain = context.activeState.agc.automatic.gain; + double activeAutoIspGain = context.activeState.agc.automatic.ispGain; /* Populate exposure and gain in auto mode */ if (frameContext.agc.autoExposureEnabled) frameContext.agc.exposure = activeAutoExposure; - if (frameContext.agc.autoGainEnabled) + if (frameContext.agc.autoGainEnabled) { frameContext.agc.gain = activeAutoGain; + frameContext.agc.ispGain = activeAutoIspGain; + } /* * Populate manual exposure and gain from the active auto values when @@ -581,6 +588,7 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, /* Update the estimated exposure and gain. */ activeState.agc.automatic.exposure = newExposureTime / lineDuration; activeState.agc.automatic.gain = aGain; + activeState.agc.automatic.ispGain = dGain; /* * Expand the target frame duration so that we do not run faster than diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index 399fb51be414..569cac4a3466 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -218,7 +218,9 @@ void Awb::prepare(IPAContext &context, const uint32_t frame, */ if (frameContext.awb.autoEnabled) { const auto &awb = context.activeState.awb; - frameContext.awb.gains = awb.automatic.gains; + const auto &agc = context.activeState.agc; + + frameContext.awb.gains = awb.automatic.gains * agc.automatic.ispGain; frameContext.awb.temperatureK = awb.automatic.temperatureK; } diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 7ccc7b501aff..7180b0b7dff2 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -73,10 +73,12 @@ struct IPAActiveState { struct { uint32_t exposure; double gain; + double ispGain; } manual; struct { uint32_t exposure; double gain; + double ispGain; } automatic; bool autoExposureEnabled; @@ -130,6 +132,7 @@ struct IPAFrameContext : public FrameContext { struct { uint32_t exposure; double gain; + double ispGain; double exposureValue; uint32_t vblank; bool autoExposureEnabled;