{"id":26895,"url":"https://patchwork.libcamera.org/api/patches/26895/?format=json","web_url":"https://patchwork.libcamera.org/patch/26895/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260616-ipu3-libipa-rework-v1-4-d4448b54f1d8@ideasonboard.com>","date":"2026-06-16T06:41:38","name":"[04/10] ipa: ipu3: ccm: Add a Colour Correction Matrix algorithm","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"f0803d717e490c5032967618d9d43baab6cbfc51","submitter":{"id":156,"url":"https://patchwork.libcamera.org/api/people/156/?format=json","name":"Dan Scally","email":"dan.scally@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/26895/mbox/","series":[{"id":5995,"url":"https://patchwork.libcamera.org/api/series/5995/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5995","date":"2026-06-16T06:41:34","name":"libipa: Re-work IPU3 IPA to use libipa algorithms","version":1,"mbox":"https://patchwork.libcamera.org/series/5995/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/26895/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/26895/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 375DCBF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 16 Jun 2026 06:42:02 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B804C62401;\n\tTue, 16 Jun 2026 08:41:54 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9D9A9623FC\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 16 Jun 2026 08:41:49 +0200 (CEST)","from [127.0.1.1]\n\t(chfd-03-b2-v4wan-176392-cust229.vm15.cable.virginm.net\n\t[82.19.20.230])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 60504166C;\n\tTue, 16 Jun 2026 08:41:16 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"dZc3Sj3w\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1781592076;\n\tbh=XhrY9g+HIVbvhGzoKDTKfPqcr6KG/n9uBAajpkwSQcM=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=dZc3Sj3w7g+swN/kTVgO9/gH60mQPqkhmBCy6NWlBeXeQe4KsFnDdVnv4AxpmlcXS\n\to69d4qhRDnE/ZUFsuvhKIJPOGrn3EtmcJrsnULHL0/+j0eZy0XWgCK+4bLlaQ23ruw\n\tsC0hm+02kZ9GUY0IvWWPI/O5H7AlFbbbW7vw/vNY=","From":"Daniel Scally <dan.scally@ideasonboard.com>","Date":"Tue, 16 Jun 2026 07:41:38 +0100","Subject":"[PATCH 04/10] ipa: ipu3: ccm: Add a Colour Correction Matrix\n\talgorithm","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","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 <dan.scally@ideasonboard.com>","X-Mailer":"b4 0.14.2","X-Developer-Signature":"v=1; a=openpgp-sha256; l=7766;\n\ti=dan.scally@ideasonboard.com; h=from:subject:message-id;\n\tbh=XhrY9g+HIVbvhGzoKDTKfPqcr6KG/n9uBAajpkwSQcM=;\n\tb=owEBbQKS/ZANAwAKAchJV3psRXUyAcsmYgBqMPApPrJ6LJ78559AyiZFIsPAUgT5ulDv19XF0\n\tyD5tTzysbyJAjMEAAEKAB0WIQQqyuwyDnZdb+mxmm/ISVd6bEV1MgUCajDwKQAKCRDISVd6bEV1\n\tMu3SD/9MiGVHynuAViDiE4IRkMk8meJJ1/bmaFT/fIoOGGf8RLc5N+PAeJfXQoF0ASP0ehYWS3J\n\to0k01Zx+5WaxOb9AswLCxk8xa87ZHbV4vuYC38r3ZHC+HdHUgX/r4jDkmfiY31KVlVk9XFTTg3q\n\tmbC5sBPOzy9sdTRJ6vLBxNizqVVVFmPh3BENpgfFO7FdRSZ/p3AtEEg9GGY1ZYIhC41vQxcXXhp\n\to3cQdqyB7j5Xlk0XwNIzuXKLxT1oDi2dG/xPbzou7kkFQC9ju59Uir3e3rjNen7aX1bHpQrvmGT\n\tkToaGYxDEt1yBF6pJ4r2vUNSfYKOdIduq52uOg+0XNp87+OVkqkLh0pS9nelGXNDgCHwaBlpdfH\n\tXIHLe4u2KgrQfNpH/gcN9YIvPrVidvzPUmPTisV4LicinIccmMNaggFG+pxO0IjEV6ECnjUSMZg\n\t/0WhJsTch9RiftMb7GfzrEuge1Xsm5rj/3AkTT98zI3eIxM98K+7k7LMFBIsIpH+DBDhKmIzZuC\n\teGhna8z8RdAEjImDQB+uwSjqx+nNqN5TcJ7D2Nem+19ANgWyUZT2cof9dDPZZP8Df7evtQsSy2/\n\tn2Jv7O5qrg4xJhJRyutuCqYGEuNmL/1Mb2r4SQnhzkB1kXkSEFuXalJWPcngzWtnXyAffb8BxAJ\n\tidx3jWYNyauDWvA==","X-Developer-Key":"i=dan.scally@ideasonboard.com; a=openpgp;\n\tfpr=EEC699ACA1B7CB5D31330C0BBD501C2A3546CCF6","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Add a Colour Correction Matrix algorithm that uses the new libipa\nimplementation. The module isn't well documented in the kernel but\nthe default values from the driver suggest a Q3.13 format.\n\nSigned-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n---\n src/ipa/ipu3/algorithms/ccm.cpp     | 116 ++++++++++++++++++++++++++++++++++++\n src/ipa/ipu3/algorithms/ccm.h       |  43 +++++++++++++\n src/ipa/ipu3/algorithms/meson.build |   1 +\n src/ipa/ipu3/ipa_context.cpp        |  10 ++++\n src/ipa/ipu3/ipa_context.h          |   3 +\n 5 files changed, 173 insertions(+)","diff":"diff --git a/src/ipa/ipu3/algorithms/ccm.cpp b/src/ipa/ipu3/algorithms/ccm.cpp\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..44b8c107b079c544c5afd1fce3cbe355f6dacd76\n--- /dev/null\n+++ b/src/ipa/ipu3/algorithms/ccm.cpp\n@@ -0,0 +1,116 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2026, Ideas On Board\n+ *\n+ * IPU3 Colour correction matrix algorithm\n+ */\n+\n+#include \"ccm.h\"\n+\n+/**\n+ * \\file ccm.h\n+ */\n+\n+namespace libcamera {\n+\n+namespace ipa::ipu3::algorithms {\n+\n+/**\n+ * \\class Ccm\n+ * \\brief The IPU3 color correction matrix algorithm\n+ */\n+\n+LOG_DEFINE_CATEGORY(IPU3Ccm)\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::init\n+ */\n+int Ccm::init(IPAContext &context, const ValueNode &tuningData)\n+{\n+\treturn ccmAlgo_.init(tuningData, context.ctrlMap);\n+}\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::configure\n+ */\n+int Ccm::configure(IPAContext &context,\n+\t\t   [[maybe_unused]] const IPAConfigInfo &configInfo)\n+{\n+\treturn ccmAlgo_.configure(context.activeState.ccm,\n+\t\t\t\t  context.activeState.awb.automatic.temperatureK);\n+}\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::queueRequest\n+ */\n+void Ccm::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n+\t\t       IPAFrameContext &frameContext,\n+\t\t       const ControlList &controls)\n+{\n+\t/* Nothing to do here, the ccm will be calculated in prepare() */\n+\tif (frameContext.awb.autoEnabled)\n+\t\treturn;\n+\n+\tccmAlgo_.queueRequest(context.activeState.ccm, frameContext.ccm, controls);\n+}\n+\n+void Ccm::setParameters(ipu3_uapi_params *params, IPAFrameContext &context)\n+{\n+\tconst Matrix<float, 3, 3> &matrix = context.ccm.ccm;\n+\tconst Matrix<int16_t, 3, 1> &offsets = context.ccm.offsets;\n+\n+\tparams->use.acc_ccm = 1;\n+\n+\tparams->acc_param.ccm.coeff_m11 = Q<3, 13>(matrix[0][0]).quantized();\n+\tparams->acc_param.ccm.coeff_m12 = Q<3, 13>(matrix[0][1]).quantized();\n+\tparams->acc_param.ccm.coeff_m13 = Q<3, 13>(matrix[0][2]).quantized();\n+\tparams->acc_param.ccm.coeff_o_r = offsets[0][0];\n+\n+\tparams->acc_param.ccm.coeff_m21 = Q<3, 13>(matrix[1][0]).quantized();\n+\tparams->acc_param.ccm.coeff_m22 = Q<3, 13>(matrix[1][1]).quantized();\n+\tparams->acc_param.ccm.coeff_m23 = Q<3, 13>(matrix[1][2]).quantized();\n+\tparams->acc_param.ccm.coeff_o_g = offsets[1][0];\n+\n+\tparams->acc_param.ccm.coeff_m31 = Q<3, 13>(matrix[2][0]).quantized();\n+\tparams->acc_param.ccm.coeff_m32 = Q<3, 13>(matrix[2][1]).quantized();\n+\tparams->acc_param.ccm.coeff_m33 = Q<3, 13>(matrix[2][2]).quantized();\n+\tparams->acc_param.ccm.coeff_o_b = offsets[2][0];\n+\n+\tLOG(IPU3Ccm, Debug) << \"Setting matrix \" << matrix;\n+\tLOG(IPU3Ccm, Debug) << \"Setting offsets \" << offsets;\n+}\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::prepare\n+ */\n+void Ccm::prepare(IPAContext &context, const uint32_t frame,\n+\t\t  IPAFrameContext &frameContext, ipu3_uapi_params *params)\n+{\n+\tif (!frameContext.awb.autoEnabled) {\n+\t\tsetParameters(params, frameContext);\n+\t\treturn;\n+\t}\n+\n+\tccmAlgo_.prepare(context.activeState.ccm, frameContext.ccm, frame,\n+\t\t\t frameContext.awb.temperatureK);\n+\n+\tsetParameters(params, frameContext);\n+}\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::process\n+ */\n+void Ccm::process([[maybe_unused]] IPAContext &context,\n+\t\t  [[maybe_unused]] const uint32_t frame,\n+\t\t  IPAFrameContext &frameContext,\n+\t\t  [[maybe_unused]] const ipu3_uapi_stats_3a *stats,\n+\t\t  ControlList &metadata)\n+{\n+\tccmAlgo_.process(frameContext.ccm, metadata);\n+}\n+\n+REGISTER_IPA_ALGORITHM(Ccm, \"Ccm\")\n+\n+} /* namespace ipa::ipu3::algorithms */\n+\n+} /* namespace libcamera */\ndiff --git a/src/ipa/ipu3/algorithms/ccm.h b/src/ipa/ipu3/algorithms/ccm.h\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..39719c986267aff02e3129aad9dbe4baeec8f8a1\n--- /dev/null\n+++ b/src/ipa/ipu3/algorithms/ccm.h\n@@ -0,0 +1,43 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2026, Ideas On Board\n+ *\n+ * IPU3 Colour correction matrix algorithm\n+ */\n+\n+#pragma once\n+\n+#include <linux/intel-ipu3.h>\n+\n+#include <libipa/ccm.h>\n+#include <libipa/fixedpoint.h>\n+\n+#include \"algorithm.h\"\n+\n+namespace libcamera {\n+\n+namespace ipa::ipu3::algorithms {\n+\n+class Ccm : public Algorithm\n+{\n+public:\n+\tint init(IPAContext &context, const ValueNode &tuningData) override;\n+\tint configure(IPAContext &context, const IPAConfigInfo &configInfo) override;\n+\tvoid queueRequest(IPAContext &context, const uint32_t frame,\n+\t\t\t  IPAFrameContext &frameContext,\n+\t\t\t  const ControlList &controls) override;\n+\tvoid prepare(IPAContext &context, const uint32_t frame,\n+\t\t     IPAFrameContext &frameContext,\n+\t\t     ipu3_uapi_params *params) override;\n+\tvoid process(IPAContext &context, const uint32_t frame,\n+\t\t     IPAFrameContext &frameContext,\n+\t\t     const ipu3_uapi_stats_3a *stats,\n+\t\t     ControlList &metadata) override;\n+\n+private:\n+\tvoid setParameters(ipu3_uapi_params *params, IPAFrameContext &context);\n+\tCcmAlgorithm<Q<3, 13>> ccmAlgo_;\n+};\n+\n+} /* namespace ipa::ipu3::algorithms */\n+} /* namespace libcamera */\ndiff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build\nindex b70a551cacf6cbdedf3ab41771a34ddcdae9fd8b..3dafd2fda9897942cf87d9640665c4fcff383859 100644\n--- a/src/ipa/ipu3/algorithms/meson.build\n+++ b/src/ipa/ipu3/algorithms/meson.build\n@@ -5,5 +5,6 @@ ipu3_ipa_algorithms = files([\n     'agc.cpp',\n     'awb.cpp',\n     'blc.cpp',\n+    'ccm.cpp',\n     'tone_mapping.cpp',\n ])\ndiff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp\nindex b35c925d959027c540257e47944047c238f85571..dc43bc0877ed5c2e7287414e12667374f5ee1c80 100644\n--- a/src/ipa/ipu3/ipa_context.cpp\n+++ b/src/ipa/ipu3/ipa_context.cpp\n@@ -114,6 +114,11 @@ namespace libcamera::ipa::ipu3 {\n  * \\brief Active auto-white balance parameters for the IPA\n  */\n \n+/**\n+ * \\var IPAActiveState::ccm\n+ * \\brief Active colour Correction Matrix parameters for the IPA\n+ */\n+\n /**\n  * \\var IPASessionConfiguration::sensor\n  * \\brief Sensor-specific configuration of the IPA\n@@ -182,4 +187,9 @@ namespace libcamera::ipa::ipu3 {\n  * \\brief Per-frame auto-white balance parameters for the IPA\n  */\n \n+/**\n+ * \\var IPAFrameContext::ccm\n+ * \\brief Per-frame colour Correction Matrix parameters for the IPA\n+ */\n+\n } /* namespace libcamera::ipa::ipu3 */\ndiff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h\nindex 245cf8b50b270a61df863e314128bede40d30541..be626d30d966b1bdaa322e5154f95f745f799976 100644\n--- a/src/ipa/ipu3/ipa_context.h\n+++ b/src/ipa/ipu3/ipa_context.h\n@@ -16,6 +16,7 @@\n #include <libcamera/geometry.h>\n \n #include <libipa/awb.h>\n+#include <libipa/ccm.h>\n #include <libipa/fc_queue.h>\n \n namespace libcamera {\n@@ -64,6 +65,7 @@ struct IPAActiveState {\n \t} agc;\n \n \tipa::awb::ActiveState awb;\n+\tipa::ccm::ActiveState ccm;\n \n \tstruct {\n \t\tdouble gamma;\n@@ -78,6 +80,7 @@ struct IPAFrameContext : public FrameContext {\n \t} sensor;\n \n \tipa::awb::FrameContext awb;\n+\tipa::ccm::FrameContext ccm;\n };\n \n struct IPAContext {\n","prefixes":["04/10"]}