Patch Detail
Show a patch.
GET /api/1.1/patches/21852/?format=api
{ "id": 21852, "url": "https://patchwork.libcamera.org/api/1.1/patches/21852/?format=api", "web_url": "https://patchwork.libcamera.org/patch/21852/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20241107114819.57599-6-dan.scally@ideasonboard.com>", "date": "2024-11-07T11:48:13", "name": "[v3,05/11] ipa: mali-c55: Add Mali-C55 ISP IPA module", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "2faa214b00e4663afca461e44ab1ccd9c6eb8a23", "submitter": { "id": 156, "url": "https://patchwork.libcamera.org/api/1.1/people/156/?format=api", "name": "Dan Scally", "email": "dan.scally@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/21852/mbox/", "series": [ { "id": 4777, "url": "https://patchwork.libcamera.org/api/1.1/series/4777/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4777", "date": "2024-11-07T11:48:08", "name": "Add Mali-C55 IPA Module and Algorithms", "version": 3, "mbox": "https://patchwork.libcamera.org/series/4777/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/21852/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/21852/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 BD990C32A9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 7 Nov 2024 11:48:39 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 626BB65496;\n\tThu, 7 Nov 2024 12:48:36 +0100 (CET)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9BAF66547A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 7 Nov 2024 12:48:28 +0100 (CET)", "from mail.ideasonboard.com\n\t(cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 796AABDB;\n\tThu, 7 Nov 2024 12:48:19 +0100 (CET)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"QP4BnYGe\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1730980099;\n\tbh=2ssG2N+hh25jYM71myIZSwYnRWck7rRM4XLDtfVGDoE=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=QP4BnYGelSQJQmEv2p4HLD54FYTvu/02Uj3SF1tthUOz27WywsWXjUpGz8AGPx7MF\n\tWmVMshlO02DuoJ6ZOWc6uJotv+8Jc4z54M753lqVzOCMNSnR8RC0ECEz6EGGvv+yhJ\n\t6T8YilktXUDpDb5Z0EIzK3jp8NwjNc1i3z6f7psU=", "From": "Daniel Scally <dan.scally@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Anthony.McGivern@arm.com, Daniel Scally <dan.scally@ideasonboard.com>,\n\tNayden Kanchev <nayden.kanchev@arm.com>,\n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>", "Subject": "[PATCH v3 05/11] ipa: mali-c55: Add Mali-C55 ISP IPA module", "Date": "Thu, 7 Nov 2024 11:48:13 +0000", "Message-Id": "<20241107114819.57599-6-dan.scally@ideasonboard.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20241107114819.57599-1-dan.scally@ideasonboard.com>", "References": "<20241107114819.57599-1-dan.scally@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "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 barebones IPA module for the Mali-C55 ISP. In this initial\nimplementation pretty much only buffer plumbing is implemented.\n\nAcked-by: Nayden Kanchev <nayden.kanchev@arm.com>\nCo-developed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\nSigned-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n---\nChanges in v3:\n\n\t- Fixed some parameter naming inconsistency\n\nChanges in v2:\n\n\t- None\n\n Documentation/Doxyfile-common.in | 1 +\n include/libcamera/ipa/mali-c55.mojom | 34 +++\n include/libcamera/ipa/meson.build | 1 +\n meson_options.txt | 2 +-\n src/ipa/mali-c55/algorithms/algorithm.h | 39 +++\n src/ipa/mali-c55/algorithms/meson.build | 4 +\n src/ipa/mali-c55/data/meson.build | 8 +\n src/ipa/mali-c55/data/uncalibrated.yaml | 6 +\n src/ipa/mali-c55/ipa_context.cpp | 101 +++++++\n src/ipa/mali-c55/ipa_context.h | 42 +++\n src/ipa/mali-c55/mali-c55.cpp | 339 ++++++++++++++++++++++++\n src/ipa/mali-c55/meson.build | 33 +++\n src/ipa/mali-c55/module.h | 27 ++\n 13 files changed, 636 insertions(+), 1 deletion(-)\n create mode 100644 include/libcamera/ipa/mali-c55.mojom\n create mode 100644 src/ipa/mali-c55/algorithms/algorithm.h\n create mode 100644 src/ipa/mali-c55/algorithms/meson.build\n create mode 100644 src/ipa/mali-c55/data/meson.build\n create mode 100644 src/ipa/mali-c55/data/uncalibrated.yaml\n create mode 100644 src/ipa/mali-c55/ipa_context.cpp\n create mode 100644 src/ipa/mali-c55/ipa_context.h\n create mode 100644 src/ipa/mali-c55/mali-c55.cpp\n create mode 100644 src/ipa/mali-c55/meson.build\n create mode 100644 src/ipa/mali-c55/module.h", "diff": "diff --git a/Documentation/Doxyfile-common.in b/Documentation/Doxyfile-common.in\nindex a70aee43..045c19dd 100644\n--- a/Documentation/Doxyfile-common.in\n+++ b/Documentation/Doxyfile-common.in\n@@ -32,6 +32,7 @@ RECURSIVE = YES\n EXCLUDE_PATTERNS = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \\\n @TOP_BUILDDIR@/include/libcamera/ipa/*_proxy.h \\\n @TOP_BUILDDIR@/include/libcamera/ipa/ipu3_*.h \\\n+ @TOP_BUILDDIR@/include/libcamera/ipa/mali-c55_*.h \\\n @TOP_BUILDDIR@/include/libcamera/ipa/raspberrypi_*.h \\\n @TOP_BUILDDIR@/include/libcamera/ipa/rkisp1_*.h \\\n @TOP_BUILDDIR@/include/libcamera/ipa/vimc_*.h\ndiff --git a/include/libcamera/ipa/mali-c55.mojom b/include/libcamera/ipa/mali-c55.mojom\nnew file mode 100644\nindex 00000000..5d7eb4ee\n--- /dev/null\n+++ b/include/libcamera/ipa/mali-c55.mojom\n@@ -0,0 +1,34 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+\n+module ipa.mali_c55;\n+\n+import \"include/libcamera/ipa/core.mojom\";\n+\n+struct IPAConfigInfo {\n+\tlibcamera.IPACameraSensorInfo sensorInfo;\n+\tlibcamera.ControlInfoMap sensorControls;\n+};\n+\n+interface IPAMaliC55Interface {\n+\tinit(libcamera.IPASettings settings, IPAConfigInfo configInfo)\n+\t\t=> (int32 ret, libcamera.ControlInfoMap ipaControls);\n+\tstart() => (int32 ret);\n+\tstop();\n+\n+\tconfigure(IPAConfigInfo configInfo, uint8 bayerOrder)\n+\t\t=> (int32 ret, libcamera.ControlInfoMap ipaControls);\n+\n+\tmapBuffers(array<libcamera.IPABuffer> buffers, bool readOnly);\n+\tunmapBuffers(array<libcamera.IPABuffer> buffers);\n+\n+\t[async] queueRequest(uint32 request, libcamera.ControlList reqControls);\n+\t[async] fillParams(uint32 request, uint32 bufferId);\n+\t[async] processStats(uint32 request, uint32 bufferId,\n+\t\t\t libcamera.ControlList sensorControls);\n+};\n+\n+interface IPAMaliC55EventInterface {\n+\tparamsComputed(uint32 request);\n+\tstatsProcessed(uint32 request, libcamera.ControlList metadata);\n+\tsetSensorControls(libcamera.ControlList sensorControls);\n+};\ndiff --git a/include/libcamera/ipa/meson.build b/include/libcamera/ipa/meson.build\nindex bf55e124..3129f119 100644\n--- a/include/libcamera/ipa/meson.build\n+++ b/include/libcamera/ipa/meson.build\n@@ -64,6 +64,7 @@ libcamera_ipa_headers += custom_target('core_ipa_serializer_h',\n # Mapping from pipeline handler name to mojom file\n pipeline_ipa_mojom_mapping = {\n 'ipu3': 'ipu3.mojom',\n+ 'mali-c55': 'mali-c55.mojom',\n 'rkisp1': 'rkisp1.mojom',\n 'rpi/vc4': 'raspberrypi.mojom',\n 'simple': 'soft.mojom',\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 7aa41249..5365601c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -32,7 +32,7 @@ option('gstreamer',\n \n option('ipas',\n type : 'array',\n- choices : ['ipu3', 'rkisp1', 'rpi/vc4', 'simple', 'vimc'],\n+ choices : ['ipu3', 'mali-c55', 'rkisp1', 'rpi/vc4', 'simple', 'vimc'],\n description : 'Select which IPA modules to build')\n \n option('lc-compliance',\ndiff --git a/src/ipa/mali-c55/algorithms/algorithm.h b/src/ipa/mali-c55/algorithms/algorithm.h\nnew file mode 100644\nindex 00000000..36a3bff0\n--- /dev/null\n+++ b/src/ipa/mali-c55/algorithms/algorithm.h\n@@ -0,0 +1,39 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024, Ideas On Board\n+ *\n+ * algorithm.h - Mali-C55 control algorithm interface\n+ */\n+\n+#pragma once\n+\n+#include <linux/mali-c55-config.h>\n+\n+#include <libipa/algorithm.h>\n+\n+#include \"module.h\"\n+\n+namespace libcamera {\n+\n+namespace ipa::mali_c55 {\n+\n+class Algorithm : public libcamera::ipa::Algorithm<Module>\n+{\n+};\n+\n+union mali_c55_params_block {\n+\tstruct mali_c55_params_block_header *header;\n+\tstruct mali_c55_params_sensor_off_preshading *sensor_offs;\n+\tstruct mali_c55_params_aexp_hist *aexp_hist;\n+\tstruct mali_c55_params_aexp_weights *aexp_weights;\n+\tstruct mali_c55_params_digital_gain *digital_gain;\n+\tstruct mali_c55_params_awb_gains *awb_gains;\n+\tstruct mali_c55_params_awb_config *awb_config;\n+\tstruct mali_c55_params_mesh_shading_config *shading_config;\n+\tstruct mali_c55_params_mesh_shading_selection *shading_selection;\n+\t__u8 *data;\n+};\n+\n+} /* namespace ipa::mali_c55 */\n+\n+} /* namespace libcamera */\ndiff --git a/src/ipa/mali-c55/algorithms/meson.build b/src/ipa/mali-c55/algorithms/meson.build\nnew file mode 100644\nindex 00000000..f2203b15\n--- /dev/null\n+++ b/src/ipa/mali-c55/algorithms/meson.build\n@@ -0,0 +1,4 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+mali_c55_ipa_algorithms = files([\n+])\ndiff --git a/src/ipa/mali-c55/data/meson.build b/src/ipa/mali-c55/data/meson.build\nnew file mode 100644\nindex 00000000..88109d17\n--- /dev/null\n+++ b/src/ipa/mali-c55/data/meson.build\n@@ -0,0 +1,8 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+conf_files = files([\n+ 'uncalibrated.yaml'\n+])\n+\n+install_data(conf_files,\n+ install_dir : ipa_data_dir / 'mali-c55')\ndiff --git a/src/ipa/mali-c55/data/uncalibrated.yaml b/src/ipa/mali-c55/data/uncalibrated.yaml\nnew file mode 100644\nindex 00000000..2cdc39a8\n--- /dev/null\n+++ b/src/ipa/mali-c55/data/uncalibrated.yaml\n@@ -0,0 +1,6 @@\n+# SPDX-License-Identifier: CC0-1.0\n+%YAML 1.1\n+---\n+version: 1\n+algorithms:\n+...\ndiff --git a/src/ipa/mali-c55/ipa_context.cpp b/src/ipa/mali-c55/ipa_context.cpp\nnew file mode 100644\nindex 00000000..99f76ecd\n--- /dev/null\n+++ b/src/ipa/mali-c55/ipa_context.cpp\n@@ -0,0 +1,101 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024, Ideas On Board\n+ *\n+ * ipa_context.cpp - MaliC55 IPA Context\n+ */\n+\n+#include \"ipa_context.h\"\n+\n+/**\n+ * \\file ipa_context.h\n+ * \\brief Context and state information shared between the algorithms\n+ */\n+\n+namespace libcamera::ipa::mali_c55 {\n+\n+/**\n+ * \\struct IPASessionConfiguration\n+ * \\brief Session configuration for the IPA module\n+ *\n+ * The session configuration contains all IPA configuration parameters that\n+ * remain constant during the capture session, from IPA module start to stop.\n+ * It is typically set during the configure() operation of the IPA module, but\n+ * may also be updated in the start() operation.\n+ */\n+\n+/**\n+ * \\struct IPAActiveState\n+ * \\brief Active state for algorithms\n+ *\n+ * The active state contains all algorithm-specific data that needs to be\n+ * maintained by algorithms across frames. Unlike the session configuration,\n+ * the active state is mutable and constantly updated by algorithms. The active\n+ * state is accessible through the IPAContext structure.\n+ *\n+ * The active state stores two distinct categories of information:\n+ *\n+ * - The consolidated value of all algorithm controls. Requests passed to\n+ * the queueRequest() function store values for controls that the\n+ * application wants to modify for that particular frame, and the\n+ * queueRequest() function updates the active state with those values.\n+ * The active state thus contains a consolidated view of the value of all\n+ * controls handled by the algorithm.\n+ *\n+ * - The value of parameters computed by the algorithm when running in auto\n+ * mode. Algorithms running in auto mode compute new parameters every\n+ * time statistics buffers are received (either synchronously, or\n+ * possibly in a background thread). The latest computed value of those\n+ * parameters is stored in the active state in the process() function.\n+ *\n+ * Each of the members in the active state belongs to a specific algorithm. A\n+ * member may be read by any algorithm, but shall only be written by its owner.\n+ */\n+\n+/**\n+ * \\struct IPAFrameContext\n+ * \\brief Per-frame context for algorithms\n+ *\n+ * The frame context stores two distinct categories of information:\n+ *\n+ * - The value of the controls to be applied to the frame. These values are\n+ * typically set in the queueRequest() function, from the consolidated\n+ * control values stored in the active state. The frame context thus stores\n+ * values for all controls related to the algorithm, not limited to the\n+ * controls specified in the corresponding request, but consolidated from all\n+ * requests that have been queued so far.\n+ *\n+ * For controls that can be set manually or computed by an algorithm\n+ * (depending on the algorithm operation mode), such as for instance the\n+ * colour gains for the AWB algorithm, the control value will be stored in\n+ * the frame context in the queueRequest() function only when operating in\n+ * manual mode. When operating in auto mode, the values are computed by the\n+ * algorithm in process(), stored in the active state, and copied to the\n+ * frame context in prepare(), just before being stored in the ISP parameters\n+ * buffer.\n+ *\n+ * The queueRequest() function can also store ancillary data in the frame\n+ * context, such as flags to indicate if (and what) control values have\n+ * changed compared to the previous request.\n+ *\n+ * - Status information computed by the algorithm for a frame. For instance,\n+ * the colour temperature estimated by the AWB algorithm from ISP statistics\n+ * calculated on a frame is stored in the frame context for that frame in\n+ * the process() function.\n+ */\n+\n+/**\n+ * \\struct IPAContext\n+ * \\brief Global IPA context data shared between all algorithms\n+ *\n+ * \\var IPAContext::configuration\n+ * \\brief The IPA session configuration, immutable during the session\n+ *\n+ * \\var IPAContext::activeState\n+ * \\brief The IPA active state, storing the latest state for all algorithms\n+ *\n+ * \\var IPAContext::frameContexts\n+ * \\brief Ring buffer of per-frame contexts\n+ */\n+\n+} /* namespace libcamera::ipa::mali_c55 */\ndiff --git a/src/ipa/mali-c55/ipa_context.h b/src/ipa/mali-c55/ipa_context.h\nnew file mode 100644\nindex 00000000..9e408a17\n--- /dev/null\n+++ b/src/ipa/mali-c55/ipa_context.h\n@@ -0,0 +1,42 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024, Ideas On Board\n+ *\n+ * ipa_context.h - Mali-C55 IPA Context\n+ */\n+\n+#pragma once\n+\n+#include <libcamera/controls.h>\n+\n+#include <libipa/fc_queue.h>\n+\n+namespace libcamera {\n+\n+namespace ipa::mali_c55 {\n+\n+struct IPASessionConfiguration {\n+};\n+\n+struct IPAActiveState {\n+};\n+\n+struct IPAFrameContext : public FrameContext {\n+\tstruct {\n+\t\tuint32_t exposure;\n+\t\tdouble sensorGain;\n+\t} agc;\n+};\n+\n+struct IPAContext {\n+\tIPASessionConfiguration configuration;\n+\tIPAActiveState activeState;\n+\n+\tFCQueue<IPAFrameContext> frameContexts;\n+\n+\tControlInfoMap::Map ctrlMap;\n+};\n+\n+} /* namespace ipa::mali_c55 */\n+\n+} /* namespace libcamera*/\ndiff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp\nnew file mode 100644\nindex 00000000..7efc0124\n--- /dev/null\n+++ b/src/ipa/mali-c55/mali-c55.cpp\n@@ -0,0 +1,339 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2023, Ideas on Board Oy\n+ *\n+ * mali-c55.cpp - Mali-C55 ISP image processing algorithms\n+ */\n+\n+#include <map>\n+#include <string.h>\n+#include <vector>\n+\n+#include <linux/mali-c55-config.h>\n+#include <linux/v4l2-controls.h>\n+\n+#include <libcamera/base/file.h>\n+#include <libcamera/base/log.h>\n+\n+#include <libcamera/control_ids.h>\n+#include <libcamera/ipa/ipa_interface.h>\n+#include <libcamera/ipa/ipa_module_info.h>\n+#include <libcamera/ipa/mali-c55_ipa_interface.h>\n+\n+#include \"libcamera/internal/bayer_format.h\"\n+#include \"libcamera/internal/mapped_framebuffer.h\"\n+#include \"libcamera/internal/yaml_parser.h\"\n+\n+#include \"algorithms/algorithm.h\"\n+#include \"libipa/camera_sensor_helper.h\"\n+\n+#include \"ipa_context.h\"\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(IPAMaliC55)\n+\n+namespace ipa::mali_c55 {\n+\n+/* Maximum number of frame contexts to be held */\n+static constexpr uint32_t kMaxFrameContexts = 16;\n+\n+class IPAMaliC55 : public IPAMaliC55Interface, public Module\n+{\n+public:\n+\tIPAMaliC55();\n+\n+\tint init(const IPASettings &settings, const IPAConfigInfo &ipaConfig,\n+\t\t ControlInfoMap *ipaControls) override;\n+\tint start() override;\n+\tvoid stop() override;\n+\tint configure(const IPAConfigInfo &ipaConfig, uint8_t bayerOrder,\n+\t\t ControlInfoMap *ipaControls) override;\n+\tvoid mapBuffers(const std::vector<IPABuffer> &buffers, bool readOnly) override;\n+\tvoid unmapBuffers(const std::vector<IPABuffer> &buffers) override;\n+\tvoid queueRequest(const uint32_t request, const ControlList &controls) override;\n+\tvoid fillParams(unsigned int request, uint32_t bufferId) override;\n+\tvoid processStats(unsigned int request, unsigned int bufferId,\n+\t\t\t const ControlList &sensorControls) override;\n+\n+protected:\n+\tstd::string logPrefix() const override;\n+\n+private:\n+\tvoid updateControls(const IPACameraSensorInfo &sensorInfo,\n+\t\t\t const ControlInfoMap &sensorControls,\n+\t\t\t ControlInfoMap *ipaControls);\n+\tvoid setControls();\n+\n+\tstd::map<unsigned int, MappedFrameBuffer> buffers_;\n+\n+\tControlInfoMap sensorControls_;\n+\n+\t/* Interface to the Camera Helper */\n+\tstd::unique_ptr<CameraSensorHelper> camHelper_;\n+\n+\t/* Local parameter storage */\n+\tstruct IPAContext context_;\n+};\n+\n+namespace {\n+\n+} /* namespace */\n+\n+IPAMaliC55::IPAMaliC55()\n+\t: context_({ {}, {}, { kMaxFrameContexts }, {} })\n+{\n+}\n+\n+std::string IPAMaliC55::logPrefix() const\n+{\n+\treturn \"mali-c55\";\n+}\n+\n+int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig,\n+\t\t ControlInfoMap *ipaControls)\n+{\n+\tcamHelper_ = CameraSensorHelperFactoryBase::create(settings.sensorModel);\n+\tif (!camHelper_) {\n+\t\tLOG(IPAMaliC55, Error)\n+\t\t\t<< \"Failed to create camera sensor helper for \"\n+\t\t\t<< settings.sensorModel;\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tFile file(settings.configurationFile);\n+\tif (!file.open(File::OpenModeFlag::ReadOnly)) {\n+\t\tint ret = file.error();\n+\t\tLOG(IPAMaliC55, Error)\n+\t\t\t<< \"Failed to open configuration file \"\n+\t\t\t<< settings.configurationFile << \": \" << strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tstd::unique_ptr<libcamera::YamlObject> data = YamlParser::parse(file);\n+\tif (!data)\n+\t\treturn -EINVAL;\n+\n+\tif (!data->contains(\"algorithms\")) {\n+\t\tLOG(IPAMaliC55, Error)\n+\t\t\t<< \"Tuning file doesn't contain any algorithm\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tint ret = createAlgorithms(context_, (*data)[\"algorithms\"]);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tupdateControls(ipaConfig.sensorInfo, ipaConfig.sensorControls, ipaControls);\n+\n+\treturn 0;\n+}\n+\n+void IPAMaliC55::setControls()\n+{\n+\tControlList ctrls(sensorControls_);\n+\n+\tsetSensorControls.emit(ctrls);\n+}\n+\n+int IPAMaliC55::start()\n+{\n+\treturn 0;\n+}\n+\n+void IPAMaliC55::stop()\n+{\n+\tcontext_.frameContexts.clear();\n+}\n+\n+void IPAMaliC55::updateControls(const IPACameraSensorInfo &sensorInfo,\n+\t\t\t\tconst ControlInfoMap &sensorControls,\n+\t\t\t\tControlInfoMap *ipaControls)\n+{\n+\tControlInfoMap::Map ctrlMap;\n+\n+\t/*\n+\t * Compute the frame duration limits.\n+\t *\n+\t * The frame length is computed assuming a fixed line length combined\n+\t * with the vertical frame sizes.\n+\t */\n+\tconst ControlInfo &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second;\n+\tuint32_t hblank = v4l2HBlank.def().get<int32_t>();\n+\tuint32_t lineLength = sensorInfo.outputSize.width + hblank;\n+\n+\tconst ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second;\n+\tstd::array<uint32_t, 3> frameHeights{\n+\t\tv4l2VBlank.min().get<int32_t>() + sensorInfo.outputSize.height,\n+\t\tv4l2VBlank.max().get<int32_t>() + sensorInfo.outputSize.height,\n+\t\tv4l2VBlank.def().get<int32_t>() + sensorInfo.outputSize.height,\n+\t};\n+\n+\tstd::array<int64_t, 3> frameDurations;\n+\tfor (unsigned int i = 0; i < frameHeights.size(); ++i) {\n+\t\tuint64_t frameSize = lineLength * frameHeights[i];\n+\t\tframeDurations[i] = frameSize / (sensorInfo.pixelRate / 1000000U);\n+\t}\n+\n+\tctrlMap[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],\n+\t\t\t\t\t\t\t frameDurations[1],\n+\t\t\t\t\t\t\t frameDurations[2]);\n+\n+\t/*\n+\t * Compute exposure time limits from the V4L2_CID_EXPOSURE control\n+\t * limits and the line duration.\n+\t */\n+\tdouble lineDuration = sensorInfo.minLineLength / sensorInfo.pixelRate;\n+\n+\tconst ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;\n+\tint32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;\n+\tint32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;\n+\tint32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;\n+\tctrlMap[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure, defExposure);\n+\n+\t/* Compute the analogue gain limits. */\n+\tconst ControlInfo &v4l2Gain = sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second;\n+\tfloat minGain = camHelper_->gain(v4l2Gain.min().get<int32_t>());\n+\tfloat maxGain = camHelper_->gain(v4l2Gain.max().get<int32_t>());\n+\tfloat defGain = camHelper_->gain(v4l2Gain.def().get<int32_t>());\n+\tctrlMap[&controls::AnalogueGain] = ControlInfo(minGain, maxGain, defGain);\n+\n+\t/*\n+\t * Merge in any controls that we support either statically or from the\n+\t * algorithms.\n+\t */\n+\tctrlMap.merge(context_.ctrlMap);\n+\n+\t*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);\n+}\n+\n+int IPAMaliC55::configure(const IPAConfigInfo &ipaConfig,\n+\t\t\t [[maybe_unused]] uint8_t bayerOrder,\n+\t\t\t ControlInfoMap *ipaControls)\n+{\n+\tsensorControls_ = ipaConfig.sensorControls;\n+\n+\t/* Clear the IPA context before the streaming session. */\n+\tcontext_.configuration = {};\n+\tcontext_.activeState = {};\n+\tcontext_.frameContexts.clear();\n+\n+\tconst IPACameraSensorInfo &info = ipaConfig.sensorInfo;\n+\n+\tupdateControls(info, ipaConfig.sensorControls, ipaControls);\n+\n+\tfor (auto const &a : algorithms()) {\n+\t\tAlgorithm *algo = static_cast<Algorithm *>(a.get());\n+\n+\t\tint ret = algo->configure(context_, info);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void IPAMaliC55::mapBuffers(const std::vector<IPABuffer> &buffers, bool readOnly)\n+{\n+\tfor (const IPABuffer &buffer : buffers) {\n+\t\tconst FrameBuffer fb(buffer.planes);\n+\t\tbuffers_.emplace(\n+\t\t\tbuffer.id,\n+\t\t\tMappedFrameBuffer(\n+\t\t\t\t&fb,\n+\t\t\t\treadOnly ? MappedFrameBuffer::MapFlag::Read\n+\t\t\t\t\t : MappedFrameBuffer::MapFlag::ReadWrite));\n+\t}\n+}\n+\n+void IPAMaliC55::unmapBuffers(const std::vector<IPABuffer> &buffers)\n+{\n+\tfor (const IPABuffer &buffer : buffers) {\n+\t\tauto it = buffers_.find(buffer.id);\n+\t\tif (it == buffers_.end())\n+\t\t\tcontinue;\n+\n+\t\tbuffers_.erase(buffer.id);\n+\t}\n+}\n+\n+void IPAMaliC55::queueRequest(const uint32_t request, const ControlList &controls)\n+{\n+\tIPAFrameContext &frameContext = context_.frameContexts.alloc(request);\n+\n+\tfor (auto const &a : algorithms()) {\n+\t\tAlgorithm *algo = static_cast<Algorithm *>(a.get());\n+\n+\t\talgo->queueRequest(context_, request, frameContext, controls);\n+\t}\n+}\n+\n+void IPAMaliC55::fillParams(unsigned int request,\n+\t\t\t [[maybe_unused]] uint32_t bufferId)\n+{\n+\tstruct mali_c55_params_buffer *params;\n+\tIPAFrameContext &frameContext = context_.frameContexts.get(request);\n+\n+\tparams = reinterpret_cast<mali_c55_params_buffer *>(\n+\t\tbuffers_.at(bufferId).planes()[0].data());\n+\tmemset(params, 0, sizeof(mali_c55_params_buffer));\n+\n+\tparams->version = MALI_C55_PARAM_BUFFER_V1;\n+\n+\tfor (auto const &algo : algorithms()) {\n+\t\talgo->prepare(context_, request, frameContext, params);\n+\n+\t\tASSERT(params->total_size <= MALI_C55_PARAMS_MAX_SIZE);\n+\t}\n+\n+\tparamsComputed.emit(request);\n+}\n+\n+void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId,\n+\t\t\t const ControlList &sensorControls)\n+{\n+\tIPAFrameContext &frameContext = context_.frameContexts.get(request);\n+\tconst mali_c55_stats_buffer *stats = nullptr;\n+\n+\tstats = reinterpret_cast<mali_c55_stats_buffer *>(\n+\t\tbuffers_.at(bufferId).planes()[0].data());\n+\n+\tframeContext.agc.exposure =\n+\t\tsensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();\n+\tframeContext.agc.sensorGain =\n+\t\tcamHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>());\n+\n+\tControlList metadata(controls::controls);\n+\n+\tfor (auto const &a : algorithms()) {\n+\t\tAlgorithm *algo = static_cast<Algorithm *>(a.get());\n+\n+\t\talgo->process(context_, request, frameContext, stats, metadata);\n+\t}\n+\n+\tsetControls();\n+\n+\tstatsProcessed.emit(request, metadata);\n+}\n+\n+} /* namespace ipa::mali_c55 */\n+\n+/*\n+ * External IPA module interface\n+ */\n+extern \"C\" {\n+const struct IPAModuleInfo ipaModuleInfo = {\n+\tIPA_MODULE_API_VERSION,\n+\t1,\n+\t\"mali-c55\",\n+\t\"mali-c55\",\n+};\n+\n+IPAInterface *ipaCreate()\n+{\n+\treturn new ipa::mali_c55::IPAMaliC55();\n+}\n+\n+} /* extern \"C\" */\n+\n+} /* namespace libcamera */\ndiff --git a/src/ipa/mali-c55/meson.build b/src/ipa/mali-c55/meson.build\nnew file mode 100644\nindex 00000000..864d90ec\n--- /dev/null\n+++ b/src/ipa/mali-c55/meson.build\n@@ -0,0 +1,33 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+subdir('algorithms')\n+subdir('data')\n+\n+ipa_name = 'ipa_mali_c55'\n+\n+mali_c55_ipa_sources = files([\n+ 'ipa_context.cpp',\n+ 'mali-c55.cpp'\n+])\n+\n+mali_c55_ipa_sources += mali_c55_ipa_algorithms\n+\n+mod = shared_module(ipa_name,\n+ mali_c55_ipa_sources,\n+ name_prefix : '',\n+ include_directories : [ipa_includes, libipa_includes],\n+ dependencies : libcamera_private,\n+ link_with : libipa,\n+ install : true,\n+ install_dir : ipa_install_dir)\n+\n+if ipa_sign_module\n+ custom_target(ipa_name + '.so.sign',\n+ input : mod,\n+ output : ipa_name + '.so.sign',\n+ command : [ipa_sign, ipa_priv_key, '@INPUT@', '@OUTPUT@'],\n+ install : false,\n+ build_by_default : true)\n+endif\n+\n+ipa_names += ipa_name\ndiff --git a/src/ipa/mali-c55/module.h b/src/ipa/mali-c55/module.h\nnew file mode 100644\nindex 00000000..1d85ec1f\n--- /dev/null\n+++ b/src/ipa/mali-c55/module.h\n@@ -0,0 +1,27 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024, Ideas On Board\n+ *\n+ * module.h - Mali-C55 IPA Module\n+ */\n+\n+#pragma once\n+\n+#include <linux/mali-c55-config.h>\n+\n+#include <libcamera/ipa/mali-c55_ipa_interface.h>\n+\n+#include <libipa/module.h>\n+\n+#include \"ipa_context.h\"\n+\n+namespace libcamera {\n+\n+namespace ipa::mali_c55 {\n+\n+using Module = ipa::Module<IPAContext, IPAFrameContext, IPACameraSensorInfo,\n+\t\t\t mali_c55_params_buffer, mali_c55_stats_buffer>;\n+\n+} /* namespace ipa::mali_c55 */\n+\n+} /* namespace libcamera*/\n", "prefixes": [ "v3", "05/11" ] }