From patchwork Wed Jul 3 22:52:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 20567 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 5133FBEFBE for ; Wed, 3 Jul 2024 22:53:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 238FB63369; Thu, 4 Jul 2024 00:53:09 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DkSANe+1"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DF4BC63334 for ; Thu, 4 Jul 2024 00:52:56 +0200 (CEST) Received: from pendragon.ideasonboard.com (117.145-247-81.adsl-dyn.isp.belgacom.be [81.247.145.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 71BB74CC; Thu, 4 Jul 2024 00:52:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1720047148; bh=Kc72srql5yGTU3CFi0fNHVCGnkuMUnsFRzPOPTsFE+o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DkSANe+1YJc02tcwPYpkicnm0lvIOhmXs83Pl4fUyUMQnVLE1hsxV3SEc59/B2OOv TFSjzKhRlexS52pdzJ7Xn0cCtVZ3apuhy93KuzmSyloP5ybxrnGiiNybRJAna7vNyT H4fq4kKeVn8RfMu/aM6qdrwwsfSM/pS6K8QXMP9Q= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Paul Elder Subject: [PATCH v1 05/11] ipa: rkisp1: Add ISP parameters abstraction class Date: Thu, 4 Jul 2024 01:52:24 +0300 Message-ID: <20240703225230.3530-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.44.2 In-Reply-To: <20240703225230.3530-1-laurent.pinchart@ideasonboard.com> References: <20240703225230.3530-1-laurent.pinchart@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" Individual algorithms of the rkisp1 IPA module access their corresponding ISP parameters through the top-level structure rkisp1_params_cfg. This will not work anymore with the new parameters format. In order to ease the transition to the new format, abstract the ISP parameters in a new RkISP1Params class that offers the same interface regardless of the format. Signed-off-by: Laurent Pinchart --- src/ipa/rkisp1/meson.build | 1 + src/ipa/rkisp1/params.cpp | 169 +++++++++++++++++++++++++++++++++++++ src/ipa/rkisp1/params.h | 140 ++++++++++++++++++++++++++++++ 3 files changed, 310 insertions(+) create mode 100644 src/ipa/rkisp1/params.cpp create mode 100644 src/ipa/rkisp1/params.h diff --git a/src/ipa/rkisp1/meson.build b/src/ipa/rkisp1/meson.build index e8b266f1ccca..65eef5d69c32 100644 --- a/src/ipa/rkisp1/meson.build +++ b/src/ipa/rkisp1/meson.build @@ -7,6 +7,7 @@ ipa_name = 'ipa_rkisp1' rkisp1_ipa_sources = files([ 'ipa_context.cpp', + 'params.cpp', 'rkisp1.cpp', 'utils.cpp', ]) diff --git a/src/ipa/rkisp1/params.cpp b/src/ipa/rkisp1/params.cpp new file mode 100644 index 000000000000..ac25ade1c8c4 --- /dev/null +++ b/src/ipa/rkisp1/params.cpp @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * + * RkISP1 ISP Parameters + */ + +#include "params.h" + +#include +#include +#include + +#include +#include + +namespace libcamera { + +namespace ipa::rkisp1 { + +namespace { + +struct BlockTypeInfo { + enum rkisp1_ext_params_block_type type; + size_t size; + size_t offset; + __u32 enableBit; +}; + +#define RKISP1_BLOCK_TYPE_ENTRY(block, id, type, category, bit) \ + { Block::block, { \ + RKISP1_EXT_PARAMS_BLOCK_TYPE_##id, \ + sizeof(struct rkisp1_cif_isp_##type##_config), \ + offsetof(struct rkisp1_params_cfg, category.type##_config), \ + RKISP1_CIF_ISP_MODULE_##bit, \ + } } + +#define RKISP1_BLOCK_TYPE_ENTRY_MEAS(block, id, type) \ + RKISP1_BLOCK_TYPE_ENTRY(block, id##_MEAS, type, meas, id) + +#define RKISP1_BLOCK_TYPE_ENTRY_OTHERS(block, id, type) \ + RKISP1_BLOCK_TYPE_ENTRY(block, id, type, others, id) + +#define RKISP1_BLOCK_TYPE_ENTRY_EXT(block, id, type) \ + { Block::block, { \ + RKISP1_EXT_PARAMS_BLOCK_TYPE_##id, \ + sizeof(struct rkisp1_cif_isp_##type##_config), \ + 0, 0, \ + } } + +const std::map kBlockTypeInfo = { + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Bls, BLS, bls), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Dpcc, DPCC, dpcc), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Sdg, SDG, sdg), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(AwbGain, AWB_GAIN, awb_gain), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Flt, FLT, flt), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Bdm, BDM, bdm), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Ctk, CTK, ctk), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Goc, GOC, goc), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Dpf, DPF, dpf), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(DpfStrength, DPF_STRENGTH, dpf_strength), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Cproc, CPROC, cproc), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Ie, IE, ie), + RKISP1_BLOCK_TYPE_ENTRY_OTHERS(Lsc, LSC, lsc), + RKISP1_BLOCK_TYPE_ENTRY_MEAS(Awb, AWB, awb_meas), + RKISP1_BLOCK_TYPE_ENTRY_MEAS(Hst, HST, hst), + RKISP1_BLOCK_TYPE_ENTRY_MEAS(Aec, AEC, aec), + RKISP1_BLOCK_TYPE_ENTRY_MEAS(Afc, AFC, afc), +}; + +} /* namespace */ + +RkISP1Params::RkISP1Params(uint32_t format, Span data) + : format_(format), data_(data), used_(0) +{ + if (format_ == V4L2_META_FMT_RK_ISP1_EXT_PARAMS) { + struct rkisp1_ext_params_cfg *cfg = + reinterpret_cast(data.data()); + + cfg->version = RKISP1_EXT_PARAM_BUFFER_V1; + cfg->data_size = 0; + + used_ += offsetof(struct rkisp1_ext_params_cfg, data); + } else { + memset(data.data(), 0, data.size()); + used_ = sizeof(struct rkisp1_params_cfg); + } +} + +Span RkISP1Params::block(Block type, State state) +{ + auto infoIt = kBlockTypeInfo.find(type); + if (infoIt == kBlockTypeInfo.end()) + return {}; + + const BlockTypeInfo &info = infoIt->second; + + /* + * For the legacy format, return a block referencing the fixed location + * of the data. + */ + if (format_ == V4L2_META_FMT_RK_ISP1_PARAMS) { + /* + * Blocks available in extended parameters only have an offset + * of 0. Return nullptr in that case. + */ + if (info.offset == 0) + return {}; + + struct rkisp1_params_cfg *cfg = + reinterpret_cast(data_.data()); + + cfg->module_cfg_update = info.enableBit; + cfg->module_en_update = info.enableBit; + cfg->module_ens = state == State::Enable ? info.enableBit : 0; + + return data_.subspan(info.offset, info.size); + } + + /* + * For the extensible format, allocate memory for the block, including + * the header. + */ + + /* Look up the block in the cache first. Caching helps providing the + * same behaviour for the legacy and extensible formats when block() is + * called multiple times for the same block, which simplifies the + * implementation of algorithms and avoids hard to debug issues. + */ + auto cacheIt = blocks_.find(type); + if (cacheIt != blocks_.end()) + return cacheIt->second; + + /* Make sure we don't run out of space. */ + size_t size = sizeof(struct rkisp1_ext_params_block_header) + + ((info.size + 7) & ~7); + if (size > data_.size() - used_) + return {}; + + /* Allocate a new block, clear its memory, and initialize its header. */ + Span block = data_.subspan(used_, size); + used_ += size; + + struct rkisp1_ext_params_cfg *cfg = + reinterpret_cast(data_.data()); + cfg->data_size += size; + + memset(block.data(), 0, block.size()); + + struct rkisp1_ext_params_block_header *header = + reinterpret_cast(block.data()); + header->type = info.type; + header->enable = state == State::Enable + ? RKISP1_EXT_PARAMS_BLOCK_ENABLE + : RKISP1_EXT_PARAMS_BLOCK_DISABLE; + header->size = block.size(); + + /* Skip the block header to get the data. */ + block = block.subspan(sizeof(*header)); + + /* Update the cache. */ + blocks_[type] = block; + + return block; +} + +} /* namespace ipa::rkisp1 */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/params.h b/src/ipa/rkisp1/params.h new file mode 100644 index 000000000000..ddd081de7894 --- /dev/null +++ b/src/ipa/rkisp1/params.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * + * RkISP1 ISP Parameters + */ + +#pragma once + +#include +#include +#include + +#include + +#include + +namespace libcamera { + +namespace ipa::rkisp1 { + +enum class Block { + Bls, + Dpcc, + Sdg, + AwbGain, + Flt, + Bdm, + Ctk, + Goc, + Dpf, + DpfStrength, + Cproc, + Ie, + Lsc, + Awb, + Hst, + Aec, + Afc, +}; + +namespace details { + +template +struct block_type { +}; + +#define RKISP1_DEFINE_BLOCK_TYPE(blockType, blockStruct) \ +template<> \ +struct block_type { \ + using type = struct rkisp1_cif_isp_##blockStruct##_config; \ +}; + +RKISP1_DEFINE_BLOCK_TYPE(Bls, bls) +RKISP1_DEFINE_BLOCK_TYPE(Dpcc, dpcc) +RKISP1_DEFINE_BLOCK_TYPE(Sdg, sdg) +RKISP1_DEFINE_BLOCK_TYPE(AwbGain, awb_gain) +RKISP1_DEFINE_BLOCK_TYPE(Flt, flt) +RKISP1_DEFINE_BLOCK_TYPE(Bdm, bdm) +RKISP1_DEFINE_BLOCK_TYPE(Ctk, ctk) +RKISP1_DEFINE_BLOCK_TYPE(Goc, goc) +RKISP1_DEFINE_BLOCK_TYPE(Dpf, dpf) +RKISP1_DEFINE_BLOCK_TYPE(DpfStrength, dpf_strength) +RKISP1_DEFINE_BLOCK_TYPE(Cproc, cproc) +RKISP1_DEFINE_BLOCK_TYPE(Ie, ie) +RKISP1_DEFINE_BLOCK_TYPE(Lsc, lsc) +RKISP1_DEFINE_BLOCK_TYPE(Awb, awb_meas) +RKISP1_DEFINE_BLOCK_TYPE(Hst, hst) +RKISP1_DEFINE_BLOCK_TYPE(Aec, aec) +RKISP1_DEFINE_BLOCK_TYPE(Afc, afc) + +} /* namespace details */ + +template +class RkISP1ParamsBlock +{ +public: + using Type = typename details::block_type::type; + + RkISP1ParamsBlock(const Span &data) + : data_(data) + { + } + + const Type *operator->() const + { + return reinterpret_cast(data_.data()); + } + + Type *operator->() + { + return reinterpret_cast(data_.data()); + } + + const Type &operator*() const & + { + return *reinterpret_cast(data_.data()); + } + + Type &operator*() & + { + return *reinterpret_cast(data_.data()); + } + +private: + Span data_; +}; + +class RkISP1Params +{ +public: + enum class State { + Disable = 1, + Enable = 1, + }; + + RkISP1Params(uint32_t format, Span data); + + template + RkISP1ParamsBlock block(State state) + { + return RkISP1ParamsBlock(block(B, state)); + } + + size_t size() const { return used_; } + +private: + Span block(Block type, State state); + + uint32_t format_; + + Span data_; + size_t used_; + + std::map> blocks_; +}; + +} /* namespace ipa::rkisp1 */ + +} /* namespace libcamera*/