From patchwork Mon Sep 14 14:53:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 28291 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 26C3AC327D for ; Mon, 14 Sep 2026 14:54:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 351D0686D8; Mon, 14 Sep 2026 16:54:07 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="YwJceHJo"; 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 F32EB686AF for ; Mon, 14 Sep 2026 16:53:56 +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 E4BAFC14; Mon, 14 Sep 2026 16:52:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789397537; bh=ngXmWFJCsCwdMWBp30ENqWIvhrKA6Vkok/uwBZarGJE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=YwJceHJo23rWm/pndNXGg+SItV3/Mt+mm8Bu2BZblXnSBlUZBeDTPKNmSKK3KkrdC gkpDLslj9De+wqSnw9U7gf7jBdRAFmx00CNtKbPqlx7gG+E3QsorNRmaXRdUO33AJr kuhBqwReg9N62/2+5Zp82VMgNWsET58njNmlIvCw= From: Daniel Scally Date: Mon, 14 Sep 2026 15:53:45 +0100 Subject: [PATCH v4 05/10] ipa: ipu3: ccm: Add a Colour Correction Matrix algorithm MIME-Version: 1.0 Message-Id: <20260914-ipu3-libipa-rework-v4-5-ff8ee2d3dd24@ideasonboard.com> References: <20260914-ipu3-libipa-rework-v4-0-ff8ee2d3dd24@ideasonboard.com> In-Reply-To: <20260914-ipu3-libipa-rework-v4-0-ff8ee2d3dd24@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Daniel Scally , Kieran Bingham , Jacopo Mondi X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=8248; i=dan.scally@ideasonboard.com; h=from:subject:message-id; bh=ngXmWFJCsCwdMWBp30ENqWIvhrKA6Vkok/uwBZarGJE=; b=owEBbQKS/ZANAwAKAchJV3psRXUyAcsmYgBqqAqB+s7d4Fw3+FrRHsD743DgWEtuCVtfrJTbt OsNtXotdIGJAjMEAAEKAB0WIQQqyuwyDnZdb+mxmm/ISVd6bEV1MgUCaqgKgQAKCRDISVd6bEV1 MkpaD/93w5XpTPod+mDBv7Hc3C4MvDEop2YuvVyQ9MoNnpduQjh0e+l7hD+OEh9tcRUn7zUmDre WODWfVZOIAyHGCPsoH4SoIv/abmadshU3ehyIJb33YllJBUS47jGLcVk+lHgAi//r4Uk6fVl7Cm zkNQ0YRkCcInYWJnybIZiCvs2gK7nCXXSOWjI7xeMJHqOuPWgvodPWWdrrVHar3CFaxTalqAshP 8R6yxL+MKYZhUFbPgJbxDeoJLxgubLGM5IJJ827QSaxqcOL7oWL1yv35MET75pX5M+zp7RpBZM4 YH78jfdlL3R7gfV7YOlUilIl+Jgat+07+KEIjwjoJzGqqD7P/OZQNaaFGfvt6ycP6W6ZyS6QPCr 9NQswNl8v8cKapYh9hwZUes5nSB34YuKN6mfCZCf3kXUGI8MXC+1nOM7DTOwJKteKkjYNTz0wME nHGom98iWdnJ7du0s22UG3mr+zZw3+9TmoOS0UVX1axX9sNBdlrj6R0rv18sBaH6iq2xmTUKo8H vWyuixdYEN43FcdEVmK/Iyj/ddzkBpy3hZ7AhNjKfO9DgomwJWDAsEXs820EmHacJviFR0+ZGoW +/DbBSeG0knhQxTvPOpwL9AQ4RY284GakUuN6rsQBEYqNM+UXft4y7L3DaSrc5cqyn/Ucq8YEHE +SYZcur50FHqQtw== 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. Reviewed-by: Kieran Bingham Reviewed-by: Jacopo Mondi Signed-off-by: Daniel Scally --- Changes in v4: - None Changes in v3: - None Changes in v2: - Fixed includes - Documentation comment rework - Some styling changes --- src/ipa/ipu3/algorithms/ccm.cpp | 116 ++++++++++++++++++++++++++++++++++++ src/ipa/ipu3/algorithms/ccm.h | 48 +++++++++++++++ src/ipa/ipu3/algorithms/meson.build | 1 + src/ipa/ipu3/ipa_context.cpp | 10 ++++ src/ipa/ipu3/ipa_context.h | 3 + 5 files changed, 178 insertions(+) diff --git a/src/ipa/ipu3/algorithms/ccm.cpp b/src/ipa/ipu3/algorithms/ccm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..105d815b03c45b4138b069a2f094d5ae4966c299 --- /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.colourTemperature); +} + +/** + * \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.colourTemperature); + + 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..9103de54b32b795d0efd22fad15ca6defb194057 --- /dev/null +++ b/src/ipa/ipu3/algorithms/ccm.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Ideas On Board + * + * IPU3 Colour correction matrix algorithm + */ + +#pragma once + +#include + +#include + +#include "libcamera/internal/value_node.h" + +#include +#include + +#include "algorithm.h" +#include "ipa_context.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 5cd8fedf27870474eb35745520206de885006b4a..5f5ac92955869898f072f5228524ca7ec8a02839 100644 --- a/src/ipa/ipu3/ipa_context.cpp +++ b/src/ipa/ipu3/ipa_context.cpp @@ -116,6 +116,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 IPAActiveState::toneMapping * \brief Context for ToneMapping and Gamma control @@ -152,4 +157,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 d2673b42bebb36dde06a795b6c1fbed6e9052535..5476a8ad0256dbb04d33fcd591b72d4b56a52897 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace libcamera { @@ -49,6 +50,7 @@ struct IPAActiveState { agc::ActiveState agc; ipa::awb::ActiveState awb; + ipa::ccm::ActiveState ccm; struct { double gamma; @@ -64,6 +66,7 @@ struct IPAFrameContext : public FrameContext { agc::FrameContext agc; ipa::awb::FrameContext awb; + ipa::ccm::FrameContext ccm; }; struct IPAContext {