From patchwork Fri Jul 3 12:25:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 27170 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 56C23C328C for ; Fri, 3 Jul 2026 12:26:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E360B65FE2; Fri, 3 Jul 2026 14:26:40 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="n6WsooLV"; 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 623C965FD8 for ; Fri, 3 Jul 2026 14:26:39 +0200 (CEST) Received: from neptunite.hamster-moth.ts.net (unknown [IPv6:2404:7a81:160:2100:a2cc:2f45:3bd7:2589]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 854B68E0; Fri, 3 Jul 2026 14:25:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1783081553; bh=VGh1iqBQr5zsnLh9R5lq1HZjJtvMAW93rS/keKbJcc8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=n6WsooLVLSjqCsjtksiLY7+AVNnazQgV60SdhWVL9a7ZcOWzlNTOCx3raKU96gDuj dvUv/k2VOBPCUcIekPg4Dshubkie+DG5U9+OwvOZacDbyJlzDugXWRY3WbxrHIv9yJ 5lMIXECxE8i6h3DT+mHQvp/5mCb0aFlrk4+6Zhkw= From: Paul Elder To: laurent.pinchart@ideasonboard.com Cc: Paul Elder , michael.riesch@collabora.com, xuhf@rock-chips.com, stefan.klug@ideasonboard.com, kieran.bingham@ideasonboard.com, dan.scally@ideasonboard.com, jacopo.mondi@ideasonboard.com, nicolas.dufresne@collabora.com, libcamera-devel@lists.libcamera.org Subject: [RFC PATCH 11/19] ipa: rkisp2: algo: ccm: Implement color correction matrix Date: Fri, 3 Jul 2026 21:25:17 +0900 Message-ID: <20260703122543.1991189-12-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20260703122543.1991189-1-paul.elder@ideasonboard.com> References: <20260703122543.1991189-1-paul.elder@ideasonboard.com> 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" Implement a color correction matrix control algorithm for the rkisp2 IPA. This uses the libipa color correction matrix algorithm. Signed-off-by: Paul Elder --- src/ipa/rkisp2/algorithms/ccm.cpp | 126 ++++++++++++++++++++++++++ src/ipa/rkisp2/algorithms/ccm.h | 57 ++++++++++++ src/ipa/rkisp2/algorithms/meson.build | 1 + 3 files changed, 184 insertions(+) create mode 100644 src/ipa/rkisp2/algorithms/ccm.cpp create mode 100644 src/ipa/rkisp2/algorithms/ccm.h diff --git a/src/ipa/rkisp2/algorithms/ccm.cpp b/src/ipa/rkisp2/algorithms/ccm.cpp new file mode 100644 index 000000000000..d9630ccf23bd --- /dev/null +++ b/src/ipa/rkisp2/algorithms/ccm.cpp @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Ideas On Board + * + * RkISP2 Color Correction Matrix control algorithm + */ + +#include "ccm.h" + +#include + +#include +#include + +#include + +#include + +#include "libipa/interpolator.h" + +/** + * \file ccm.h + * \brief RkISP2 CCM algorithm implementation + */ + +namespace libcamera { + +namespace ipa::rkisp2::algorithms { + +/** + * \class Ccm + * \brief RkISP2 color correction matrix algorithm + */ + +LOG_DEFINE_CATEGORY(RkISP2Ccm) + +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Ccm::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData) +{ + return ccmAlgo_.init(tuningData, context.ctrlMap); +} + +/** + * \copydoc libcamera::ipa::Algorithm::configure + */ +int Ccm::configure(IPAContext &context, + [[maybe_unused]] const IPACameraSensorInfo &configInfo) +{ + return ccmAlgo_.configure(context.activeState.ccm, + context.activeState.awb.automatic.temperatureK); +} + +void Ccm::queueRequest(IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) +{ + ccmAlgo_.queueRequest(context.activeState.ccm, frameContext.ccm, controls); +} + +void Ccm::setParameters(RkISP2Params *params, IPAFrameContext &context) +{ + const Matrix &matrix = context.ccm.ccm; + const Matrix &offsets = context.ccm.offsets; + + auto config = params->block(); + config.setEnabled(true); + + /* + * 4 bit integer and 7 bit fractional, ranging from -8 (0x400) to + * +7.9921875 (0x3ff) + */ + for (unsigned int i = 0; i < 3; i++) { + for (unsigned int j = 0; j < 3; j++) + config->coeff[i][j] = Q<4, 7>(matrix[i][j]).quantized(); + } + + for (unsigned int i = 0; i < 3; i++) + config->offset[i] = offsets[i][0] & 0xfff; + + config->y_coeff[0] = 0x26; + config->y_coeff[1] = 0x4b; + config->y_coeff[2] = 0x0f; + config->inflection_point = 0xa; + + for (unsigned int i = 0; i < 17; i++) + config->alp[i] = 0x400; + + /* \todo Support alp */ + + LOG(RkISP2Ccm, Debug) << "Setting matrix " << matrix; + LOG(RkISP2Ccm, Debug) << "Setting offsets " << offsets; +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Ccm::prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, RkISP2Params *params) +{ + if (frameContext.awb.autoEnabled) + 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 rkisp2_stats_buffer *stats, + ControlList &metadata) +{ + ccmAlgo_.process(frameContext.ccm, metadata); +} + +REGISTER_IPA_ALGORITHM(Ccm, "Ccm") + +} /* namespace ipa::rkisp2::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp2/algorithms/ccm.h b/src/ipa/rkisp2/algorithms/ccm.h new file mode 100644 index 000000000000..80a87e1c73d0 --- /dev/null +++ b/src/ipa/rkisp2/algorithms/ccm.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Ideas On Board + * + * RkISP2 Color Correction Matrix control algorithm + */ + +#pragma once + +#include + +#include + +#include "libcamera/internal/value_node.h" + +#include "libipa/ccm.h" +#include "libipa/fixedpoint.h" + +#include "algorithm.h" +#include "ipa_context.h" +#include "params.h" + +namespace libcamera { + +namespace ipa::rkisp2::algorithms { + +class Ccm : public Algorithm +{ +public: + Ccm() {} + ~Ccm() = default; + + int init(IPAContext &context, const ValueNode &tuningData) override; + int configure(IPAContext &context, + const IPACameraSensorInfo &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, + RkISP2Params *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const rkisp2_stats_buffer *stats, + ControlList &metadata) override; + +private: + void parseYaml(const ValueNode &tuningData); + void setParameters(RkISP2Params *params, IPAFrameContext &context); + + CcmAlgorithm> ccmAlgo_; +}; + +} /* namespace ipa::rkisp2::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp2/algorithms/meson.build b/src/ipa/rkisp2/algorithms/meson.build index 027e40dd0346..e7ae3d163bfb 100644 --- a/src/ipa/rkisp2/algorithms/meson.build +++ b/src/ipa/rkisp2/algorithms/meson.build @@ -4,5 +4,6 @@ rkisp2_ipa_algorithms = files([ 'agc.cpp', 'awb.cpp', 'bls.cpp', + 'ccm.cpp', ])