From patchwork Tue Oct 14 10:55:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 24630 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 62AA6BE080 for ; Tue, 14 Oct 2025 10:55:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EC1E3605E6; Tue, 14 Oct 2025 12:55:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PQxiWg41"; 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 2DD9D60443 for ; Tue, 14 Oct 2025 12:55:52 +0200 (CEST) Received: from [192.168.1.182] (93-46-82-201.ip106.fastwebnet.it [93.46.82.201]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 55DFFC73; Tue, 14 Oct 2025 12:54:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760439252; bh=RlVztrqRILKiKyxjM9/uvbIg23F7JW+C2iycRA3ftjo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=PQxiWg41nM4tmlOA9m2AglEaktI5vUKTn3RfFKiM11j0PIsdNsgnEBNLcYrHczqyQ DdjlbvrFYg04SeuQfWMTLTDdDGUQG191NCo7jmmUVd9paYpe1j3XnrIAcrUvjnvq/u gSL2f4cPTivRliT0/ZDWezwN7L9xqUmsRPmDX/og= From: Jacopo Mondi Date: Tue, 14 Oct 2025 12:55:36 +0200 Subject: [PATCH v6 1/5] include: linux: Add stddef.h MIME-Version: 1.0 Message-Id: <20251014-v4l2-params-v6-1-caf5fa69eb29@ideasonboard.com> References: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> In-Reply-To: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Laurent Pinchart , Kieran Bingham X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3703; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=RlVztrqRILKiKyxjM9/uvbIg23F7JW+C2iycRA3ftjo=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBo7iw1f/vfnYgsvQVGkLNa8d/FQRGDrrKbiwifN xmZQAGbR6+JAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaO4sNQAKCRByNAaPFqFW PCbAD/9paJO5DyrNBXj1bUCmAuWuyS1fiNyrZMYIuZsuRK8iAVXjdO3sQ2Vz9kgIz4X8yl5p03k Z7zsPLNlCJ2FmST7I3B1MthslG+OIpWN8X/33zTEe6Y1lEFK+kBKv1HIuL1TkIONlNFTN0UfYa2 abFHWgNWGfvxbY+bGAs2bsfCojSARjZImwYTaIWqkd4taipToDyBl4X49Q4mnb8a5bmBuYMTjB1 ezNMCS/zReYbD8I47ufd4vrcLJo0OLr4PIRH4ph/1c6InKwS4OUhgjT3FrXkBIetUEnXrT01r2C 2fLrvRc4U+nEo2N6EJ9aIDcb30idfLPVWY6k/vQL/qTY3ayF5nYrfsT/5Q1dxNwEjL+Tsgddgfi KZieLH22Wv7rKngrmiLVCX4WoSwp/Bqg9lRLhyYbrI1KWvgVb7o8zRVHr2CzfWuNXtxzQozAQOA dxKYB4I8CAYmlrE+h3pN7VEVFSoegMiV+FzP7pEFzwmPmjvuszD748mQiIdZ38/d5sLHmVA9Rdb PpTr0wU589keNkAn1hu3oF4kzrfbtvzPIGv/wFH1molj6J/i6p7gQnNRU9s/xUtsXaxzvPqy03g U1CV8aUVEgpiyCzv7BHH2ZGavXUMHv0PvnhkybCA2v2BLVRArPWwVHq/8/ZE518iK5Kjz1b+s3v 6AnkzlyJso41Dog== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B 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" Import stddef.h from the Linux kernel sources v6.17 at revision 3407caa69a06 ("uapi: stddef.h: Introduce __kernel_nonstring") The stddef.h header is imported to provide the __counted_by() symbol which is not available in the header version shipped with, in example, Debian 12. __counted_by() will be used by the v4l2-isp.h header which will be imported next. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart Acked-by: Kieran Bingham --- include/linux/stddef.h | 75 ++++++++++++++++++++++++++++++++++++++++++ utils/update-kernel-headers.sh | 1 + 2 files changed, 76 insertions(+) diff --git a/include/linux/stddef.h b/include/linux/stddef.h new file mode 100644 index 0000000000000000000000000000000000000000..e1fcfcf3b33261939797d79f4e29a28fa1da6e10 --- /dev/null +++ b/include/linux/stddef.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_STDDEF_H +#define _LINUX_STDDEF_H + + + +#ifndef __always_inline +#define __always_inline __inline__ +#endif + +/* Not all C++ standards support type declarations inside an anonymous union */ +#ifndef __cplusplus +#define __struct_group_tag(TAG) TAG +#else +#define __struct_group_tag(TAG) +#endif + +/** + * __struct_group() - Create a mirrored named and anonyomous struct + * + * @TAG: The tag name for the named sub-struct (usually empty) + * @NAME: The identifier name of the mirrored sub-struct + * @ATTRS: Any struct attributes (usually empty) + * @MEMBERS: The member declarations for the mirrored structs + * + * Used to create an anonymous union of two structs with identical layout + * and size: one anonymous and one named. The former's members can be used + * normally without sub-struct naming, and the latter can be used to + * reason about the start, end, and size of the group of struct members. + * The named struct can also be explicitly tagged for layer reuse (C only), + * as well as both having struct attributes appended. + */ +#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \ + } ATTRS + +#ifdef __cplusplus +/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */ +#define __DECLARE_FLEX_ARRAY(T, member) \ + T member[0] +#else +/** + * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union + * + * @TYPE: The type of each flexible array element + * @NAME: The name of the flexible array member + * + * In order to have a flexible array member in a union or alone in a + * struct, it needs to be wrapped in an anonymous struct with at least 1 + * named member, but that member can be empty. + */ +#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \ + struct { \ + struct { } __empty_ ## NAME; \ + TYPE NAME[]; \ + } +#endif + +#ifndef __counted_by +#define __counted_by(m) +#endif + +#ifndef __counted_by_le +#define __counted_by_le(m) +#endif + +#ifndef __counted_by_be +#define __counted_by_be(m) +#endif + +#define __kernel_nonstring + +#endif /* _LINUX_STDDEF_H */ diff --git a/utils/update-kernel-headers.sh b/utils/update-kernel-headers.sh index 9a64dfb5698c67945ab4eee085360c1728589401..666624f9972ea61067e5b5695237ab7a17c61664 100755 --- a/utils/update-kernel-headers.sh +++ b/utils/update-kernel-headers.sh @@ -52,6 +52,7 @@ headers=" linux/media-bus-format.h linux/media.h linux/rkisp1-config.h + linux/stddef.h linux/udmabuf.h linux/v4l2-common.h linux/v4l2-controls.h From patchwork Tue Oct 14 10:55:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 24631 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 07AC3C3264 for ; Tue, 14 Oct 2025 10:55:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D450A605EC; Tue, 14 Oct 2025 12:55:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="YtNgpXhi"; 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 8F2F4605E4 for ; Tue, 14 Oct 2025 12:55:52 +0200 (CEST) Received: from [192.168.1.182] (93-46-82-201.ip106.fastwebnet.it [93.46.82.201]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 92512E70; Tue, 14 Oct 2025 12:54:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760439252; bh=B04XQR2HsXyiHyqtqII3W7XT9inNJ/kKeKMlTQUnZ0Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=YtNgpXhiPe8C7nPxPCOHlshugem2zw5kExb2jDMDWR5HGcEy0HGaawAKipZPmymdH ZuhJkYK6nOvOcZXNcO+E8l8xO7eYPhe5pZ2mYkGejd6BNGVQwM3jA7GbVnA5eowW39 ArXrS5t/yLF+Zxu16X+SUIIslcT8iCEoKEbeifiE= From: Jacopo Mondi Date: Tue, 14 Oct 2025 12:55:37 +0200 Subject: [PATCH v6 2/5] include: linux: Add v4l2-isp.h MIME-Version: 1.0 Message-Id: <20251014-v4l2-params-v6-2-caf5fa69eb29@ideasonboard.com> References: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> In-Reply-To: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Antoine Bouyer , Laurent Pinchart , Kieran Bingham , Daniel Scally X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5849; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=B04XQR2HsXyiHyqtqII3W7XT9inNJ/kKeKMlTQUnZ0Q=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBo7iw15AMIh7D0Q0L1oqmgrkXFgPnTcSdleNwQg DuYqN67MO6JAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaO4sNQAKCRByNAaPFqFW PI4aD/9My1oXnu04Ke6JDMW+QdiUkEUKfJtmhfIZJGqIPJYfFvWh8Jffz3K8NKEXu+HGs4fw0S4 iC7gZb3XnBda1mWey1HqSUUy4qTrzfkTV04FDZhzR66eiq2x3SuUFWS6+WEaoakxH+/vQE1nh44 s+9Uu+Dw6yH+X+lcX5u8R/UgTz/9jaM5UQ5gAryPfWAb0hLPTANuLVIiyZKGXecWFGp8au4FkqF xcM2KIrrECj047//qiOA74fVfPN9F/bucdF6T5wJGwZmx/1w+WPQy8JnWno8hPxryX+MSu1huGK SbpeBUysdGJ4oeie84UI4Jz9Vqp9p1khz7rIMTpwyduln0xFIlVj2XAPe8bx4G5uPLCYjgPzo8z qib2zvwQnBs8oaOZSzR+G5dKdrNUUnxC6WCDaEj5Q5LX9csm1DkBsBb20DFC878H0R3UAN4au10 eHfMoYMBOjBGR4TVovx4+H+R9brrQwKMJuiSmQZEVy+DeATOmeOFqGAXTMrzMxrJH4hhzTIa0d7 xKlalSLhpey0xJ5+0RRbkol6rlWFN/Pou9KRytd48raU/dF2hjDYcRBYO2RnSKXf5NXQQdl9tUE GRNY+TM8Y5jAjfAW1VBIE2iAKmksAPAqGSRlc0xw3/oEWzxnuvsSfNrpiy9QK4WP0+Yjc/Tz0JD UutKFtYLU9EeTUg== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B 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" Import the v4l2-isp.h header from the Linux kernel sources. The file has not been merged in mainline Linux yet but is available at v7: https://lore.kernel.org/all/20251014-extensible-parameters-validation-v7-0-6628bed5ca98@ideasonboard.com/ Create the include/linux/media/ directory so that header files exported from the kernel which include this file do not need to be adjusted when imported in libcamera. Signed-off-by: Jacopo Mondi Tested-by: Antoine Bouyer Reviewed-by: Laurent Pinchart Acked-by: Kieran Bingham Reviewed-by: Daniel Scally --- include/linux/media/v4l2-isp.h | 102 +++++++++++++++++++++++++++++++++++++++++ utils/update-kernel-headers.sh | 1 + 2 files changed, 103 insertions(+) diff --git a/include/linux/media/v4l2-isp.h b/include/linux/media/v4l2-isp.h new file mode 100644 index 0000000000000000000000000000000000000000..0cfc4ab94967ae796e9d9fc755dbbe072c1e82e2 --- /dev/null +++ b/include/linux/media/v4l2-isp.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Video4Linux2 generic ISP parameters and statistics support + * + * Copyright (C) 2025 Ideas On Board Oy + * Author: Jacopo Mondi + */ + +#ifndef _V4L2_ISP_H_ +#define _V4L2_ISP_H_ + +#include +#include + +/** + * enum v4l2_isp_params_version - V4L2 ISP parameters versioning + * + * @V4L2_ISP_PARAMS_VERSION_V0: First version of the V4L2 ISP parameters format + * (for compatibility) + * @V4L2_ISP_PARAMS_VERSION_V1: First version of the V4L2 ISP parameters format + * + * V0 and V1 are identical in order to support drivers compatible with the V4L2 + * ISP parameters format already upstreamed which use either 0 or 1 as their + * versioning identifier. Both V0 and V1 refers to the first version of the + * V4L2 ISP parameters format. + * + * Future revisions of the V4L2 ISP parameters format should start from the + * value of 2. + */ +enum v4l2_isp_params_version { + V4L2_ISP_PARAMS_VERSION_V0 = 0, + V4L2_ISP_PARAMS_VERSION_V1 +}; + +#define V4L2_ISP_PARAMS_FL_BLOCK_DISABLE (1U << 0) +#define V4L2_ISP_PARAMS_FL_BLOCK_ENABLE (1U << 1) + +/* + * Reserve the first 8 bits for V4L2_ISP_PARAMS_FL_* flag. + * + * Driver-specific flags should be defined as: + * #define DRIVER_SPECIFIC_FLAG0 ((1U << V4L2_ISP_PARAMS_FL_DRIVER_FLAGS(0)) + * #define DRIVER_SPECIFIC_FLAG1 ((1U << V4L2_ISP_PARAMS_FL_DRIVER_FLAGS(1)) + */ +#define V4L2_ISP_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8) + +/** + * struct v4l2_isp_params_block_header - V4L2 extensible parameters block header + * @type: The parameters block type (driver-specific) + * @flags: A bitmask of block flags (driver-specific) + * @size: Size (in bytes) of the parameters block, including this header + * + * This structure represents the common part of all the ISP configuration + * blocks. Each parameters block shall embed an instance of this structure type + * as its first member, followed by the block-specific configuration data. + * + * The @type field is an ISP driver-specific value that identifies the block + * type. The @size field specifies the size of the parameters block. + * + * The @flags field is a bitmask of per-block flags V4L2_PARAMS_ISP_FL_* and + * driver-specific flags specified by the driver header. + */ +struct v4l2_isp_params_block_header { + __u16 type; + __u16 flags; + __u32 size; +} __attribute__((aligned(8))); + +/** + * struct v4l2_isp_params_buffer - V4L2 extensible parameters configuration + * @version: The parameters buffer version (driver-specific) + * @data_size: The configuration data effective size, excluding this header + * @data: The configuration data + * + * This structure contains the configuration parameters of the ISP algorithms, + * serialized by userspace into a data buffer. Each configuration parameter + * block is represented by a block-specific structure which contains a + * :c:type:`v4l2_isp_params_block_header` entry as first member. Userspace + * populates the @data buffer with configuration parameters for the blocks that + * it intends to configure. As a consequence, the data buffer effective size + * changes according to the number of ISP blocks that userspace intends to + * configure and is set by userspace in the @data_size field. + * + * The parameters buffer is versioned by the @version field to allow modifying + * and extending its definition. Userspace shall populate the @version field to + * inform the driver about the version it intends to use. The driver will parse + * and handle the @data buffer according to the data layout specific to the + * indicated version and return an error if the desired version is not + * supported. + * + * For each ISP block that userspace wants to configure, a block-specific + * structure is appended to the @data buffer, one after the other without gaps + * in between. Userspace shall populate the @data_size field with the effective + * size, in bytes, of the @data buffer. + */ +struct v4l2_isp_params_buffer { + __u32 version; + __u32 data_size; + __u8 data[] __counted_by(data_size); +}; + +#endif /* _V4L2_ISP_H_ */ diff --git a/utils/update-kernel-headers.sh b/utils/update-kernel-headers.sh index 666624f9972ea61067e5b5695237ab7a17c61664..749c9e0345e7b8f40fece720a3fbfcd428eeab7f 100755 --- a/utils/update-kernel-headers.sh +++ b/utils/update-kernel-headers.sh @@ -51,6 +51,7 @@ headers=" linux/dma-heap.h linux/media-bus-format.h linux/media.h + linux/media/v4l2-isp.h linux/rkisp1-config.h linux/stddef.h linux/udmabuf.h From patchwork Tue Oct 14 10:55:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 24632 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 34095BE080 for ; Tue, 14 Oct 2025 10:55:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A1003605DE; Tue, 14 Oct 2025 12:55:56 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="G4LHaOib"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E31C7605D6 for ; Tue, 14 Oct 2025 12:55:52 +0200 (CEST) Received: from [192.168.1.182] (93-46-82-201.ip106.fastwebnet.it [93.46.82.201]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D8F22EAE; Tue, 14 Oct 2025 12:54:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760439253; bh=2OA4WIgL8CjcyqPYWxbDmyvI5xCv7zzEeh3onOk8hVc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=G4LHaOib4hZEhrai5OQk+RHOQbjJAQn3jI30n5/Wp215tO2dszU4+VRy4J5TGBJUJ yE/prsoqgP6wrYoMCMj29aSDzWU3ErJ1C9/6UKpnZVn8raJ3R474Glt8TNm0pQ3xU2 s/lr1j0H+Sv4biMerefrt5E1c6dhZMu+zeri2E0A= From: Jacopo Mondi Date: Tue, 14 Oct 2025 12:55:38 +0200 Subject: [PATCH v6 3/5] ipa: Update Mali C55 header file and adjust IPA MIME-Version: 1.0 Message-Id: <20251014-v4l2-params-v6-3-caf5fa69eb29@ideasonboard.com> References: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> In-Reply-To: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Antoine Bouyer , Kieran Bingham , Daniel Scally X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=26410; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=2OA4WIgL8CjcyqPYWxbDmyvI5xCv7zzEeh3onOk8hVc=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBo7iw1TuzeGFu3vgHZXo7OsYlRlLQ8nQ9rO5+c5 Qmuu1qrPnOJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaO4sNQAKCRByNAaPFqFW PA0WD/wJxxVS+9BmDEfUgLCfI448hG3jlRpQHtSRHAr6K5xoaj9rgIlnto1KwJY8K9UrdCrt/wJ Mm4zO7Wnyg9eeI7rwl3WoosWQ7W/VsaeSlGRPbNP9q2VSOSucc0Wd/HovDjAqvqF7N6tITID/lw 9IO6e9PfUAWWXadtoZivZeqRvIrOd5t3nq6QN3EQK9cJmM9//CM5xJ29A7PyTKGhliMg5zm/Eg0 c7SvIiZghhxAMfjUrymQvof7gWvBnXukH5N4Ncvq4DHURuSYvNJMOUcH4/QDKT135b0IBSJTHmn 8Ko5wd48eRbQHJzQcjiYrvsuj3rN2UKlK3mriRc5H/xwvPRdJ5GP6RG9ZuA1l1AiPRXget8rOI5 7tZSCdtMORyLzLzWswV8er2jjhU+EoqVzusgjcp07pTyLtb8/RlGRp+8H1tQUTahnX6njDjPxTb aUqwyg1hKUd34t3p2PfGNMZTffUp5Uh/d4UqzntJR9GRm9nBksBbVIhbWn+N8AfhPSgWmDDDg5l b7aBp49XzLXLriSOCRSRJvi70C6JQg8Ns8J4+ELk8UYCmlTYfYpwgNSJ0oTbsYMy6iHA+ILIwZo DefPnIKurH79TJioqUvyK+Kzu3N+ZsuyUwnD0CVkUMDV3nIoXisKnqTw/ANrrR+L6efTBSBj+pt 4rQSfxZEZSnvwxQ== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B 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" Update Mali C55 header file with the v11 version of the patch series, based on v4l2 extensible parameters, sent to the linux-media mailing list at: https://lore.kernel.org/all/20250714-c55-v11-0-bc20e460e42a@ideasonboard.com/ Adjust the IPA module to use the new v4l2-isp.h header file. Signed-off-by: Jacopo Mondi Tested-by: Antoine Bouyer Reviewed-by: Kieran Bingham Reviewed-by: Daniel Scally --- include/linux/mali-c55-config.h | 161 +++++--------------------------- src/ipa/mali-c55/algorithms/agc.cpp | 28 +++--- src/ipa/mali-c55/algorithms/agc.h | 2 +- src/ipa/mali-c55/algorithms/algorithm.h | 2 +- src/ipa/mali-c55/algorithms/awb.cpp | 14 +-- src/ipa/mali-c55/algorithms/awb.h | 2 +- src/ipa/mali-c55/algorithms/blc.cpp | 8 +- src/ipa/mali-c55/algorithms/blc.h | 2 +- src/ipa/mali-c55/algorithms/lsc.cpp | 14 +-- src/ipa/mali-c55/algorithms/lsc.h | 2 +- src/ipa/mali-c55/mali-c55.cpp | 11 ++- src/ipa/mali-c55/module.h | 2 +- 12 files changed, 67 insertions(+), 181 deletions(-) diff --git a/include/linux/mali-c55-config.h b/include/linux/mali-c55-config.h index b31415597e886496b65f8fb396c095618467f1ac..109082c5694f6b927dc5511043e3bfbc27a0b675 100644 --- a/include/linux/mali-c55-config.h +++ b/include/linux/mali-c55-config.h @@ -9,6 +9,21 @@ #define __UAPI_MALI_C55_CONFIG_H #include +#include +#include + +#define V4L2_CID_MALI_C55_CAPABILITIES (V4L2_CID_USER_MALI_C55_BASE + 0x0) +#define MALI_C55_GPS_PONG (1U << 0) +#define MALI_C55_GPS_WDR (1U << 1) +#define MALI_C55_GPS_COMPRESSION (1U << 2) +#define MALI_C55_GPS_TEMPER (1U << 3) +#define MALI_C55_GPS_SINTER_LITE (1U << 4) +#define MALI_C55_GPS_SINTER (1U << 5) +#define MALI_C55_GPS_IRIDIX_LTM (1U << 6) +#define MALI_C55_GPS_IRIDIX_GTM (1U << 7) +#define MALI_C55_GPS_CNR (1U << 8) +#define MALI_C55_GPS_FRSCALER (1U << 9) +#define MALI_C55_GPS_DS_PIPE (1U << 10) /* * Frames are split into zones of almost equal width and height - a zone is a @@ -228,65 +243,6 @@ enum mali_c55_param_block_type { MALI_C55_PARAM_MESH_SHADING_SELECTION, }; -#define MALI_C55_PARAM_BLOCK_FL_NONE 0 -#define MALI_C55_PARAM_BLOCK_FL_DISABLED BIT(0) - -/** - * struct mali_c55_params_block_header - Mali-C55 parameter block header - * - * This structure represents the common part of all the ISP configuration - * blocks. Each parameters block embeds an instance of this structure type - * as its first member, followed by the block-specific configuration data. The - * driver inspects this common header to discern the block type and its size and - * properly handle the block content by casting it to the correct block-specific - * type. - * - * The @type field is one of the values enumerated by - * :c:type:`mali_c55_param_block_type` and specifies how the data should be - * interpreted by the driver. The @size field specifies the size of the - * parameters block and is used by the driver for validation purposes. The - * @flags field holds a bitmask of per-block flags MALI_C55_PARAM_BLOCK_FL_*. - * - * If userspace wants to disable an ISP block the - * MALI_C55_PARAM_BLOCK_FL_DISABLED bit should be set in the @flags field. In - * that case userspace may optionally omit the remainder of the configuration - * block, which will in any case be ignored by the driver. If a new - * configuration of an ISP block has to be applied userspace shall fully - * populate the ISP block and omit setting the MALI_C55_PARAM_BLOCK_FL_DISABLED - * bit in the @flags field. - * - * Userspace is responsible for correctly populating the parameters block header - * fields (@type, @flags and @size) and correctly populate the block-specific - * parameters. - * - * For example: - * - * .. code-block:: c - * - * void populate_sensor_offs(struct mali_c55_params_block_header *block) { - * block->type = MALI_C55_PARAM_BLOCK_SENSOR_OFFS; - * block->enabled = MALI_C55_PARAM_BLOCK_FL_NONE; - * block->size = sizeof(struct mali_c55_params_sensor_off_preshading); - * - * struct mali_c55_params_sensor_off_preshading *sensor_offs = - * (struct mali_c55_params_sensor_off_preshading *)block; - * - * sensor_offs->chan00 = offset00; - * sensor_offs->chan01 = offset01; - * sensor_offs->chan10 = offset10; - * sensor_offs->chan11 = offset11; - * } - * - * @type: The parameters block type from :c:type:`mali_c55_param_block_type` - * @flags: Bitmask of block flags - * @size: Size (in bytes) of the parameters block - */ -struct mali_c55_params_block_header { - __u16 type; - __u16 flags; - __u32 size; -} __attribute__((aligned(8))); - /** * struct mali_c55_params_sensor_off_preshading - offset subtraction for each * color channel @@ -305,7 +261,7 @@ struct mali_c55_params_block_header { * @chan11: Offset for color channel 11 (default: B) */ struct mali_c55_params_sensor_off_preshading { - struct mali_c55_params_block_header header; + struct v4l2_isp_params_block_header header; __u32 chan00; __u32 chan01; __u32 chan10; @@ -470,7 +426,7 @@ enum mali_c55_aexp_hist_plane_mode { * This parameter is unused for the post-Iridix Histogram */ struct mali_c55_params_aexp_hist { - struct mali_c55_params_block_header header; + struct v4l2_isp_params_block_header header; __u8 skip_x; __u8 offset_x; __u8 skip_y; @@ -502,7 +458,7 @@ struct mali_c55_params_aexp_hist { * @nodes_used_horiz */ struct mali_c55_params_aexp_weights { - struct mali_c55_params_block_header header; + struct v4l2_isp_params_block_header header; __u8 nodes_used_horiz; __u8 nodes_used_vert; __u8 zone_weights[MALI_C55_MAX_ZONES]; @@ -520,7 +476,7 @@ struct mali_c55_params_aexp_weights { * @gain: The digital gain value to apply, in Q5.8 format. */ struct mali_c55_params_digital_gain { - struct mali_c55_params_block_header header; + struct v4l2_isp_params_block_header header; __u16 gain; }; @@ -560,7 +516,7 @@ enum mali_c55_awb_stats_mode { * @gain11: Multiplier for colour channel 11 */ struct mali_c55_params_awb_gains { - struct mali_c55_params_block_header header; + struct v4l2_isp_params_block_header header; __u16 gain00; __u16 gain01; __u16 gain10; @@ -635,7 +591,7 @@ enum mali_c55_params_awb_tap_points { * @cb_low: B/G ratio trim low (Q4.8 format) */ struct mali_c55_params_awb_config { - struct mali_c55_params_block_header header; + struct v4l2_isp_params_block_header header; __u8 tap_point; __u8 stats_mode; __u16 white_level; @@ -745,7 +701,7 @@ struct mali_c55_params_awb_config { * @mesh: Mesh shading correction tables */ struct mali_c55_params_mesh_shading_config { - struct mali_c55_params_block_header header; + struct v4l2_isp_params_block_header header; __u8 mesh_show; __u8 mesh_scale; __u8 mesh_page_r; @@ -800,7 +756,7 @@ enum mali_c55_params_mesh_alpha_bank { * @mesh_strength: Mesh strength in Q4.12 format [0..4096] */ struct mali_c55_params_mesh_shading_selection { - struct mali_c55_params_block_header header; + struct v4l2_isp_params_block_header header; __u8 mesh_alpha_bank_r; __u8 mesh_alpha_bank_g; __u8 mesh_alpha_bank_b; @@ -835,75 +791,4 @@ struct mali_c55_params_mesh_shading_selection { sizeof(struct mali_c55_params_mesh_shading_config) + \ sizeof(struct mali_c55_params_mesh_shading_selection)) -/** - * struct mali_c55_params_buffer - 3A configuration parameters - * - * This struct contains the configuration parameters of the Mali-C55 ISP - * algorithms, serialized by userspace into a data buffer. Each configuration - * parameter block is represented by a block-specific structure which contains a - * :c:type:`mali_c55_params_block_header` entry as first member. Userspace - * populates the @data buffer with configuration parameters for the blocks that - * it intends to configure. As a consequence, the data buffer effective size - * changes according to the number of ISP blocks that userspace intends to - * configure. - * - * The parameters buffer is versioned by the @version field to allow modifying - * and extending its definition. Userspace shall populate the @version field to - * inform the driver about the version it intends to use. The driver will parse - * and handle the @data buffer according to the data layout specific to the - * indicated version and return an error if the desired version is not - * supported. - * - * For each ISP block that userspace wants to configure, a block-specific - * structure is appended to the @data buffer, one after the other without gaps - * in between nor overlaps. Userspace shall populate the @total_size field with - * the effective size, in bytes, of the @data buffer. - * - * The expected memory layout of the parameters buffer is:: - * - * +-------------------- struct mali_c55_params_buffer ------------------+ - * | version = MALI_C55_PARAM_BUFFER_V1; | - * | total_size = sizeof(struct mali_c55_params_sensor_off_preshading) | - * | sizeof(struct mali_c55_params_aexp_hist); | - * | +------------------------- data ---------------------------------+ | - * | | +--------- struct mali_c55_params_sensor_off_preshading ------+ | | - * | | | +-------- struct mali_c55_params_block_header header -----+ | | | - * | | | | type = MALI_C55_PARAM_BLOCK_SENSOR_OFFS; | | | | - * | | | | flags = MALI_C55_PARAM_BLOCK_FL_NONE; | | | | - * | | | | size = | | | | - * | | | | sizeof(struct mali_c55_params_sensor_off_preshading);| | | | - * | | | +---------------------------------------------------------+ | | | - * | | | chan00 = ...; | | | - * | | | chan01 = ...; | | | - * | | | chan10 = ...; | | | - * | | | chan11 = ...; | | | - * | | +------------ struct mali_c55_params_aexp_hist ---------------+ | | - * | | | +-------- struct mali_c55_params_block_header header -----+ | | | - * | | | | type = MALI_C55_PARAM_BLOCK_AEXP_HIST; | | | | - * | | | | flags = MALI_C55_PARAM_BLOCK_FL_NONE; | | | | - * | | | | size = sizeof(struct mali_c55_params_aexp_hist); | | | | - * | | | +---------------------------------------------------------+ | | | - * | | | skip_x = ...; | | | - * | | | offset_x = ...; | | | - * | | | skip_y = ...; | | | - * | | | offset_y = ...; | | | - * | | | scale_bottom = ...; | | | - * | | | scale_top = ...; | | | - * | | | plane_mode = ...; | | | - * | | | tap_point = ...; | | | - * | | +-------------------------------------------------------------+ | | - * | +-----------------------------------------------------------------+ | - * +---------------------------------------------------------------------+ - * - * @version: The version from :c:type:`mali_c55_param_buffer_version` - * @total_size: The Mali-C55 configuration data effective size, excluding this - * header - * @data: The Mali-C55 configuration blocks data - */ -struct mali_c55_params_buffer { - __u8 version; - __u32 total_size; - __u8 data[MALI_C55_PARAMS_MAX_SIZE]; -}; - #endif /* __UAPI_MALI_C55_CONFIG_H */ diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index f60fddac3f04fd6f09dc782e929ff1593758c29b..78e7e07b2348a711e6261bac45e006f49a59513a 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -253,7 +253,7 @@ size_t Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContex gain = activeState.agc.manual.ispGain; block.header->type = MALI_C55_PARAM_BLOCK_DIGITAL_GAIN; - block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE; + block.header->flags = 0; block.header->size = sizeof(struct mali_c55_params_digital_gain); block.digital_gain->gain = floatingToFixedPoint<5, 8, uint16_t, double>(gain); @@ -266,7 +266,7 @@ size_t Agc::fillParamsBuffer(mali_c55_params_block block, enum mali_c55_param_block_type type) { block.header->type = type; - block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE; + block.header->flags = 0; block.header->size = sizeof(struct mali_c55_params_aexp_hist); /* Collect every 3rd pixel horizontally */ @@ -292,7 +292,7 @@ size_t Agc::fillWeightsArrayBuffer(mali_c55_params_block block, enum mali_c55_param_block_type type) { block.header->type = type; - block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE; + block.header->flags = 0; block.header->size = sizeof(struct mali_c55_params_aexp_weights); /* We use every zone - a 15x15 grid */ @@ -314,30 +314,30 @@ size_t Agc::fillWeightsArrayBuffer(mali_c55_params_block block, } void Agc::prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, mali_c55_params_buffer *params) + IPAFrameContext &frameContext, v4l2_isp_params_buffer *params) { mali_c55_params_block block; - block.data = ¶ms->data[params->total_size]; - params->total_size += fillGainParamBlock(context, frameContext, block); + block.data = ¶ms->data[params->data_size]; + params->data_size += fillGainParamBlock(context, frameContext, block); if (frame > 0) return; - block.data = ¶ms->data[params->total_size]; - params->total_size += fillParamsBuffer(block, + block.data = ¶ms->data[params->data_size]; + params->data_size += fillParamsBuffer(block, MALI_C55_PARAM_BLOCK_AEXP_HIST); - block.data = ¶ms->data[params->total_size]; - params->total_size += fillWeightsArrayBuffer(block, + block.data = ¶ms->data[params->data_size]; + params->data_size += fillWeightsArrayBuffer(block, MALI_C55_PARAM_BLOCK_AEXP_HIST_WEIGHTS); - block.data = ¶ms->data[params->total_size]; - params->total_size += fillParamsBuffer(block, + block.data = ¶ms->data[params->data_size]; + params->data_size += fillParamsBuffer(block, MALI_C55_PARAM_BLOCK_AEXP_IHIST); - block.data = ¶ms->data[params->total_size]; - params->total_size += fillWeightsArrayBuffer(block, + block.data = ¶ms->data[params->data_size]; + params->data_size += fillWeightsArrayBuffer(block, MALI_C55_PARAM_BLOCK_AEXP_IHIST_WEIGHTS); } diff --git a/src/ipa/mali-c55/algorithms/agc.h b/src/ipa/mali-c55/algorithms/agc.h index 0b4bf7eda1c2a7c9894f6932452fea5f53699b30..4325ef5a9b7dcef36107b64a65db993f194d4167 100644 --- a/src/ipa/mali-c55/algorithms/agc.h +++ b/src/ipa/mali-c55/algorithms/agc.h @@ -57,7 +57,7 @@ public: const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - mali_c55_params_buffer *params) override; + v4l2_isp_params_buffer *params) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const mali_c55_stats_buffer *stats, diff --git a/src/ipa/mali-c55/algorithms/algorithm.h b/src/ipa/mali-c55/algorithms/algorithm.h index ec8dd3973eaf2d804d8de8620840f716340e9cfd..e61115f6c2d6c911c15a1d877833d3f2b06a0db8 100644 --- a/src/ipa/mali-c55/algorithms/algorithm.h +++ b/src/ipa/mali-c55/algorithms/algorithm.h @@ -22,7 +22,7 @@ class Algorithm : public libcamera::ipa::Algorithm }; union mali_c55_params_block { - struct mali_c55_params_block_header *header; + struct v4l2_isp_params_block_header *header; struct mali_c55_params_sensor_off_preshading *sensor_offs; struct mali_c55_params_aexp_hist *aexp_hist; struct mali_c55_params_aexp_weights *aexp_weights; diff --git a/src/ipa/mali-c55/algorithms/awb.cpp b/src/ipa/mali-c55/algorithms/awb.cpp index 3d546e5a854b8aa02987c44f57109a6171e3794b..694c0aaa9c6804bb58e380ba9c744f11c39224fe 100644 --- a/src/ipa/mali-c55/algorithms/awb.cpp +++ b/src/ipa/mali-c55/algorithms/awb.cpp @@ -47,7 +47,7 @@ size_t Awb::fillGainsParamBlock(mali_c55_params_block block, IPAContext &context IPAFrameContext &frameContext) { block.header->type = MALI_C55_PARAM_BLOCK_AWB_GAINS; - block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE; + block.header->flags = 0; block.header->size = sizeof(struct mali_c55_params_awb_gains); double rGain = context.activeState.awb.rGain; @@ -77,7 +77,7 @@ size_t Awb::fillGainsParamBlock(mali_c55_params_block block, IPAContext &context size_t Awb::fillConfigParamBlock(mali_c55_params_block block) { block.header->type = MALI_C55_PARAM_BLOCK_AWB_CONFIG; - block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE; + block.header->flags = 0; block.header->size = sizeof(struct mali_c55_params_awb_config); /* Tap the stats after the purple fringe block */ @@ -126,18 +126,18 @@ size_t Awb::fillConfigParamBlock(mali_c55_params_block block) } void Awb::prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, mali_c55_params_buffer *params) + IPAFrameContext &frameContext, v4l2_isp_params_buffer *params) { mali_c55_params_block block; - block.data = ¶ms->data[params->total_size]; + block.data = ¶ms->data[params->data_size]; - params->total_size += fillGainsParamBlock(block, context, frameContext); + params->data_size += fillGainsParamBlock(block, context, frameContext); if (frame > 0) return; - block.data = ¶ms->data[params->total_size]; - params->total_size += fillConfigParamBlock(block); + block.data = ¶ms->data[params->data_size]; + params->data_size += fillConfigParamBlock(block); } void Awb::process(IPAContext &context, const uint32_t frame, diff --git a/src/ipa/mali-c55/algorithms/awb.h b/src/ipa/mali-c55/algorithms/awb.h index 2351d405553058dbff569e9e09e265a56baaa23f..647525ff700e8281e3cce63e64ba56a91294bcc2 100644 --- a/src/ipa/mali-c55/algorithms/awb.h +++ b/src/ipa/mali-c55/algorithms/awb.h @@ -22,7 +22,7 @@ public: const IPACameraSensorInfo &configInfo) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - mali_c55_params_buffer *params) override; + v4l2_isp_params_buffer *params) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const mali_c55_stats_buffer *stats, diff --git a/src/ipa/mali-c55/algorithms/blc.cpp b/src/ipa/mali-c55/algorithms/blc.cpp index 2a54c86a91f83d24183cb7236fcd5181302eb622..543ba96cb57ac0cca2b8f822180d8d8b42f21fc7 100644 --- a/src/ipa/mali-c55/algorithms/blc.cpp +++ b/src/ipa/mali-c55/algorithms/blc.cpp @@ -85,10 +85,10 @@ int BlackLevelCorrection::configure(IPAContext &context, void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context, const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - mali_c55_params_buffer *params) + v4l2_isp_params_buffer *params) { mali_c55_params_block block; - block.data = ¶ms->data[params->total_size]; + block.data = ¶ms->data[params->data_size]; if (frame > 0) return; @@ -97,7 +97,7 @@ void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context, return; block.header->type = MALI_C55_PARAM_BLOCK_SENSOR_OFFS; - block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE; + block.header->flags = 0; block.header->size = sizeof(mali_c55_params_sensor_off_preshading); block.sensor_offs->chan00 = offset00; @@ -105,7 +105,7 @@ void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context, block.sensor_offs->chan10 = offset10; block.sensor_offs->chan11 = offset11; - params->total_size += block.header->size; + params->data_size += block.header->size; } void BlackLevelCorrection::process([[maybe_unused]] IPAContext &context, diff --git a/src/ipa/mali-c55/algorithms/blc.h b/src/ipa/mali-c55/algorithms/blc.h index 9696e8e9f2aa8b9076a3a41fb8f5ea356e32be12..ee6c889ed89ac2230b231cb58a9fe4412c0ce164 100644 --- a/src/ipa/mali-c55/algorithms/blc.h +++ b/src/ipa/mali-c55/algorithms/blc.h @@ -22,7 +22,7 @@ public: const IPACameraSensorInfo &configInfo) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - mali_c55_params_buffer *params) override; + v4l2_isp_params_buffer *params) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const mali_c55_stats_buffer *stats, diff --git a/src/ipa/mali-c55/algorithms/lsc.cpp b/src/ipa/mali-c55/algorithms/lsc.cpp index c43d034a181edb7559706189f8d75edd67a2dc08..cb915c5efd3c22952035f2b03ee659f293942ec9 100644 --- a/src/ipa/mali-c55/algorithms/lsc.cpp +++ b/src/ipa/mali-c55/algorithms/lsc.cpp @@ -111,7 +111,7 @@ int Lsc::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData size_t Lsc::fillConfigParamsBlock(mali_c55_params_block block) const { block.header->type = MALI_C55_PARAM_MESH_SHADING_CONFIG; - block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE; + block.header->flags = 0; block.header->size = sizeof(struct mali_c55_params_mesh_shading_config); block.shading_config->mesh_show = false; @@ -131,7 +131,7 @@ size_t Lsc::fillSelectionParamsBlock(mali_c55_params_block block, uint8_t bank, uint8_t alpha) const { block.header->type = MALI_C55_PARAM_MESH_SHADING_SELECTION; - block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE; + block.header->flags = 0; block.header->size = sizeof(struct mali_c55_params_mesh_shading_selection); block.shading_selection->mesh_alpha_bank_r = bank; @@ -170,7 +170,7 @@ std::tuple Lsc::findBankAndAlpha(uint32_t ct) const void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - mali_c55_params_buffer *params) + v4l2_isp_params_buffer *params) { /* * For each frame we assess the colour temperature of the **last** frame @@ -194,9 +194,9 @@ void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, } mali_c55_params_block block; - block.data = ¶ms->data[params->total_size]; + block.data = ¶ms->data[params->data_size]; - params->total_size += fillSelectionParamsBlock(block, bank, alpha); + params->data_size += fillSelectionParamsBlock(block, bank, alpha); if (frame > 0) return; @@ -205,8 +205,8 @@ void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, * If this is the first frame, we need to load the parsed coefficient * tables from tuning data to the ISP. */ - block.data = ¶ms->data[params->total_size]; - params->total_size += fillConfigParamsBlock(block); + block.data = ¶ms->data[params->data_size]; + params->data_size += fillConfigParamsBlock(block); } REGISTER_IPA_ALGORITHM(Lsc, "Lsc") diff --git a/src/ipa/mali-c55/algorithms/lsc.h b/src/ipa/mali-c55/algorithms/lsc.h index d11e23bc7c34fa3e1f45ccf015b50f3d390d7159..c287900502528ca82ab6c62d732b6ffc28ad8df6 100644 --- a/src/ipa/mali-c55/algorithms/lsc.h +++ b/src/ipa/mali-c55/algorithms/lsc.h @@ -23,7 +23,7 @@ public: int init(IPAContext &context, const YamlObject &tuningData) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - mali_c55_params_buffer *params) override; + v4l2_isp_params_buffer *params) override; private: static constexpr unsigned int kRedOffset = 0; static constexpr unsigned int kGreenOffset = 1024; diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp index 7d45e7310aecdae0e47655e6d2e8830e776d74cd..504d95222074a35b033949a25178f998738e5699 100644 --- a/src/ipa/mali-c55/mali-c55.cpp +++ b/src/ipa/mali-c55/mali-c55.cpp @@ -331,22 +331,23 @@ void IPAMaliC55::queueRequest(const uint32_t request, const ControlList &control void IPAMaliC55::fillParams(unsigned int request, [[maybe_unused]] uint32_t bufferId) { - struct mali_c55_params_buffer *params; + struct v4l2_isp_params_buffer *params; IPAFrameContext &frameContext = context_.frameContexts.get(request); - params = reinterpret_cast( + params = reinterpret_cast( buffers_.at(bufferId).planes()[0].data()); - memset(params, 0, sizeof(mali_c55_params_buffer)); + memset(params, 0, + buffers_.at(bufferId).planes()[0].size()); params->version = MALI_C55_PARAM_BUFFER_V1; for (auto const &algo : algorithms()) { algo->prepare(context_, request, frameContext, params); - ASSERT(params->total_size <= MALI_C55_PARAMS_MAX_SIZE); + ASSERT(params->data_size <= MALI_C55_PARAMS_MAX_SIZE); } - size_t bytesused = offsetof(struct mali_c55_params_buffer, data) + params->total_size; + size_t bytesused = offsetof(struct v4l2_isp_params_buffer, data) + params->data_size; paramsComputed.emit(request, bytesused); } diff --git a/src/ipa/mali-c55/module.h b/src/ipa/mali-c55/module.h index 4f6a4f18bfaf83263ccb5b7eb1723da9b655cc3c..a8dcb20841a4ebd7bde22cae4ff1f8eef530d8bb 100644 --- a/src/ipa/mali-c55/module.h +++ b/src/ipa/mali-c55/module.h @@ -20,7 +20,7 @@ namespace libcamera { namespace ipa::mali_c55 { using Module = ipa::Module; + v4l2_isp_params_buffer, mali_c55_stats_buffer>; } /* namespace ipa::mali_c55 */ From patchwork Tue Oct 14 10:55:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 24633 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 06790C3331 for ; Tue, 14 Oct 2025 10:55:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B0427605FA; Tue, 14 Oct 2025 12:55:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rLiBppzK"; 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 2FB27605DE for ; Tue, 14 Oct 2025 12:55:53 +0200 (CEST) Received: from [192.168.1.182] (93-46-82-201.ip106.fastwebnet.it [93.46.82.201]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 39644F09; Tue, 14 Oct 2025 12:54:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760439253; bh=3oRwtQJD4vEwVmVb78GMsM6rxq7l9LRAJcwS3WSN9TI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rLiBppzKvE/iAuZGvBdVEai4itOjUacDbvTCdUnIp0AXBBE1xullU8Trdcb7VHoj8 oFYdVZ9E4hkRDlTPF5YGrvbSIeVGxpCdfX9aPBfeYAsCGFul2qxl8NcWyh7zryW7NT /rcz5iSrISmgvMBF69Ur+dg626sImc6eVqDyscw8= From: Jacopo Mondi Date: Tue, 14 Oct 2025 12:55:39 +0200 Subject: [PATCH v6 4/5] ipa: libipa: Introduce V4L2Params MIME-Version: 1.0 Message-Id: <20251014-v4l2-params-v6-4-caf5fa69eb29@ideasonboard.com> References: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> In-Reply-To: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Antoine Bouyer X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=26276; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=3oRwtQJD4vEwVmVb78GMsM6rxq7l9LRAJcwS3WSN9TI=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBo7iw1pEUvAreMYegG6d5iE4ChWDccqrL+kp0Sd KcQrLM/4YGJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaO4sNQAKCRByNAaPFqFW PDBiD/wLmYw3LEdN1ZGZ82U6hnNVazgW6HirqTXr2EYwibxDChBgPRQELt3YcSKV30CxUGTWASE +Q0h7KRFT1YVkVplJDEsvTbo2vBItnls5lkDBtlDW6Sk5bD3fGRXAOMpcvHBp1cRHLgtwzPLyDk o0pOcopLC3URDlcagCM9kAr4lVwOgy1Eo+evLzqs7dEA0hWyfn1PMWHp3uF724/9ZweMADAM90F 9w7Y9YMBHVVyMVtdUCUkVPjMxFqQqkIxIM/f8mXPT7lrwO2Zsp8dg5XTlRpwyYi/ucV1KW9vOVJ dl6Vgt8uHJUhvhPQzN8619/qAzxD9E3tIb5iq9w/QLwLGz60XE4c616pITZTf5t+2daY9UVJb+w tyiyzsFMVjQPMhCGejF18+8dosIYxeop2h7JHStNih8+Soq2xDA+i5td4sz5rLSHUYaEeCPUUrf kNsn4mo3LVoUl+4Zcu5NUFuNbXWcvqndgcj6wNtMiBNxUhufchHyuiGs+mgfEnenO16TaNwp3yl boODcenRuacFT/CDbyzHvicgY5zPKayLq2aw4zFNF01xDh2vsbZkOeVuVP4ldJvk6LEtJL+dCWQ LxMUV4ea/TOefenNsjLASJonX2gVgR8hgXeOUqtkcatt/w4FyZyjO+ClkFw1wg/2eFd5teFE/BV /bF1/JF1UZIGoQw== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B 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" The existing RkISP1Params helper class allows the RkISP1 IPA to handle both the extensible parameters format and the legacy fixed-size format. With the introduction of v4l2-isp.h in the Linux kernel the part of the RkISP1Params helper class that handles extensible parameters can be generalized so that other IPA modules can use the same helpers to populate a parameters buffer compatible with v4l2-isp.h. Generalize the RkISP1Params class to a new libipa component named V4L2Params and derive the existing RkISP1Params from it, leaving in the RkISP1-specific implementation the handling of the legacy format. Deriving RkISP1Params from V4L2Params requires changing the size associated to each block to include the size of v4l2_params_block_header in the ipa:rkisp1::kBlockTypeInfo map as the V4L2Params::block() implementation doesn't account for that as RkIS1Params::block() implementation did. Signed-off-by: Jacopo Mondi Tested-by: Antoine Bouyer --- src/ipa/libipa/meson.build | 2 + src/ipa/libipa/v4l2_params.cpp | 254 +++++++++++++++++++++++++++++++++++++++++ src/ipa/libipa/v4l2_params.h | 152 ++++++++++++++++++++++++ src/ipa/rkisp1/params.cpp | 93 +-------------- src/ipa/rkisp1/params.h | 175 ++++++++++++++++------------ src/ipa/rkisp1/rkisp1.cpp | 2 +- 6 files changed, 512 insertions(+), 166 deletions(-) diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index 660be94054fa98b714b6bc586039081e45a6b4bc..7202df869c2fe4d58586f72f0c3d7c9fb1472d23 100644 --- a/src/ipa/libipa/meson.build +++ b/src/ipa/libipa/meson.build @@ -17,6 +17,7 @@ libipa_headers = files([ 'lux.h', 'module.h', 'pwl.h', + 'v4l2_params.h', ]) libipa_sources = files([ @@ -36,6 +37,7 @@ libipa_sources = files([ 'lux.cpp', 'module.cpp', 'pwl.cpp', + 'v4l2_params.cpp', ]) libipa_includes = include_directories('..') diff --git a/src/ipa/libipa/v4l2_params.cpp b/src/ipa/libipa/v4l2_params.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea0cc85471f1289ecd227d9833ed20d5851d404e --- /dev/null +++ b/src/ipa/libipa/v4l2_params.cpp @@ -0,0 +1,254 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2025, Ideas On Board + * + * V4L2 Parameters + */ + +#include "v4l2_params.h" + +namespace libcamera { + +namespace ipa { + +/** + * \file v4l2_params.cpp + * \brief Helper class to populate an ISP configuration buffer compatible with + * the generic V4L2 ISP format + * + * The Linux kernel defines a generic buffer format for configuring ISP devices. + * The format describes a serialisation method for ISP parameters that allows + * userspace to populate a buffer of configuration data by appending blocks to + * the buffer with common headers but device-specific contents one after the + * other. + * + * The V4L2Params class implements support the V4L2 ISP parameters buffer format + * and allows users to populate the ISP configuration blocks, represented as + * V4L2ParamBlock class instances. + * + * IPA implementations using this helpers should define an enumeration of ISP + * blocks supported by the IPA module and use a set of common abstraction to + * help their derived implementation of V4L2Params translate the enumerated ISP + * block identifier to the actual type of the configuration data as defined by + * the kernel interface. + * + * As an example of this see the RkISP1 and Mali-C55 implementations. + */ + +/** + * \class V4L2ParamsBlock + * \brief Helper class that represents a ISP configuration block + * + * Each ISP function is associated with a set of configuration parameters + * defined by the kernel interface. + * + * This class represents an ISP block configuration entry. It is constructed + * with a reference to the memory area where the block configuration will be + * stored in the parameters buffer. The template parameter represents + * the underlying kernel-defined ISP block configuration type and allow its + * user to easily cast it to said type to populate and read the configuration + * parameters. + * + * \sa V4L2Params::block() + */ + +/** + * \fn V4L2ParamsBlock::V4L2ParamsBlock() + * \brief Construct a V4L2ParamsBlock with memory represented by \a data + * \param[in] data The memory area where the ISP block is located + */ + +/** + * \fn V4L2ParamsBlock::setEnabled() + * \brief Enable/disable an ISP configuration block + * \param[in] enabled The enable flag + */ + +/** + * \fn V4L2ParamsBlock::operator->() + * \brief Access the ISP configuration block casting it to the kernel-defined + * ISP configuration type + * + * The V4L2ParamsBlock is templated with the kernel defined ISP configuration + * block type. This function allows users to easily cast a V4L2ParamsBlock to + * the underlying kernel-defined type in order to easily populate or read + * the ISP configuration data. + * + * \code{.cpp} + * + * // The kernel header defines the ISP configuration types, in example + * // struct my_isp_awb_config_data { + * // u16 gain_ch00; + * // u16 gain_ch01; + * // u16 gain_ch10; + * // u16 gain_ch11; + * // + * // } + * + * template<> V4L2ParamsBlock awbBlock = ... + * + * awbBlock->gain_ch00 = ...; + * awbBlock->gain_ch01 = ...; + * awbBlock->gain_ch10 = ...; + * awbBlock->gain_ch11 = ...; + * + * \endcode + * + * Users of this class shall not create a V4L2ParamsBlock manually but should + * use V4L2Params::block(). + */ + +/** + * \fn V4L2ParamsBlock::operator->() const + * \copydoc V4L2ParamsBlock::operator->() + */ + +/** + * \fn V4L2ParamsBlock::operator*() const + * \copydoc V4L2ParamsBlock::operator->() + */ + +/** + * \fn V4L2ParamsBlock::operator*() + * \copydoc V4L2ParamsBlock::operator->() + */ + +/** + * \var V4L2ParamsBlock::data_ + * \brief Memory area reserved for the ISP configuration block + */ + + /** + * \class V4L2Params + * \brief Helper class that represent an ISP configuration buffer + * + * This class represents an ISP configuration buffer. It is constructed + * with a reference to the memory mapped buffer that will be queued to the ISP + * driver. + * + * This class is templated with the type of the enumeration of ISP blocks that + * each IPA module is expected to support. IPA modules are expected to derive + * this class by providing a 'param_traits' type that helps the class associate + * a block type with the actual memory area that represents the ISP + * configuration block. + * + * \code{.cpp} + * + * // Define the supported ISP blocks + * enum class myISPBlocks { + * Agc, + * Awb, + * ... + * }; + * + * // Maps the C++ enum type to the kernel enum type and concrete parameter type + * template + * struct block_type { + * }; + * + * template<> + * struct block_type { + * using type = struct my_isp_kernel_config_type_agc; + * static constexpr kernel_enum_type blockType = MY_ISP_TYPE_AGC; + * }; + * + * template<> + * struct block_type { + * using type = struct my_isp_kernel_config_type_awb; + * static constexpr kernel_enum_type blockType = MY_ISP_TYPE_AWB; + * }; + * + * + * // Convenience type to associate a block id to the 'block_type' overload + * struct params_traits { + * using id_type = myISPBlocks; + * template using id_to_details = block_type; + * }; + * + * ... + * + * // Derive the V4L2Params class by providing params_traits + * class MyISPParams : public V4L2Params + * { + * public: + * MyISPParams::MyISPParams(Span data) + * : V4L2Params(data, kVersion) + * { + * } + * }; + * + * \endcode + * + * Users of this class can then easily access an ISP configuration block as a + * V4L2ParamsBlock instance. + * + * \code{.cpp} + * + * MyISPParams params(data); + * + * auto awb = params.block(); + * awb->gain00 = ...; + * awb->gain01 = ...; + * awb->gain10 = ...; + * awb->gain11 = ...; + * \endcode + */ + +/** + * \fn V4L2Params::V4L2Params() + * \brief Construct an instance of V4L2Params + * \param[in] data Reference to the v4l2-buffer memory mapped area + * \param[in] version The ISP parameters version the implementation supports + */ + +/** + * \fn V4L2Params::bytesused() + * \brief Retrieve the used size of the parameters buffer (in bytes) + * + * The parameters buffer size is mostly used to populate the v4l2_buffer + * bytesused field before queueing the buffer to the ISP. + * + * \return The number of bytes occupied by the ISP configuration parameters + */ + +/** + * \fn V4L2Params::block() + * \brief Retrieve the location of an ISP configuration block a return it + * \return A V4L2ParamsBlock instance that points to the ISP configuration block + */ + +/** + * \fn V4L2Params::block(typename Traits::id_type type, unsigned int blockType, size_t blockSize) + * \brief Populate an ISP configuration block a returns a reference to its + * memory + * \param[in] type The ISP block identifier enumerated by the IPA module + * \param[in] blockType The kernel-defined ISP block identifier, used to + * populate the block header + * \param[in] blockSize The ISP block size, used to populate the block header + * + * Initialize the block header with \a blockType and \a blockSize and + * returns a reference to the memory used to store an ISP configuration block. + * + * IPA modules that derive the V4L2Params class shall use this function to + * retrieve the memory area that will be used to construct a V4L2ParamsBlock + * before returning it to the caller. + */ + +/** + * \var V4L2Params::data_ + * \brief The ISP parameters buffer memory + */ + +/** + * \var V4L2Params::used_ + * \brief The number of bytes used in the parameters buffer + */ + +/** + * \var V4L2Params::blocks_ + * \brief Cache of ISP configuration blocks + */ + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/v4l2_params.h b/src/ipa/libipa/v4l2_params.h new file mode 100644 index 0000000000000000000000000000000000000000..728305c5b7b859815bee6da62ce35c44dd1ec41a --- /dev/null +++ b/src/ipa/libipa/v4l2_params.h @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2025, Ideas On Board + * + * V4L2 Parameters + */ + +#pragma once + +#include +#include +#include + +#include + +#include +#include + +namespace libcamera { + +namespace ipa { + +LOG_DECLARE_CATEGORY(V4L2Params) + +template +class V4L2ParamsBlock +{ +public: + V4L2ParamsBlock(const Span data) + : data_(data) + { + } + + virtual ~V4L2ParamsBlock() {} + + virtual void setEnabled(bool enabled) + { + struct v4l2_isp_params_block_header *header = + reinterpret_cast(data_.data()); + + header->flags &= ~(V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | + V4L2_ISP_PARAMS_FL_BLOCK_DISABLE); + header->flags |= enabled ? V4L2_ISP_PARAMS_FL_BLOCK_ENABLE + : V4L2_ISP_PARAMS_FL_BLOCK_DISABLE; + } + + virtual const T *operator->() const + { + return reinterpret_cast(data_.data()); + } + + virtual T *operator->() + { + return reinterpret_cast(data_.data()); + } + + virtual const T &operator*() const + { + return *reinterpret_cast(data_.data()); + } + + virtual T &operator*() + { + return *reinterpret_cast(data_.data()); + } + +protected: + Span data_; +}; + +template +class V4L2Params +{ +public: + V4L2Params(Span data, unsigned int version) + : data_(data) + { + struct v4l2_isp_params_buffer *params = + reinterpret_cast(data_.data()); + params->data_size = 0; + params->version = version; + + used_ = offsetof(struct v4l2_isp_params_buffer, data); + } + + size_t bytesused() const { return used_; } + + template + auto block() + { + using Details = typename Traits::template id_to_details; + + using Type = typename Details::type; + constexpr auto kernelId = Details::blockType; + + auto data = block(Id, kernelId, sizeof(Type)); + return V4L2ParamsBlock(data); + } + +protected: + Span block(typename Traits::id_type type, + unsigned int blockType, size_t blockSize) + { + /* + * Look up the block in the cache first. If an algorithm + * requests the same block type twice, it should get the same + * block. + */ + auto cacheIt = blocks_.find(type); + if (cacheIt != blocks_.end()) + return cacheIt->second; + + /* + * Make sure we don't run out of space. Assert as otherwise + * we get a segfault as soon as someone tries to access the + * empty Span<> returned from here. + */ + if (blockSize > data_.size() - used_) { + LOG(Fatal) << + "Parameters buffer out of space; potential version mismatch between driver and libcamera"; + return {}; + } + + /* Allocate a new block, clear its memory, and initialize its header. */ + Span block = data_.subspan(used_, blockSize); + memset(block.data(), 0, block.size()); + + struct v4l2_isp_params_block_header *header = + reinterpret_cast(block.data()); + header->type = blockType; + header->size = block.size(); + + used_ += block.size(); + + reinterpret_cast + (data_.data())->data_size += block.size(); + + /* Update the cache. */ + blocks_[type] = block; + + return block; + } + + Span data_; + size_t used_; + + std::map> blocks_; +}; + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/rkisp1/params.cpp b/src/ipa/rkisp1/params.cpp index 5edb36c91b87859d02c0a8b41efe977ff048def5..7040207c26557aa278050a1f7232cc6c380505b1 100644 --- a/src/ipa/rkisp1/params.cpp +++ b/src/ipa/rkisp1/params.cpp @@ -35,7 +35,7 @@ struct BlockTypeInfo { #define RKISP1_BLOCK_TYPE_ENTRY(block, id, type, category, bit) \ { BlockType::block, { \ RKISP1_EXT_PARAMS_BLOCK_TYPE_##id, \ - sizeof(struct rkisp1_cif_isp_##type##_config), \ + sizeof(struct rkisp1_ext_params_##type##_config), \ offsetof(struct rkisp1_params_cfg, category.type##_config), \ RKISP1_CIF_ISP_MODULE_##bit, \ } } @@ -49,7 +49,7 @@ struct BlockTypeInfo { #define RKISP1_BLOCK_TYPE_ENTRY_EXT(block, id, type) \ { BlockType::block, { \ RKISP1_EXT_PARAMS_BLOCK_TYPE_##id, \ - sizeof(struct rkisp1_cif_isp_##type##_config), \ + sizeof(struct rkisp1_ext_params_##type##_config), \ 0, 0, \ } } @@ -79,56 +79,6 @@ const std::map kBlockTypeInfo = { } /* namespace */ -RkISP1ParamsBlockBase::RkISP1ParamsBlockBase(RkISP1Params *params, BlockType type, - const Span &data) - : params_(params), type_(type) -{ - if (params_->format() == V4L2_META_FMT_RK_ISP1_EXT_PARAMS) { - header_ = data.subspan(0, sizeof(rkisp1_ext_params_block_header)); - data_ = data.subspan(sizeof(rkisp1_ext_params_block_header)); - } else { - data_ = data; - } -} - -void RkISP1ParamsBlockBase::setEnabled(bool enabled) -{ - /* - * For the legacy fixed format, blocks are enabled in the top-level - * header. Delegate to the RkISP1Params class. - */ - if (params_->format() == V4L2_META_FMT_RK_ISP1_PARAMS) - return params_->setBlockEnabled(type_, enabled); - - /* - * For the extensible format, set the enable and disable flags in the - * block header directly. - */ - struct rkisp1_ext_params_block_header *header = - reinterpret_cast(header_.data()); - header->flags &= ~(RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE | - RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE); - header->flags |= enabled ? RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE - : RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE; -} - -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); - } -} - void RkISP1Params::setBlockEnabled(BlockType type, bool enabled) { const BlockTypeInfo &info = kBlockTypeInfo.at(type); @@ -178,44 +128,7 @@ Span RkISP1Params::block(BlockType type) 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. If an algorithm - * requests the same block type twice, it should get the same block. - */ - 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_) { - LOG(RkISP1Params, Error) - << "Out of memory to allocate block type " - << utils::to_underlying(type); - 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->size = block.size(); - - /* Update the cache. */ - blocks_[type] = block; - - return block; + return V4L2Params::block(type, info.type, info.size); } } /* namespace ipa::rkisp1 */ diff --git a/src/ipa/rkisp1/params.h b/src/ipa/rkisp1/params.h index 2e60528d102ec44a31417d4b146e74cace363efa..eddb37d5c000b6b1de1c698ad915f2b42da58b81 100644 --- a/src/ipa/rkisp1/params.h +++ b/src/ipa/rkisp1/params.h @@ -7,13 +7,10 @@ #pragma once -#include -#include - #include +#include -#include -#include +#include namespace libcamera { @@ -49,115 +46,143 @@ template struct block_type { }; -#define RKISP1_DEFINE_BLOCK_TYPE(blockType, blockStruct) \ +#define RKISP1_DEFINE_BLOCK_TYPE(blockType, blockStruct, id) \ template<> \ struct block_type { \ using type = struct rkisp1_cif_isp_##blockStruct##_config; \ + static constexpr rkisp1_ext_params_block_type blockType = \ + RKISP1_EXT_PARAMS_BLOCK_TYPE_##id; \ }; -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) -RKISP1_DEFINE_BLOCK_TYPE(CompandBls, compand_bls) -RKISP1_DEFINE_BLOCK_TYPE(CompandExpand, compand_curve) -RKISP1_DEFINE_BLOCK_TYPE(CompandCompress, compand_curve) -RKISP1_DEFINE_BLOCK_TYPE(Wdr, wdr) +RKISP1_DEFINE_BLOCK_TYPE(Bls, bls, BLS) +RKISP1_DEFINE_BLOCK_TYPE(Dpcc, dpcc, DPCC) +RKISP1_DEFINE_BLOCK_TYPE(Sdg, sdg, SDG) +RKISP1_DEFINE_BLOCK_TYPE(AwbGain, awb_gain, AWB_GAIN) +RKISP1_DEFINE_BLOCK_TYPE(Flt, flt, FLT) +RKISP1_DEFINE_BLOCK_TYPE(Bdm, bdm, BDM) +RKISP1_DEFINE_BLOCK_TYPE(Ctk, ctk, CTK) +RKISP1_DEFINE_BLOCK_TYPE(Goc, goc, GOC) +RKISP1_DEFINE_BLOCK_TYPE(Dpf, dpf, DPF) +RKISP1_DEFINE_BLOCK_TYPE(DpfStrength, dpf_strength, DPF_STRENGTH) +RKISP1_DEFINE_BLOCK_TYPE(Cproc, cproc, CPROC) +RKISP1_DEFINE_BLOCK_TYPE(Ie, ie, IE) +RKISP1_DEFINE_BLOCK_TYPE(Lsc, lsc, LSC) +RKISP1_DEFINE_BLOCK_TYPE(Awb, awb_meas, AWB_MEAS) +RKISP1_DEFINE_BLOCK_TYPE(Hst, hst, HST_MEAS) +RKISP1_DEFINE_BLOCK_TYPE(Aec, aec, AEC_MEAS) +RKISP1_DEFINE_BLOCK_TYPE(Afc, afc, AFC_MEAS) +RKISP1_DEFINE_BLOCK_TYPE(CompandBls, compand_bls, COMPAND_BLS) +RKISP1_DEFINE_BLOCK_TYPE(CompandExpand, compand_curve, COMPAND_EXPAND) +RKISP1_DEFINE_BLOCK_TYPE(CompandCompress, compand_curve, COMPAND_COMPRESS) +RKISP1_DEFINE_BLOCK_TYPE(Wdr, wdr, WDR) + +struct params_traits { + using id_type = BlockType; + + template + using id_to_details = block_type; +}; } /* namespace details */ -class RkISP1Params; +template +class RkISP1ParamsBlock; -class RkISP1ParamsBlockBase +class RkISP1Params : public V4L2Params { public: - RkISP1ParamsBlockBase(RkISP1Params *params, BlockType type, - const Span &data); + static constexpr unsigned int kVersion = RKISP1_EXT_PARAM_BUFFER_V1; + + RkISP1Params(uint32_t format, Span data) + : V4L2Params(data, kVersion), format_(format) + { + if (format_ == V4L2_META_FMT_RK_ISP1_PARAMS) { + memset(data.data(), 0, data.size()); + used_ = sizeof(struct rkisp1_params_cfg); + } + } + + template + auto block() + { + using Type = typename details::block_type::type; - Span data() const { return data_; } + return RkISP1ParamsBlock(this, id, block(id)); + } - void setEnabled(bool enabled); + uint32_t format() const { return format_; } + void setBlockEnabled(BlockType type, bool enabled); private: - LIBCAMERA_DISABLE_COPY(RkISP1ParamsBlockBase) + Span block(BlockType type); - RkISP1Params *params_; - BlockType type_; - Span header_; - Span data_; + uint32_t format_; }; -template -class RkISP1ParamsBlock : public RkISP1ParamsBlockBase +template +class RkISP1ParamsBlock final : public V4L2ParamsBlock { public: - using Type = typename details::block_type::type; - - RkISP1ParamsBlock(RkISP1Params *params, const Span &data) - : RkISP1ParamsBlockBase(params, B, data) + RkISP1ParamsBlock(RkISP1Params *params, BlockType type, + const Span data) + : V4L2ParamsBlock(data) { + params_ = params; + type_ = type; + + /* + * cifData_ points to the actual configuration data + * (struct rkisp1_cif_isp_*) which is not prefixed by any header, + * for the legacy fixed format. + */ + if (params_->format() == V4L2_META_FMT_RK_ISP1_PARAMS) + cifData_ = data; + else + cifData_ = data.subspan(sizeof(v4l2_isp_params_block_header)); } - const Type *operator->() const + void setEnabled(bool enabled) override { - return reinterpret_cast(data().data()); + /* + * For the legacy fixed format, blocks are enabled in the + * top-level header. Delegate to the RkISP1Params class. + */ + if (params_->format() == V4L2_META_FMT_RK_ISP1_PARAMS) + return params_->setBlockEnabled(type_, enabled); + + return V4L2ParamsBlock::setEnabled(enabled); } - Type *operator->() + /* + * Override the dereference operators to return a reference to the + * actual configuration data (struct rkisp1_cif_isp_*) skipping the + * 'v4l2_isp_params_block_header' header. + */ + + virtual const T *operator->() const override { - return reinterpret_cast(data().data()); + return reinterpret_cast(cifData_.data()); } - const Type &operator*() const & + virtual T *operator->() override { - return *reinterpret_cast(data().data()); + return reinterpret_cast(cifData_.data()); } - Type &operator*() & + virtual const T &operator*() const override { - return *reinterpret_cast(data().data()); + return *reinterpret_cast(cifData_.data()); } -}; - -class RkISP1Params -{ -public: - RkISP1Params(uint32_t format, Span data); - template - RkISP1ParamsBlock block() + virtual T &operator*() override { - return RkISP1ParamsBlock(this, block(B)); + return *reinterpret_cast(cifData_.data()); } - uint32_t format() const { return format_; } - size_t size() const { return used_; } - private: - friend class RkISP1ParamsBlockBase; - - Span block(BlockType type); - void setBlockEnabled(BlockType type, bool enabled); - - uint32_t format_; - - Span data_; - size_t used_; - - std::map> blocks_; + RkISP1Params *params_; + BlockType type_; + Span cifData_; }; } /* namespace ipa::rkisp1 */ diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index fa22bfc349043002345d275b11a60ac983e329d7..f5f7377b63d21af11473ccc4ab18ab45294743cb 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -349,7 +349,7 @@ void IPARkISP1::computeParams(const uint32_t frame, const uint32_t bufferId) for (auto const &algo : algorithms()) algo->prepare(context_, frame, frameContext, ¶ms); - paramsComputed.emit(frame, params.size()); + paramsComputed.emit(frame, params.bytesused()); } void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId, From patchwork Tue Oct 14 10:55:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 24634 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 CD99AC3264 for ; Tue, 14 Oct 2025 10:55:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DF93D605EF; Tue, 14 Oct 2025 12:55:58 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="TgYusaJG"; 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 6F133605E6 for ; Tue, 14 Oct 2025 12:55:53 +0200 (CEST) Received: from [192.168.1.182] (93-46-82-201.ip106.fastwebnet.it [93.46.82.201]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7E31E104D; Tue, 14 Oct 2025 12:54:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1760439253; bh=JYiKS5thndV42WwNCkAQvn0OzNEF9wnCUl9r15fupRM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TgYusaJGaW1wHCsnFJE3xkSoTJybzp6tbvra9f9LTPSL554RCrEqW645LeVbN4PZv aFy/EyeN1wRBCcreaxhIiPoBoxjOM6QCg2nE54+1k7Xg0rkZsg74K5AV89RDd7lMw/ 5ZJskQwAx8zXjezzaJ7VRmudUpmPZEwBLCm39G9c= From: Jacopo Mondi Date: Tue, 14 Oct 2025 12:55:40 +0200 Subject: [PATCH v6 5/5] ipa: mali-c55: Introduce MaliC55Params MIME-Version: 1.0 Message-Id: <20251014-v4l2-params-v6-5-caf5fa69eb29@ideasonboard.com> References: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> In-Reply-To: <20251014-v4l2-params-v6-0-caf5fa69eb29@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Antoine Bouyer , Daniel Scally X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=25121; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=JYiKS5thndV42WwNCkAQvn0OzNEF9wnCUl9r15fupRM=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBo7iw1IBcxisr2RdKwYHgYDq51Uo5BfU0D6/sI+ P/nfTTpW/WJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaO4sNQAKCRByNAaPFqFW PKCaEACH8H3REZp5LY76NMmUkVGjFVRrmOEusmaMLVMqIYwrTpJscPs6PbKhl3e47ki9/pXBGOD k+spr1TYvYEH3hHMyZn4OkKzInkWeqxHEHZ1YBwLsN45lHcIVMKhobGTaMIlj9mxxsY8ZT5796S 0Uu8+PRdMb9RPI/zEe7GhQKpDkTBrGjh8sdvVDzSZbAe4gFOBPOVslXnKltCSvG3JGupIMswwr9 xQL43SMJnJE10SkROdNnNoUEubae7EazreAVSos3w5IREfuxcbU9OZXitgTdnPjURqxrjf5ZFeh PPgSZ3/trZdCuz9HeGIR11zsBxPSju6XcY3wSkGw29/SinjTfDRKxH5dP1K+XECK+nC9dqOFqj6 kFgVl0eezrdhtH6hbZBqgxdXanUbhfFFubbk4U5hjCk2c6sAVPmLUHtezNyPnb5nrjud1HGBV0C Y2N/OS/VCn9XgfxnTvZftgVcvuzoXf+yqVG8wBd/ceHGAp13OmJiY4+spm3y+ymDrz55NVSrX/t xUubUrrx97mJyTcWIOLdjGflcaQRRVAqb6xCOUwNj7RfGVIT60DFVhO+zRzEvefPmwziespFEPm iG0pH+13w6aD7cUkRhS8SMYZz3pfEGrAc0hhpDoqDNJj/t/ylvJjR3Obmjb39hDcbBo5kXMsD0d P2afgtDv+IGtjxg== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B 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 MaliC55Params to derive from V4L2Params and use the new helpers in the Mali C55 IPA algorithms implementation. Signed-off-by: Jacopo Mondi Tested-by: Antoine Bouyer Reviewed-by: Daniel Scally --- src/ipa/mali-c55/algorithms/agc.cpp | 87 +++++++++++++++---------------------- src/ipa/mali-c55/algorithms/agc.h | 14 +++--- src/ipa/mali-c55/algorithms/awb.cpp | 64 +++++++++++---------------- src/ipa/mali-c55/algorithms/awb.h | 10 ++--- src/ipa/mali-c55/algorithms/blc.cpp | 20 +++------ src/ipa/mali-c55/algorithms/blc.h | 3 +- src/ipa/mali-c55/algorithms/lsc.cpp | 58 ++++++++++--------------- src/ipa/mali-c55/algorithms/lsc.h | 8 ++-- src/ipa/mali-c55/mali-c55.cpp | 20 +++------ src/ipa/mali-c55/module.h | 3 +- src/ipa/mali-c55/params.h | 77 ++++++++++++++++++++++++++++++++ 11 files changed, 191 insertions(+), 173 deletions(-) diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index 78e7e07b2348a711e6261bac45e006f49a59513a..5d60cd8c9ff8a90e2e48e5d6939b538135b7ec3d 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -241,8 +241,8 @@ void Agc::queueRequest(IPAContext &context, const uint32_t frame, } } -size_t Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContext, - mali_c55_params_block block) +void Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContext, + MaliC55Params *params) { IPAActiveState &activeState = context.activeState; double gain; @@ -252,52 +252,50 @@ size_t Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContex else gain = activeState.agc.manual.ispGain; - block.header->type = MALI_C55_PARAM_BLOCK_DIGITAL_GAIN; - block.header->flags = 0; - block.header->size = sizeof(struct mali_c55_params_digital_gain); + auto block = params->block(); + block->gain = floatingToFixedPoint<5, 8, uint16_t, double>(gain); - block.digital_gain->gain = floatingToFixedPoint<5, 8, uint16_t, double>(gain); frameContext.agc.ispGain = gain; - - return block.header->size; } -size_t Agc::fillParamsBuffer(mali_c55_params_block block, - enum mali_c55_param_block_type type) +void Agc::fillParamsBuffer(MaliC55Params *params, enum MaliC55Blocks type) { - block.header->type = type; - block.header->flags = 0; - block.header->size = sizeof(struct mali_c55_params_aexp_hist); + + assert(type == MaliC55Blocks::AexpHist || type == MaliC55Blocks::AexpIhist); + + auto block = type == MaliC55Blocks::AexpHist ? + params->block() : + params->block(); /* Collect every 3rd pixel horizontally */ - block.aexp_hist->skip_x = 1; + block->skip_x = 1; /* Start from first column */ - block.aexp_hist->offset_x = 0; + block->offset_x = 0; /* Collect every pixel vertically */ - block.aexp_hist->skip_y = 0; + block->skip_y = 0; /* Start from the first row */ - block.aexp_hist->offset_y = 0; + block->offset_y = 0; /* 1x scaling (i.e. none) */ - block.aexp_hist->scale_bottom = 0; - block.aexp_hist->scale_top = 0; + block->scale_bottom = 0; + block->scale_top = 0; /* Collect all Bayer planes into 4 separate histograms */ - block.aexp_hist->plane_mode = 1; + block->plane_mode = 1; /* Tap the data immediately after the digital gain block */ - block.aexp_hist->tap_point = MALI_C55_AEXP_HIST_TAP_FS; - - return block.header->size; + block->tap_point = MALI_C55_AEXP_HIST_TAP_FS; } -size_t Agc::fillWeightsArrayBuffer(mali_c55_params_block block, - enum mali_c55_param_block_type type) +void Agc::fillWeightsArrayBuffer(MaliC55Params *params, const enum MaliC55Blocks type) { - block.header->type = type; - block.header->flags = 0; - block.header->size = sizeof(struct mali_c55_params_aexp_weights); + assert(type == MaliC55Blocks::AexpHistWeights || + type == MaliC55Blocks::AexpIhistWeights); + + auto block = type == MaliC55Blocks::AexpHistWeights ? + params->block() : + params->block(); /* We use every zone - a 15x15 grid */ - block.aexp_weights->nodes_used_horiz = 15; - block.aexp_weights->nodes_used_vert = 15; + block->nodes_used_horiz = 15; + block->nodes_used_vert = 15; /* * We uniformly weight the zones to 1 - this results in the collected @@ -305,40 +303,25 @@ size_t Agc::fillWeightsArrayBuffer(mali_c55_params_block block, * approximate colour channel averages for the image. */ Span weights{ - block.aexp_weights->zone_weights, + block->zone_weights, MALI_C55_MAX_ZONES }; std::fill(weights.begin(), weights.end(), 1); - - return block.header->size; } void Agc::prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, v4l2_isp_params_buffer *params) + IPAFrameContext &frameContext, MaliC55Params *params) { - mali_c55_params_block block; - - block.data = ¶ms->data[params->data_size]; - params->data_size += fillGainParamBlock(context, frameContext, block); + fillGainParamBlock(context, frameContext, params); if (frame > 0) return; - block.data = ¶ms->data[params->data_size]; - params->data_size += fillParamsBuffer(block, - MALI_C55_PARAM_BLOCK_AEXP_HIST); - - block.data = ¶ms->data[params->data_size]; - params->data_size += fillWeightsArrayBuffer(block, - MALI_C55_PARAM_BLOCK_AEXP_HIST_WEIGHTS); - - block.data = ¶ms->data[params->data_size]; - params->data_size += fillParamsBuffer(block, - MALI_C55_PARAM_BLOCK_AEXP_IHIST); + fillParamsBuffer(params, MaliC55Blocks::AexpHist); + fillWeightsArrayBuffer(params, MaliC55Blocks::AexpHistWeights); - block.data = ¶ms->data[params->data_size]; - params->data_size += fillWeightsArrayBuffer(block, - MALI_C55_PARAM_BLOCK_AEXP_IHIST_WEIGHTS); + fillParamsBuffer(params, MaliC55Blocks::AexpIhist); + fillWeightsArrayBuffer(params, MaliC55Blocks::AexpIhistWeights); } double Agc::estimateLuminance(const double gain) const diff --git a/src/ipa/mali-c55/algorithms/agc.h b/src/ipa/mali-c55/algorithms/agc.h index 4325ef5a9b7dcef36107b64a65db993f194d4167..9684fff664bc67d287bb00f8dc88e238d8dd0cea 100644 --- a/src/ipa/mali-c55/algorithms/agc.h +++ b/src/ipa/mali-c55/algorithms/agc.h @@ -57,7 +57,7 @@ public: const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - v4l2_isp_params_buffer *params) override; + MaliC55Params *params) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const mali_c55_stats_buffer *stats, @@ -65,13 +65,11 @@ public: private: double estimateLuminance(const double gain) const override; - size_t fillGainParamBlock(IPAContext &context, - IPAFrameContext &frameContext, - mali_c55_params_block block); - size_t fillParamsBuffer(mali_c55_params_block block, - enum mali_c55_param_block_type type); - size_t fillWeightsArrayBuffer(mali_c55_params_block block, - enum mali_c55_param_block_type type); + void fillGainParamBlock(IPAContext &context, + IPAFrameContext &frameContext, + MaliC55Params *params); + void fillParamsBuffer(MaliC55Params *params, enum MaliC55Blocks type); + void fillWeightsArrayBuffer(MaliC55Params *params, enum MaliC55Blocks type); AgcStatistics statistics_; }; diff --git a/src/ipa/mali-c55/algorithms/awb.cpp b/src/ipa/mali-c55/algorithms/awb.cpp index 694c0aaa9c6804bb58e380ba9c744f11c39224fe..964e810882a93cce02f991675d74bbf163d51e7c 100644 --- a/src/ipa/mali-c55/algorithms/awb.cpp +++ b/src/ipa/mali-c55/algorithms/awb.cpp @@ -43,13 +43,9 @@ int Awb::configure([[maybe_unused]] IPAContext &context, return 0; } -size_t Awb::fillGainsParamBlock(mali_c55_params_block block, IPAContext &context, +void Awb::fillGainsParamBlock(MaliC55Params *params, IPAContext &context, IPAFrameContext &frameContext) { - block.header->type = MALI_C55_PARAM_BLOCK_AWB_GAINS; - block.header->flags = 0; - block.header->size = sizeof(struct mali_c55_params_awb_gains); - double rGain = context.activeState.awb.rGain; double bGain = context.activeState.awb.bGain; @@ -63,34 +59,32 @@ size_t Awb::fillGainsParamBlock(mali_c55_params_block block, IPAContext &context * This holds true regardless of the bayer order of the input data, as * the mapping is done internally in the ISP. */ - block.awb_gains->gain00 = floatingToFixedPoint<4, 8, uint16_t, double>(rGain); - block.awb_gains->gain01 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0); - block.awb_gains->gain10 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0); - block.awb_gains->gain11 = floatingToFixedPoint<4, 8, uint16_t, double>(bGain); + auto block = params->block(); + + block->gain00 = floatingToFixedPoint<4, 8, uint16_t, double>(rGain); + block->gain01 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0); + block->gain10 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0); + block->gain11 = floatingToFixedPoint<4, 8, uint16_t, double>(bGain); frameContext.awb.rGain = rGain; frameContext.awb.bGain = bGain; - - return sizeof(struct mali_c55_params_awb_gains); } -size_t Awb::fillConfigParamBlock(mali_c55_params_block block) +void Awb::fillConfigParamBlock(MaliC55Params *params) { - block.header->type = MALI_C55_PARAM_BLOCK_AWB_CONFIG; - block.header->flags = 0; - block.header->size = sizeof(struct mali_c55_params_awb_config); + auto block = params->block(); /* Tap the stats after the purple fringe block */ - block.awb_config->tap_point = MALI_C55_AWB_STATS_TAP_PF; + block->tap_point = MALI_C55_AWB_STATS_TAP_PF; /* Get R/G and B/G ratios as statistics */ - block.awb_config->stats_mode = MALI_C55_AWB_MODE_RGBG; + block->stats_mode = MALI_C55_AWB_MODE_RGBG; /* Default white level */ - block.awb_config->white_level = 1023; + block->white_level = 1023; /* Default black level */ - block.awb_config->black_level = 0; + block->black_level = 0; /* * By default pixels are included who's colour ratios are bounded in a @@ -104,40 +98,34 @@ size_t Awb::fillConfigParamBlock(mali_c55_params_block block) * * \todo should these perhaps be tunable? */ - block.awb_config->cr_max = 511; - block.awb_config->cr_min = 64; - block.awb_config->cb_max = 511; - block.awb_config->cb_min = 64; + block->cr_max = 511; + block->cr_min = 64; + block->cb_max = 511; + block->cb_min = 64; /* We use the full 15x15 zoning scheme */ - block.awb_config->nodes_used_horiz = 15; - block.awb_config->nodes_used_vert = 15; + block->nodes_used_horiz = 15; + block->nodes_used_vert = 15; /* * We set the trimming boundaries equivalent to the main boundaries. In * other words; no trimming. */ - block.awb_config->cr_high = 511; - block.awb_config->cr_low = 64; - block.awb_config->cb_high = 511; - block.awb_config->cb_low = 64; - - return sizeof(struct mali_c55_params_awb_config); + block->cr_high = 511; + block->cr_low = 64; + block->cb_high = 511; + block->cb_low = 64; } void Awb::prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, v4l2_isp_params_buffer *params) + IPAFrameContext &frameContext, MaliC55Params *params) { - mali_c55_params_block block; - block.data = ¶ms->data[params->data_size]; - - params->data_size += fillGainsParamBlock(block, context, frameContext); + fillGainsParamBlock(params, context, frameContext); if (frame > 0) return; - block.data = ¶ms->data[params->data_size]; - params->data_size += fillConfigParamBlock(block); + fillConfigParamBlock(params); } void Awb::process(IPAContext &context, const uint32_t frame, diff --git a/src/ipa/mali-c55/algorithms/awb.h b/src/ipa/mali-c55/algorithms/awb.h index 647525ff700e8281e3cce63e64ba56a91294bcc2..683a62af263a14d2f5d5b261448953ada6669b2f 100644 --- a/src/ipa/mali-c55/algorithms/awb.h +++ b/src/ipa/mali-c55/algorithms/awb.h @@ -22,17 +22,17 @@ public: const IPACameraSensorInfo &configInfo) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - v4l2_isp_params_buffer *params) override; + MaliC55Params *params) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const mali_c55_stats_buffer *stats, ControlList &metadata) override; private: - size_t fillGainsParamBlock(mali_c55_params_block block, - IPAContext &context, - IPAFrameContext &frameContext); - size_t fillConfigParamBlock(mali_c55_params_block block); + void fillGainsParamBlock(MaliC55Params *params, + IPAContext &context, + IPAFrameContext &frameContext); + void fillConfigParamBlock(MaliC55Params *params); }; } /* namespace ipa::mali_c55::algorithms */ diff --git a/src/ipa/mali-c55/algorithms/blc.cpp b/src/ipa/mali-c55/algorithms/blc.cpp index 543ba96cb57ac0cca2b8f822180d8d8b42f21fc7..d099219c3e43ec96fa452ed13fa46ada2025edc9 100644 --- a/src/ipa/mali-c55/algorithms/blc.cpp +++ b/src/ipa/mali-c55/algorithms/blc.cpp @@ -85,27 +85,19 @@ int BlackLevelCorrection::configure(IPAContext &context, void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context, const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - v4l2_isp_params_buffer *params) + MaliC55Params *params) { - mali_c55_params_block block; - block.data = ¶ms->data[params->data_size]; - if (frame > 0) return; if (!tuningParameters_) return; - block.header->type = MALI_C55_PARAM_BLOCK_SENSOR_OFFS; - block.header->flags = 0; - block.header->size = sizeof(mali_c55_params_sensor_off_preshading); - - block.sensor_offs->chan00 = offset00; - block.sensor_offs->chan01 = offset01; - block.sensor_offs->chan10 = offset10; - block.sensor_offs->chan11 = offset11; - - params->data_size += block.header->size; + auto block = params->block(); + block->chan00 = offset00; + block->chan01 = offset01; + block->chan10 = offset10; + block->chan11 = offset11; } void BlackLevelCorrection::process([[maybe_unused]] IPAContext &context, diff --git a/src/ipa/mali-c55/algorithms/blc.h b/src/ipa/mali-c55/algorithms/blc.h index ee6c889ed89ac2230b231cb58a9fe4412c0ce164..fc5a7ea310cbdbcf271eb26c73b17243aea744cd 100644 --- a/src/ipa/mali-c55/algorithms/blc.h +++ b/src/ipa/mali-c55/algorithms/blc.h @@ -6,6 +6,7 @@ */ #include "algorithm.h" +#include "params.h" namespace libcamera { @@ -22,7 +23,7 @@ public: const IPACameraSensorInfo &configInfo) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - v4l2_isp_params_buffer *params) override; + MaliC55Params *params) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const mali_c55_stats_buffer *stats, diff --git a/src/ipa/mali-c55/algorithms/lsc.cpp b/src/ipa/mali-c55/algorithms/lsc.cpp index cb915c5efd3c22952035f2b03ee659f293942ec9..5b042c757bc70fe4eb4a5aaa848266b3afce9100 100644 --- a/src/ipa/mali-c55/algorithms/lsc.cpp +++ b/src/ipa/mali-c55/algorithms/lsc.cpp @@ -108,41 +108,33 @@ int Lsc::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData return 0; } -size_t Lsc::fillConfigParamsBlock(mali_c55_params_block block) const +void Lsc::fillConfigParamsBlock(MaliC55Params *params) const { - block.header->type = MALI_C55_PARAM_MESH_SHADING_CONFIG; - block.header->flags = 0; - block.header->size = sizeof(struct mali_c55_params_mesh_shading_config); + auto block = params->block(); - block.shading_config->mesh_show = false; - block.shading_config->mesh_scale = meshScale_; - block.shading_config->mesh_page_r = 0; - block.shading_config->mesh_page_g = 1; - block.shading_config->mesh_page_b = 2; - block.shading_config->mesh_width = meshSize_; - block.shading_config->mesh_height = meshSize_; + block->mesh_show = false; + block->mesh_scale = meshScale_; + block->mesh_page_r = 0; + block->mesh_page_g = 1; + block->mesh_page_b = 2; + block->mesh_width = meshSize_; + block->mesh_height = meshSize_; - std::copy(mesh_.begin(), mesh_.end(), block.shading_config->mesh); - - return block.header->size; + std::copy(mesh_.begin(), mesh_.end(), block->mesh); } -size_t Lsc::fillSelectionParamsBlock(mali_c55_params_block block, uint8_t bank, +void Lsc::fillSelectionParamsBlock(MaliC55Params *params, uint8_t bank, uint8_t alpha) const { - block.header->type = MALI_C55_PARAM_MESH_SHADING_SELECTION; - block.header->flags = 0; - block.header->size = sizeof(struct mali_c55_params_mesh_shading_selection); - - block.shading_selection->mesh_alpha_bank_r = bank; - block.shading_selection->mesh_alpha_bank_g = bank; - block.shading_selection->mesh_alpha_bank_b = bank; - block.shading_selection->mesh_alpha_r = alpha; - block.shading_selection->mesh_alpha_g = alpha; - block.shading_selection->mesh_alpha_b = alpha; - block.shading_selection->mesh_strength = 0x1000; /* Otherwise known as 1.0 */ - - return block.header->size; + auto block = params->block(); + + block->mesh_alpha_bank_r = bank; + block->mesh_alpha_bank_g = bank; + block->mesh_alpha_bank_b = bank; + block->mesh_alpha_r = alpha; + block->mesh_alpha_g = alpha; + block->mesh_alpha_b = alpha; + block->mesh_strength = 0x1000; /* Otherwise known as 1.0 */ } std::tuple Lsc::findBankAndAlpha(uint32_t ct) const @@ -170,7 +162,7 @@ std::tuple Lsc::findBankAndAlpha(uint32_t ct) const void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - v4l2_isp_params_buffer *params) + MaliC55Params *params) { /* * For each frame we assess the colour temperature of the **last** frame @@ -193,10 +185,7 @@ void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, std::tie(bank, alpha) = findBankAndAlpha(temperatureK); } - mali_c55_params_block block; - block.data = ¶ms->data[params->data_size]; - - params->data_size += fillSelectionParamsBlock(block, bank, alpha); + fillSelectionParamsBlock(params, bank, alpha); if (frame > 0) return; @@ -205,8 +194,7 @@ void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, * If this is the first frame, we need to load the parsed coefficient * tables from tuning data to the ISP. */ - block.data = ¶ms->data[params->data_size]; - params->data_size += fillConfigParamsBlock(block); + fillConfigParamsBlock(params); } REGISTER_IPA_ALGORITHM(Lsc, "Lsc") diff --git a/src/ipa/mali-c55/algorithms/lsc.h b/src/ipa/mali-c55/algorithms/lsc.h index c287900502528ca82ab6c62d732b6ffc28ad8df6..e7092bc74a0b0301463167d16e1e888696547d10 100644 --- a/src/ipa/mali-c55/algorithms/lsc.h +++ b/src/ipa/mali-c55/algorithms/lsc.h @@ -23,15 +23,15 @@ public: int init(IPAContext &context, const YamlObject &tuningData) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - v4l2_isp_params_buffer *params) override; + MaliC55Params *params) override; private: static constexpr unsigned int kRedOffset = 0; static constexpr unsigned int kGreenOffset = 1024; static constexpr unsigned int kBlueOffset = 2048; - size_t fillConfigParamsBlock(mali_c55_params_block block) const; - size_t fillSelectionParamsBlock(mali_c55_params_block block, - uint8_t bank, uint8_t alpha) const; + void fillConfigParamsBlock(MaliC55Params *params) const; + void fillSelectionParamsBlock(MaliC55Params *params, + uint8_t bank, uint8_t alpha) const; std::tuple findBankAndAlpha(uint32_t ct) const; std::vector mesh_ = std::vector(3072); diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp index 504d95222074a35b033949a25178f998738e5699..e05acf277dd832ace240885d4259cc78c55e85c0 100644 --- a/src/ipa/mali-c55/mali-c55.cpp +++ b/src/ipa/mali-c55/mali-c55.cpp @@ -28,6 +28,7 @@ #include "libipa/camera_sensor_helper.h" #include "ipa_context.h" +#include "params.h" namespace libcamera { @@ -331,24 +332,13 @@ void IPAMaliC55::queueRequest(const uint32_t request, const ControlList &control void IPAMaliC55::fillParams(unsigned int request, [[maybe_unused]] uint32_t bufferId) { - struct v4l2_isp_params_buffer *params; IPAFrameContext &frameContext = context_.frameContexts.get(request); + MaliC55Params params(buffers_.at(bufferId).planes()[0]); - params = reinterpret_cast( - buffers_.at(bufferId).planes()[0].data()); - memset(params, 0, - buffers_.at(bufferId).planes()[0].size()); - - params->version = MALI_C55_PARAM_BUFFER_V1; - - for (auto const &algo : algorithms()) { - algo->prepare(context_, request, frameContext, params); - - ASSERT(params->data_size <= MALI_C55_PARAMS_MAX_SIZE); - } + for (auto const &algo : algorithms()) + algo->prepare(context_, request, frameContext, ¶ms); - size_t bytesused = offsetof(struct v4l2_isp_params_buffer, data) + params->data_size; - paramsComputed.emit(request, bytesused); + paramsComputed.emit(request, params.bytesused()); } void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId, diff --git a/src/ipa/mali-c55/module.h b/src/ipa/mali-c55/module.h index a8dcb20841a4ebd7bde22cae4ff1f8eef530d8bb..13b34eb2839530a3518340165e6ca895d0f6bcaf 100644 --- a/src/ipa/mali-c55/module.h +++ b/src/ipa/mali-c55/module.h @@ -14,13 +14,14 @@ #include #include "ipa_context.h" +#include "params.h" namespace libcamera { namespace ipa::mali_c55 { using Module = ipa::Module; + MaliC55Params, mali_c55_stats_buffer>; } /* namespace ipa::mali_c55 */ diff --git a/src/ipa/mali-c55/params.h b/src/ipa/mali-c55/params.h new file mode 100644 index 0000000000000000000000000000000000000000..370f1b8b77bcf9ca5658ff75fca855b4c5f8467b --- /dev/null +++ b/src/ipa/mali-c55/params.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2025, Ideas On Board + * + * Mali C55 ISP Parameters + */ + +#pragma once + +#include +#include + +#include + +namespace libcamera { + +namespace ipa::mali_c55 { + +enum class MaliC55Blocks { + Bls, + AexpHist, + AexpHistWeights, + AexpIhist, + AexpIhistWeights, + Dgain, + AwbGains, + AwbConfig, + MeshShadingConfig, + MeshShadingSel, +}; + +namespace details { + +template +struct block_type { +}; + +#define MALI_C55_DEFINE_BLOCK_TYPE(id, cfgType, blkType) \ +template<> \ +struct block_type { \ + using type = struct mali_c55_params_##cfgType; \ + static constexpr mali_c55_param_block_type blockType = \ + mali_c55_param_block_type::MALI_C55_PARAM_##blkType; \ +} + +MALI_C55_DEFINE_BLOCK_TYPE(Bls, sensor_off_preshading, BLOCK_SENSOR_OFFS); +MALI_C55_DEFINE_BLOCK_TYPE(AexpHist, aexp_hist, BLOCK_AEXP_HIST); +MALI_C55_DEFINE_BLOCK_TYPE(AexpHistWeights, aexp_weights, BLOCK_AEXP_HIST_WEIGHTS); +MALI_C55_DEFINE_BLOCK_TYPE(AexpIhist, aexp_hist, BLOCK_AEXP_IHIST); +MALI_C55_DEFINE_BLOCK_TYPE(AexpIhistWeights, aexp_weights, BLOCK_AEXP_IHIST_WEIGHTS); +MALI_C55_DEFINE_BLOCK_TYPE(Dgain, digital_gain, BLOCK_DIGITAL_GAIN); +MALI_C55_DEFINE_BLOCK_TYPE(AwbGains, awb_gains, BLOCK_AWB_GAINS); +MALI_C55_DEFINE_BLOCK_TYPE(AwbConfig, awb_config, BLOCK_AWB_CONFIG); +MALI_C55_DEFINE_BLOCK_TYPE(MeshShadingConfig, mesh_shading_config, MESH_SHADING_CONFIG); +MALI_C55_DEFINE_BLOCK_TYPE(MeshShadingSel, mesh_shading_selection, MESH_SHADING_SELECTION); + +struct param_traits { + using id_type = MaliC55Blocks; + + template + using id_to_details = block_type; +}; + +} /* namespace details */ + +class MaliC55Params : public V4L2Params +{ +public: + MaliC55Params(Span data) + : V4L2Params(data, V4L2_ISP_PARAMS_VERSION_V1) + { + } +}; + +} /* namespace ipa::mali_c55 */ + +} /* namespace libcamera */