From patchwork Sat Oct 31 18:40:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 28732 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 E8070C3261 for ; Sat, 31 Oct 2026 18:41:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5D3F469157; Sat, 31 Oct 2026 19:41:13 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="ReWFu4Ue"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9E8856914F for ; Sat, 31 Oct 2026 19:41:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1793472067; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iVh8OxiP2DB2YgTJTwmaET0iiaDwQhUHqsegUm5kr98=; b=ReWFu4Ue094Mnu9HlyMXggkEZa20rG1g7n/ZojVRg/P17Hb1JuvmyPa7sGdOvVoPqi3fKi HyIN3DfMEvGfwejIJk0lOMBv0BY3KnddpyarbMcIPfZu8MwnHTAlQjVWovuewhp53awpTE Er4aaG/9aMJsJVN0t8wrSYL6Okk6DKI= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-85-6UpkkboPPR2yWzOOE8nwMQ-1; Sat, 31 Oct 2026 14:41:05 -0400 X-MC-Unique: 6UpkkboPPR2yWzOOE8nwMQ-1 X-Mimecast-MFC-AGG-ID: 6UpkkboPPR2yWzOOE8nwMQ_1793472064 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7375C1802157; Sat, 31 Oct 2026 18:41:04 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.csb (headnet04.pony-001.prod.iad2.dc.redhat.com [10.2.32.116]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D973618005BA; Sat, 31 Oct 2026 18:41:02 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , =?utf-8?b?QmFybmFiw6FzIFDFkWN6?= =?utf-8?q?e?= , Kieran Bingham , Robert Mader Subject: [PATCH v2 7/8] libcamera: software_isp: Add autofocus controls Date: Sat, 31 Oct 2026 19:40:39 +0100 Message-ID: <20261031184040.20139-8-mzamazal@redhat.com> In-Reply-To: <20261031184040.20139-1-mzamazal@redhat.com> References: <20261031184040.20139-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: u7NRCsyXb4lFm6sw4gyiLNdLbiyu0cwrNpzxlYzktXM_1793472064 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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" In order to support focusing operations, lens controls are set up and passed around, similarly to the sensor controls. Currently, the only control used, and only if the sensor supports autofocus, is V4L2_CID_FOCUS_ABSOLUTE. Instead of serializing the whole lens ControList in setSensorControls, we could pass around just the value. But using the ControlList is more consistent with what we do with the sensor controls and what is done in ipu3 pipeline. Additionally, it's ready for possibly amending the controls in future; we might end up having to determine between V4L2_CID_FOCUS_ABSOLUTE or V4L2_CID_FOCUS_RELATIVE, or V4L2_CID_FOCUS_AUTO settings. Signed-off-by: Milan Zamazal --- .../libcamera/internal/software_isp/software_isp.h | 4 ++-- include/libcamera/ipa/softisp.mojom | 3 ++- src/ipa/softisp/ipa_context.h | 1 + src/ipa/softisp/softisp.cpp | 7 ++++++- src/libcamera/pipeline/simple/simple.cpp | 13 +++++++++++-- src/libcamera/software_isp/software_isp.cpp | 4 ++-- 6 files changed, 24 insertions(+), 8 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index b64910637..be90a229a 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -87,11 +87,11 @@ public: Signal outputBufferReady; Signal ispStatsReady; Signal metadataReady; - Signal setSensorControls; + Signal setSensorControls; private: void saveIspParams(uint32_t frame); - void setSensorCtrls(const ControlList &sensorControls); + void setSensorCtrls(const ControlList &sensorControls, const ControlList &lensControls); void statsReady(uint32_t frame, uint32_t bufferId); void inputReady(FrameBuffer *input); void outputReady(FrameBuffer *output); diff --git a/include/libcamera/ipa/softisp.mojom b/include/libcamera/ipa/softisp.mojom index e42742ed7..833f4440b 100644 --- a/include/libcamera/ipa/softisp.mojom +++ b/include/libcamera/ipa/softisp.mojom @@ -10,6 +10,7 @@ import "include/libcamera/ipa/core.mojom"; struct IPAConfigInfo { libcamera.ControlInfoMap sensorControls; + libcamera.ControlInfoMap lensControls; }; interface IPASoftIspInterface { @@ -34,7 +35,7 @@ interface IPASoftIspInterface { }; interface IPASoftIspEventInterface { - setSensorControls(libcamera.ControlList sensorControls); + setSensorControls(libcamera.ControlList sensorControls, libcamera.ControlList lensControls); paramsComputed(uint32 frame); metadataReady(uint32 frame, libcamera.ControlList metadata); }; diff --git a/src/ipa/softisp/ipa_context.h b/src/ipa/softisp/ipa_context.h index 39823261c..73b145cab 100644 --- a/src/ipa/softisp/ipa_context.h +++ b/src/ipa/softisp/ipa_context.h @@ -84,6 +84,7 @@ struct IPAContext { IPACameraSensorInfo sensorInfo; ControlInfoMap sensorControls; + ControlInfoMap lensControls; std::unique_ptr camHelper; IPASessionConfiguration configuration; IPAActiveState activeState; diff --git a/src/ipa/softisp/softisp.cpp b/src/ipa/softisp/softisp.cpp index 00249a300..e96a8d596 100644 --- a/src/ipa/softisp/softisp.cpp +++ b/src/ipa/softisp/softisp.cpp @@ -27,6 +27,7 @@ #include "libcamera/internal/yaml_parser.h" #include "algorithms/adjust.h" +#include "libipa/af.h" #include "libipa/agc.h" #include "libipa/camera_sensor_helper.h" @@ -192,6 +193,7 @@ int IPASoftIsp::init(const IPASettings &settings, int IPASoftIsp::configure(const IPAConfigInfo &configInfo, ControlInfoMap *ipaControls) { context_.sensorControls = configInfo.sensorControls; + context_.lensControls = configInfo.lensControls; /* Clear the IPA context before the streaming session. */ context_.configuration = {}; @@ -256,7 +258,10 @@ void IPASoftIsp::processStats(const uint32_t frame, ControlList ctrls(context_.sensorControls); agc::prepareControls(ctrls, context_.camHelper.get(), frameContext.agc.exposure, frameContext.agc.gain); - setSensorControls.emit(ctrls); + ControlList lensCtrls(context_.lensControls); + if (context_.afEnabled) + af::prepareControls(lensCtrls, context_.activeState.af.focus); + setSensorControls.emit(ctrls, lensCtrls); } std::string IPASoftIsp::logPrefix() const diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 35e066499..4eaccaf01 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -34,6 +34,7 @@ #include #include "libcamera/internal/camera.h" +#include "libcamera/internal/camera_lens.h" #include "libcamera/internal/camera_manager.h" #include "libcamera/internal/camera_sensor.h" #include "libcamera/internal/camera_sensor_properties.h" @@ -374,7 +375,7 @@ private: void ispStatsReady(uint32_t frame, uint32_t bufferId); void metadataReady(uint32_t frame, const ControlList &metadata); - void setSensorControls(const ControlList &sensorControls); + void setSensorControls(const ControlList &sensorControls, const ControlList &lensControls); }; class SimpleCameraConfiguration : public CameraConfiguration @@ -1046,7 +1047,7 @@ void SimpleCameraData::metadataReady(uint32_t frame, const ControlList &metadata tryCompleteRequest(info->request); } -void SimpleCameraData::setSensorControls(const ControlList &sensorControls) +void SimpleCameraData::setSensorControls(const ControlList &sensorControls, const ControlList &lensControls) { delayedCtrls_->push(sensorControls); /* @@ -1060,6 +1061,12 @@ void SimpleCameraData::setSensorControls(const ControlList &sensorControls) if (!frameStartEmitter_) { ControlList ctrls(sensorControls); sensor_->setControls(&ctrls); + + CameraLens *lens = sensor_->focusLens(); + if (lens && lensControls.contains(V4L2_CID_FOCUS_ABSOLUTE)) { + ControlValue const &focusValue = lensControls.get(V4L2_CID_FOCUS_ABSOLUTE); + lens->setFocusPosition(focusValue.get()); + } } } @@ -1652,6 +1659,8 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) } else { ipa::softisp::IPAConfigInfo configInfo; configInfo.sensorControls = data->sensor_->controls(); + if (data->sensor_->focusLens()) + configInfo.lensControls = data->sensor_->focusLens()->controls(); return data->swIsp_->configure(inputCfg, outputCfgs, configInfo, &data->controlInfo_); } } diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 627625b4f..53ae3d76f 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -443,9 +443,9 @@ void SoftwareIsp::saveIspParams([[maybe_unused]] uint32_t frame) debayerParams_ = *sharedParams_; } -void SoftwareIsp::setSensorCtrls(const ControlList &sensorControls) +void SoftwareIsp::setSensorCtrls(const ControlList &sensorControls, const ControlList &lensControls) { - setSensorControls.emit(sensorControls); + setSensorControls.emit(sensorControls, lensControls); } void SoftwareIsp::statsReady(uint32_t frame, uint32_t bufferId)