From patchwork Tue Jun 16 06:41:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 26895 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 375DCBF415 for ; Tue, 16 Jun 2026 06:42:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B804C62401; Tue, 16 Jun 2026 08:41:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="dZc3Sj3w"; 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 9D9A9623FC for ; Tue, 16 Jun 2026 08:41:49 +0200 (CEST) Received: from [127.0.1.1] (chfd-03-b2-v4wan-176392-cust229.vm15.cable.virginm.net [82.19.20.230]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 60504166C; Tue, 16 Jun 2026 08:41:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1781592076; bh=XhrY9g+HIVbvhGzoKDTKfPqcr6KG/n9uBAajpkwSQcM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dZc3Sj3w7g+swN/kTVgO9/gH60mQPqkhmBCy6NWlBeXeQe4KsFnDdVnv4AxpmlcXS o69d4qhRDnE/ZUFsuvhKIJPOGrn3EtmcJrsnULHL0/+j0eZy0XWgCK+4bLlaQ23ruw sC0hm+02kZ9GUY0IvWWPI/O5H7AlFbbbW7vw/vNY= From: Daniel Scally Date: Tue, 16 Jun 2026 07:41:38 +0100 Subject: [PATCH 04/10] ipa: ipu3: ccm: Add a Colour Correction Matrix algorithm MIME-Version: 1.0 Message-Id: <20260616-ipu3-libipa-rework-v1-4-d4448b54f1d8@ideasonboard.com> References: <20260616-ipu3-libipa-rework-v1-0-d4448b54f1d8@ideasonboard.com> In-Reply-To: <20260616-ipu3-libipa-rework-v1-0-d4448b54f1d8@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Daniel Scally X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7766; i=dan.scally@ideasonboard.com; h=from:subject:message-id; bh=XhrY9g+HIVbvhGzoKDTKfPqcr6KG/n9uBAajpkwSQcM=; b=owEBbQKS/ZANAwAKAchJV3psRXUyAcsmYgBqMPApPrJ6LJ78559AyiZFIsPAUgT5ulDv19XF0 yD5tTzysbyJAjMEAAEKAB0WIQQqyuwyDnZdb+mxmm/ISVd6bEV1MgUCajDwKQAKCRDISVd6bEV1 Mu3SD/9MiGVHynuAViDiE4IRkMk8meJJ1/bmaFT/fIoOGGf8RLc5N+PAeJfXQoF0ASP0ehYWS3J o0k01Zx+5WaxOb9AswLCxk8xa87ZHbV4vuYC38r3ZHC+HdHUgX/r4jDkmfiY31KVlVk9XFTTg3q mbC5sBPOzy9sdTRJ6vLBxNizqVVVFmPh3BENpgfFO7FdRSZ/p3AtEEg9GGY1ZYIhC41vQxcXXhp o3cQdqyB7j5Xlk0XwNIzuXKLxT1oDi2dG/xPbzou7kkFQC9ju59Uir3e3rjNen7aX1bHpQrvmGT kToaGYxDEt1yBF6pJ4r2vUNSfYKOdIduq52uOg+0XNp87+OVkqkLh0pS9nelGXNDgCHwaBlpdfH XIHLe4u2KgrQfNpH/gcN9YIvPrVidvzPUmPTisV4LicinIccmMNaggFG+pxO0IjEV6ECnjUSMZg /0WhJsTch9RiftMb7GfzrEuge1Xsm5rj/3AkTT98zI3eIxM98K+7k7LMFBIsIpH+DBDhKmIzZuC eGhna8z8RdAEjImDQB+uwSjqx+nNqN5TcJ7D2Nem+19ANgWyUZT2cof9dDPZZP8Df7evtQsSy2/ n2Jv7O5qrg4xJhJRyutuCqYGEuNmL/1Mb2r4SQnhzkB1kXkSEFuXalJWPcngzWtnXyAffb8BxAJ idx3jWYNyauDWvA== X-Developer-Key: i=dan.scally@ideasonboard.com; a=openpgp; fpr=EEC699ACA1B7CB5D31330C0BBD501C2A3546CCF6 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" Add a Colour Correction Matrix algorithm that uses the new libipa implementation. The module isn't well documented in the kernel but the default values from the driver suggest a Q3.13 format. Signed-off-by: Daniel Scally --- src/ipa/ipu3/algorithms/ccm.cpp | 116 ++++++++++++++++++++++++++++++++++++ src/ipa/ipu3/algorithms/ccm.h | 43 +++++++++++++ src/ipa/ipu3/algorithms/meson.build | 1 + src/ipa/ipu3/ipa_context.cpp | 10 ++++ src/ipa/ipu3/ipa_context.h | 3 + 5 files changed, 173 insertions(+) diff --git a/src/ipa/ipu3/algorithms/ccm.cpp b/src/ipa/ipu3/algorithms/ccm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44b8c107b079c544c5afd1fce3cbe355f6dacd76 --- /dev/null +++ b/src/ipa/ipu3/algorithms/ccm.cpp @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Ideas On Board + * + * IPU3 Colour correction matrix algorithm + */ + +#include "ccm.h" + +/** + * \file ccm.h + */ + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +/** + * \class Ccm + * \brief The IPU3 color correction matrix algorithm + */ + +LOG_DEFINE_CATEGORY(IPU3Ccm) + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Ccm::init(IPAContext &context, const ValueNode &tuningData) +{ + return ccmAlgo_.init(tuningData, context.ctrlMap); +} + +/** + * \copydoc libcamera::ipa::Algorithm::configure + */ +int Ccm::configure(IPAContext &context, + [[maybe_unused]] const IPAConfigInfo &configInfo) +{ + return ccmAlgo_.configure(context.activeState.ccm, + context.activeState.awb.automatic.temperatureK); +} + +/** + * \copydoc libcamera::ipa::Algorithm::queueRequest + */ +void Ccm::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) +{ + /* Nothing to do here, the ccm will be calculated in prepare() */ + if (frameContext.awb.autoEnabled) + return; + + ccmAlgo_.queueRequest(context.activeState.ccm, frameContext.ccm, controls); +} + +void Ccm::setParameters(ipu3_uapi_params *params, IPAFrameContext &context) +{ + const Matrix &matrix = context.ccm.ccm; + const Matrix &offsets = context.ccm.offsets; + + params->use.acc_ccm = 1; + + params->acc_param.ccm.coeff_m11 = Q<3, 13>(matrix[0][0]).quantized(); + params->acc_param.ccm.coeff_m12 = Q<3, 13>(matrix[0][1]).quantized(); + params->acc_param.ccm.coeff_m13 = Q<3, 13>(matrix[0][2]).quantized(); + params->acc_param.ccm.coeff_o_r = offsets[0][0]; + + params->acc_param.ccm.coeff_m21 = Q<3, 13>(matrix[1][0]).quantized(); + params->acc_param.ccm.coeff_m22 = Q<3, 13>(matrix[1][1]).quantized(); + params->acc_param.ccm.coeff_m23 = Q<3, 13>(matrix[1][2]).quantized(); + params->acc_param.ccm.coeff_o_g = offsets[1][0]; + + params->acc_param.ccm.coeff_m31 = Q<3, 13>(matrix[2][0]).quantized(); + params->acc_param.ccm.coeff_m32 = Q<3, 13>(matrix[2][1]).quantized(); + params->acc_param.ccm.coeff_m33 = Q<3, 13>(matrix[2][2]).quantized(); + params->acc_param.ccm.coeff_o_b = offsets[2][0]; + + LOG(IPU3Ccm, Debug) << "Setting matrix " << matrix; + LOG(IPU3Ccm, Debug) << "Setting offsets " << offsets; +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Ccm::prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, ipu3_uapi_params *params) +{ + if (!frameContext.awb.autoEnabled) { + setParameters(params, frameContext); + return; + } + + ccmAlgo_.prepare(context.activeState.ccm, frameContext.ccm, frame, + frameContext.awb.temperatureK); + + setParameters(params, frameContext); +} + +/** + * \copydoc libcamera::ipa::Algorithm::process + */ +void Ccm::process([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + [[maybe_unused]] const ipu3_uapi_stats_3a *stats, + ControlList &metadata) +{ + ccmAlgo_.process(frameContext.ccm, metadata); +} + +REGISTER_IPA_ALGORITHM(Ccm, "Ccm") + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/ipu3/algorithms/ccm.h b/src/ipa/ipu3/algorithms/ccm.h new file mode 100644 index 0000000000000000000000000000000000000000..39719c986267aff02e3129aad9dbe4baeec8f8a1 --- /dev/null +++ b/src/ipa/ipu3/algorithms/ccm.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Ideas On Board + * + * IPU3 Colour correction matrix algorithm + */ + +#pragma once + +#include + +#include +#include + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +class Ccm : public Algorithm +{ +public: + int init(IPAContext &context, const ValueNode &tuningData) override; + int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; + void queueRequest(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) override; + void prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + ipu3_uapi_params *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const ipu3_uapi_stats_3a *stats, + ControlList &metadata) override; + +private: + void setParameters(ipu3_uapi_params *params, IPAFrameContext &context); + CcmAlgorithm> ccmAlgo_; +}; + +} /* namespace ipa::ipu3::algorithms */ +} /* namespace libcamera */ diff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build index b70a551cacf6cbdedf3ab41771a34ddcdae9fd8b..3dafd2fda9897942cf87d9640665c4fcff383859 100644 --- a/src/ipa/ipu3/algorithms/meson.build +++ b/src/ipa/ipu3/algorithms/meson.build @@ -5,5 +5,6 @@ ipu3_ipa_algorithms = files([ 'agc.cpp', 'awb.cpp', 'blc.cpp', + 'ccm.cpp', 'tone_mapping.cpp', ]) diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp index b35c925d959027c540257e47944047c238f85571..dc43bc0877ed5c2e7287414e12667374f5ee1c80 100644 --- a/src/ipa/ipu3/ipa_context.cpp +++ b/src/ipa/ipu3/ipa_context.cpp @@ -114,6 +114,11 @@ namespace libcamera::ipa::ipu3 { * \brief Active auto-white balance parameters for the IPA */ +/** + * \var IPAActiveState::ccm + * \brief Active colour Correction Matrix parameters for the IPA + */ + /** * \var IPASessionConfiguration::sensor * \brief Sensor-specific configuration of the IPA @@ -182,4 +187,9 @@ namespace libcamera::ipa::ipu3 { * \brief Per-frame auto-white balance parameters for the IPA */ +/** + * \var IPAFrameContext::ccm + * \brief Per-frame colour Correction Matrix parameters for the IPA + */ + } /* namespace libcamera::ipa::ipu3 */ diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index 245cf8b50b270a61df863e314128bede40d30541..be626d30d966b1bdaa322e5154f95f745f799976 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -16,6 +16,7 @@ #include #include +#include #include namespace libcamera { @@ -64,6 +65,7 @@ struct IPAActiveState { } agc; ipa::awb::ActiveState awb; + ipa::ccm::ActiveState ccm; struct { double gamma; @@ -78,6 +80,7 @@ struct IPAFrameContext : public FrameContext { } sensor; ipa::awb::FrameContext awb; + ipa::ccm::FrameContext ccm; }; struct IPAContext {