* [PATCH v5 0/8] media: Introduce V4L2 generic ISP support
@ 2025-09-15 17:18 Jacopo Mondi
2025-09-15 17:18 ` [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types Jacopo Mondi
` (8 more replies)
0 siblings, 9 replies; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
Extensible parameters meta formats have been introduced in the Linux
kernel v6.12 initially to support different revision of the RkISP1 ISP
implemented in different SoC. In order to avoid breaking userspace
everytime an ISP configuration block is added or modified in the uAPI
these new formats, which are versionated and extensible by their
definition have been introduced.
See for reference:
e9d05e9d5db1 ("media: uapi: rkisp1-config: Add extensible params format")
6c53a7b68c5d ("media: rkisp1: Implement extensible params support")
The Amlogic C3 ISP driver followed shortly, introducing an extensible
format for the ISP configuration:
6d406187ebc0 ("media: uapi: Add stats info and parameters buffer for C3 ISP")
with a very similar, if not identical, implementation of the routines to
validate and handle the ISP configuration in the ISP driver in the
c3-isp-params.c file.
fb2e135208f3 ("media: platform: Add C3 ISP driver")
With the recent upstreaming attempt of the Mali C55 ISP driver from Dan,
a third user of extensible parameters is going to be itroduced in the
kernel, duplicating again in the driver the procedure for validating and
handling the ISP configuration blocks
https://patchwork.linuxtv.org/project/linux-media/patch/20250624-c55-v10-15-54f3d4196990@ideasonboard.com/
To avoid duplicating again the validation routines and common types
definition, this series introduces v4l2-isp.c/.h for the kAPI
and v4l2-isp.h for the uAPI and re-organize the RkISP1
and Amlogic C3 drivers to use the common types and the helper validation
routines.
The v4l2-isp abstraction will be augmented to support statistcs as well.
If the here proposed approach is accepted, I propose to rebase the Mali
C55 driver on top of this series, to use the new common types and
helpers.
I have been able to test this on RkISP1 but not on C3.
Thanks
j
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
Changes in v5:
- Move everything to v4l2-isp prefix except from format documentation
which still is about 'extensible-parameters' (to be paired in future
with extensbile-stats)
- Simplify documentation and move it part to the driver-api
Documentation
- Remove 'group' and 'features' from the generic handlers definition and
adjust rkisp1 accordingly
- Link to v4: https://lore.kernel.org/r/20250820-extensible-parameters-validation-v4-0-30fe5a99cb1f@ideasonboard.com
Changes in v4:
- Fix the definition of V4L2_PARAMS_FL_PLATFORM_FLAGS
- Add __counted_by() attribute to the data[] flexible-array member of
v4l2_params_buffer
- Minor style change
- Link to v3: https://lore.kernel.org/r/20250819-extensible-parameters-validation-v3-0-9dc008348b30@ideasonboard.com
Changes in v3:
- Rebased on latest media-committers/next
- Take in Dan's suggestion in block size validation
- Documentation minor spelling fixes
- Link to v2: https://lore.kernel.org/r/20250710-extensible-parameters-validation-v2-0-7ec8918ec443@ideasonboard.com
Changes in v2:
- Make v4l2_params_buffer directly usable
- Centralize ENABLE/DISABLE flags definition and validation
- Take in Dan's v4l2_params_buffer_size()
- Allow blocks to only contain the header if they're going to be
disabled
- Documentation fixes as reported by Nicolas
- Link to v1: https://lore.kernel.org/r/20250708-extensible-parameters-validation-v1-0-9fc27c9c728c@ideasonboard.com
---
Jacopo Mondi (8):
media: uapi: Introduce V4L2 generic ISP types
media: uapi: Convert RkISP1 to V4L2 extensible params
media: uapi: Convert Amlogic C3 to V4L2 extensible params
media: Documentation: uapi: Add V4L2 extensible parameters
media: v4l2-core: Introduce v4l2-isp.c
media: rkisp1: Use v4l2-isp for validation
media: amlogic-c3: Use v4l2-isp for validation
media: Documentation: kapi: Add v4l2 generic ISP support
Documentation/driver-api/media/v4l2-core.rst | 1 +
Documentation/driver-api/media/v4l2-isp.rst | 37 ++
.../media/v4l/extensible-parameters.rst | 97 +++++
.../userspace-api/media/v4l/meta-formats.rst | 1 +
MAINTAINERS | 10 +
drivers/media/platform/amlogic/c3/isp/Kconfig | 1 +
.../media/platform/amlogic/c3/isp/c3-isp-params.c | 248 ++++--------
drivers/media/platform/rockchip/rkisp1/Kconfig | 1 +
.../media/platform/rockchip/rkisp1/rkisp1-params.c | 441 ++++++++++-----------
drivers/media/v4l2-core/Kconfig | 4 +
drivers/media/v4l2-core/Makefile | 1 +
drivers/media/v4l2-core/v4l2-isp.c | 108 +++++
include/media/v4l2-isp.h | 100 +++++
include/uapi/linux/media/amlogic/c3-isp-config.h | 86 +---
include/uapi/linux/media/v4l2-isp.h | 100 +++++
include/uapi/linux/rkisp1-config.h | 104 +----
16 files changed, 793 insertions(+), 547 deletions(-)
---
base-commit: 0e2ee70291e64a30fe36960c85294726d34a103e
change-id: 20250701-extensible-parameters-validation-c831f7f5cc0b
Best regards,
--
Jacopo Mondi <jacopo.mondi@ideasonboard.com>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
@ 2025-09-15 17:18 ` Jacopo Mondi
2025-10-05 0:06 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 2/8] media: uapi: Convert RkISP1 to V4L2 extensible params Jacopo Mondi
` (7 subsequent siblings)
8 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
Introduce v4l2-isp.h in the Linux kernel uAPI.
The header includes types for generic ISP configuration parameters
and will be extended in future with support for generic ISP statistics
formats.
Generic ISP parameters support is provided by introducing two new
types that represent an extensible and versioned buffer of ISP
configuration parameters.
The v4l2_params_block_header structure represents the header to be
prepend to each ISP configuration block and the v4l2_params_buffer type
represents the base type for the configuration parameters buffer.
The v4l2_params_buffer represents the container for the ISP
configuration data block. The generic type is defined with a 0-sized
data member that the ISP driver implementations shall properly size
according to their capabilities.
[Add v4l2_params_buffer_size()]
Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
MAINTAINERS | 6 +++
include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
2 files changed, 106 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
F: drivers/media/i2c/vd56g3.c
F: drivers/media/i2c/vgxy61.c
+V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
+M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: include/uapi/linux/media/v4l2-isp.h
+
VF610 NAND DRIVER
M: Stefan Agner <stefan@agner.ch>
L: linux-mtd@lists.infradead.org
diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
new file mode 100644
index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
--- /dev/null
+++ b/include/uapi/linux/media/v4l2-isp.h
@@ -0,0 +1,100 @@
+/* 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 <jacopo.mondi@ideasonboard.com>
+ */
+
+#ifndef _UAPI_V4L2_ISP_H_
+#define _UAPI_V4L2_ISP_H_
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+
+#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
+#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
+
+/*
+ * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
+ *
+ * Driver-specific flags should be defined as:
+ * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
+ * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
+ */
+#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
+
+/**
+ * struct v4l2_params_block_header - V4L2 extensible parameters block 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
+ * driver inspects this common header to discern the block type and its size and
+ * properly handle the block content.
+ *
+ * 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_FL_* and
+ * driver-specific flags specified by the driver 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
+ */
+struct v4l2_params_block_header {
+ __u16 type;
+ __u16 flags;
+ __u32 size;
+} __attribute__((aligned(8)));
+
+/**
+ * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
+ *
+ * Users of the v4l2 extensible parameters will have differing sized data arrays
+ * depending on their specific parameter buffers. Drivers and userspace will
+ * need to be able to calculate the appropriate size of the struct to
+ * accommodate all ISP configuration blocks provided by the platform.
+ * This macro provides a convenient tool for the calculation.
+ *
+ * @max_params_size: The total size of the ISP configuration blocks
+ */
+#define v4l2_params_buffer_size(max_params_size) \
+ (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
+
+/**
+ * struct v4l2_params_buffer - V4L2 extensible parameters configuration
+ *
+ * This struct 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_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 nor overlaps. Userspace shall populate the @data_size field with
+ * the effective size, in bytes, of the @data buffer.
+ *
+ * @version: The parameters buffer version (driver-specific)
+ * @data_size: The configuration data effective size, excluding this header
+ * @data: The configuration data
+ */
+struct v4l2_params_buffer {
+ __u32 version;
+ __u32 data_size;
+ __u8 data[] __counted_by(data_size);
+};
+
+#endif /* _UAPI_V4L2_ISP_H_ */
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v5 2/8] media: uapi: Convert RkISP1 to V4L2 extensible params
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
2025-09-15 17:18 ` [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types Jacopo Mondi
@ 2025-09-15 17:18 ` Jacopo Mondi
2025-10-05 0:18 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 3/8] media: uapi: Convert Amlogic C3 " Jacopo Mondi
` (6 subsequent siblings)
8 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
With the introduction of common types for extensible parameters
format, convert the rkisp1-config.h header to use the new types.
Factor-out the documentation that is now part of the common header
and only keep the driver-specific on in place.
The conversion to use common types doesn't impact userspace as the
new types are either identical to the ones already existing in the
RkISP1 uAPI or are 1-to-1 type convertible.
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
include/uapi/linux/rkisp1-config.h | 104 ++++++++-----------------------------
1 file changed, 22 insertions(+), 82 deletions(-)
diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
index 3b060ea6eed71b87d79abc8401eae4e9c9f5323a..b90d94d3a852fb0af0fe447649487e9e80aca795 100644
--- a/include/uapi/linux/rkisp1-config.h
+++ b/include/uapi/linux/rkisp1-config.h
@@ -7,8 +7,13 @@
#ifndef _UAPI_RKISP1_CONFIG_H
#define _UAPI_RKISP1_CONFIG_H
+#ifdef __KERNEL__
+#include <linux/build_bug.h>
+#endif /* __KERNEL__ */
#include <linux/types.h>
+#include <linux/media/v4l2-isp.h>
+
/* Defect Pixel Cluster Detection */
#define RKISP1_CIF_ISP_MODULE_DPCC (1U << 0)
/* Black Level Subtraction */
@@ -1158,79 +1163,26 @@ enum rkisp1_ext_params_block_type {
RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR,
};
-#define RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE (1U << 0)
-#define RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE (1U << 1)
+/* For backward compatibility */
+#define RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE V4L2_PARAMS_FL_BLOCK_DISABLE
+#define RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE V4L2_PARAMS_FL_BLOCK_ENABLE
/* A bitmask of parameters blocks supported on the current hardware. */
#define RKISP1_CID_SUPPORTED_PARAMS_BLOCKS (V4L2_CID_USER_RKISP1_BASE + 0x01)
/**
- * struct rkisp1_ext_params_block_header - RkISP1 extensible parameters block
- * header
+ * rkisp1_ext_params_block_header - RkISP1 extensible parameters block 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
- * 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.
+ * blocks and is identical to :c:type:`v4l2_params_block_header`.
*
- * The @type field is one of the values enumerated by
+ * The type field is one of the values enumerated by
* :c:type:`rkisp1_ext_params_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 is a bitmask of per-block flags RKISP1_EXT_PARAMS_FL_*.
- *
- * When userspace wants to configure and enable an ISP block it shall fully
- * populate the block configuration and set the
- * RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE bit in the @flags field.
- *
- * When userspace simply wants to disable an ISP block the
- * RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bit should be set in @flags field. The
- * driver ignores the rest of the block configuration structure in this case.
- *
- * If a new configuration of an ISP block has to be applied userspace shall
- * fully populate the ISP block configuration and omit setting the
- * RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE and RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bits
- * in the @flags field.
- *
- * Setting both the RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE and
- * RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bits in the @flags field is not allowed
- * and not accepted by the driver.
- *
- * Userspace is responsible for correctly populating the parameters block header
- * fields (@type, @flags and @size) and the block-specific parameters.
- *
- * For example:
+ * interpreted by the driver.
*
- * .. code-block:: c
- *
- * void populate_bls(struct rkisp1_ext_params_block_header *block) {
- * struct rkisp1_ext_params_bls_config *bls =
- * (struct rkisp1_ext_params_bls_config *)block;
- *
- * bls->header.type = RKISP1_EXT_PARAMS_BLOCK_ID_BLS;
- * bls->header.flags = RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE;
- * bls->header.size = sizeof(*bls);
- *
- * bls->config.enable_auto = 0;
- * bls->config.fixed_val.r = blackLevelRed_;
- * bls->config.fixed_val.gr = blackLevelGreenR_;
- * bls->config.fixed_val.gb = blackLevelGreenB_;
- * bls->config.fixed_val.b = blackLevelBlue_;
- * }
- *
- * @type: The parameters block type, see
- * :c:type:`rkisp1_ext_params_block_type`
- * @flags: A bitmask of block flags
- * @size: Size (in bytes) of the parameters block, including this header
+ * The flags field is a bitmask of per-block flags RKISP1_EXT_PARAMS_FL_*.
*/
-struct rkisp1_ext_params_block_header {
- __u16 type;
- __u16 flags;
- __u32 size;
-};
+#define rkisp1_ext_params_block_header v4l2_params_block_header
/**
* struct rkisp1_ext_params_bls_config - RkISP1 extensible params BLS config
@@ -1594,21 +1546,7 @@ enum rksip1_ext_param_buffer_version {
/**
* struct rkisp1_ext_params_cfg - RkISP1 extensible parameters configuration
*
- * This struct contains the configuration parameters of the RkISP1 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:`rkisp1_ext_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.
+ * This is the driver-specific implementation of :c:type:`v4l2_params_buffer`.
*
* Currently the single RKISP1_EXT_PARAM_BUFFER_V1 version is supported.
* When a new format version will be added, a mechanism for userspace to query
@@ -1624,11 +1562,6 @@ enum rksip1_ext_param_buffer_version {
* the maximum value represents the blocks supported by the kernel driver,
* independently of the device instance.
*
- * 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 @data_size field with
- * the effective size, in bytes, of the @data buffer.
- *
* The expected memory layout of the parameters buffer is::
*
* +-------------------- struct rkisp1_ext_params_cfg -------------------+
@@ -1678,4 +1611,11 @@ struct rkisp1_ext_params_cfg {
__u8 data[RKISP1_EXT_PARAMS_MAX_SIZE];
};
+#ifdef __KERNEL__
+/* Make sure the header is type-convertible to the generic v4l2 params one */
+static_assert((sizeof(struct rkisp1_ext_params_cfg) -
+ RKISP1_EXT_PARAMS_MAX_SIZE) ==
+ sizeof(struct v4l2_params_buffer));
+#endif /* __KERNEL__ */
+
#endif /* _UAPI_RKISP1_CONFIG_H */
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v5 3/8] media: uapi: Convert Amlogic C3 to V4L2 extensible params
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
2025-09-15 17:18 ` [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types Jacopo Mondi
2025-09-15 17:18 ` [PATCH v5 2/8] media: uapi: Convert RkISP1 to V4L2 extensible params Jacopo Mondi
@ 2025-09-15 17:18 ` Jacopo Mondi
2025-10-05 0:24 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 4/8] media: Documentation: uapi: Add V4L2 extensible parameters Jacopo Mondi
` (5 subsequent siblings)
8 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
With the introduction of common types for extensible parameters
format, convert the c3-isp-config.h header to use the new types.
Factor-out the documentation that is now part of the common header
and only keep the driver-specific on in place.
The conversion to use common types doesn't impact userspace as the
new types are either identical to the ones already existing in the
C3 ISP uAPI or are 1-to-1 type convertible.
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Keke Li <keke.li@amlogic.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
include/uapi/linux/media/amlogic/c3-isp-config.h | 86 ++++++------------------
1 file changed, 20 insertions(+), 66 deletions(-)
diff --git a/include/uapi/linux/media/amlogic/c3-isp-config.h b/include/uapi/linux/media/amlogic/c3-isp-config.h
index ed085ea62a574932c7ad8d59d34b2c5c74a597d8..bf6de55b27a7d4d15effcca5525865650d9070fb 100644
--- a/include/uapi/linux/media/amlogic/c3-isp-config.h
+++ b/include/uapi/linux/media/amlogic/c3-isp-config.h
@@ -6,8 +6,13 @@
#ifndef _UAPI_C3_ISP_CONFIG_H_
#define _UAPI_C3_ISP_CONFIG_H_
+#ifdef __KERNEL__
+#include <linux/build_bug.h>
+#endif /* __KERNEL__ */
#include <linux/types.h>
+#include <linux/media/v4l2-isp.h>
+
/*
* Frames are split into zones of almost equal width and height - a zone is a
* rectangular tile of a frame. The metering blocks within the ISP collect
@@ -176,62 +181,22 @@ enum c3_isp_params_block_type {
C3_ISP_PARAMS_BLOCK_SENTINEL
};
-#define C3_ISP_PARAMS_BLOCK_FL_DISABLE (1U << 0)
-#define C3_ISP_PARAMS_BLOCK_FL_ENABLE (1U << 1)
+/* For backward compatibility */
+#define C3_ISP_PARAMS_BLOCK_FL_DISABLE V4L2_PARAMS_FL_BLOCK_DISABLE
+#define C3_ISP_PARAMS_BLOCK_FL_ENABLE V4L2_PARAMS_FL_BLOCK_ENABLE
/**
* struct c3_isp_params_block_header - C3 ISP parameter block 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
- * 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:`c3_isp_params_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 is a bitmask of per-block flags C3_ISP_PARAMS_FL*.
- *
- * When userspace wants to disable an ISP block the
- * C3_ISP_PARAMS_BLOCK_FL_DISABLED bit should be set in the @flags field. In
- * this case userspace may optionally omit the remainder of the configuration
- * block, which will be ignored by the driver.
- *
- * When a new configuration of an ISP block needs to be applied userspace
- * shall fully populate the ISP block and omit setting the
- * C3_ISP_PARAMS_BLOCK_FL_DISABLED bit in the @flags field.
- *
- * Userspace is responsible for correctly populating the parameters block header
- * fields (@type, @flags and @size) and the block-specific parameters.
- *
- * For example:
- *
- * .. code-block:: c
+ * interpreted by the driver.
*
- * void populate_pst_gamma(struct c3_isp_params_block_header *block) {
- * struct c3_isp_params_pst_gamma *gamma =
- * (struct c3_isp_params_pst_gamma *)block;
- *
- * gamma->header.type = C3_ISP_PARAMS_BLOCK_PST_GAMMA;
- * gamma->header.flags = C3_ISP_PARAMS_BLOCK_FL_ENABLE;
- * gamma->header.size = sizeof(*gamma);
- *
- * for (unsigned int i = 0; i < 129; i++)
- * gamma->pst_gamma_lut[i] = i;
- * }
- *
- * @type: The parameters block type from :c:type:`c3_isp_params_block_type`
- * @flags: A bitmask of block flags
- * @size: Size (in bytes) of the parameters block, including this header
+ * The flags field is a bitmask of per-block flags C3_ISP_PARAMS_FL_*.
*/
-struct c3_isp_params_block_header {
- __u16 type;
- __u16 flags;
- __u32 size;
-};
+#define c3_isp_params_block_header v4l2_params_block_header
/**
* struct c3_isp_params_awb_gains - Gains for auto-white balance
@@ -498,26 +463,9 @@ struct c3_isp_params_blc {
/**
* struct c3_isp_params_cfg - C3 ISP configuration parameters
*
- * This struct contains the configuration parameters of the C3 ISP
- * algorithms, serialized by userspace into an opaque data buffer. Each
- * configuration parameter block is represented by a block-specific structure
- * which contains a :c:type:`c3_isp_param_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 should 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 revision and return an error if the desired revision 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.
+ * This is the driver-specific implementation of :c:type:`v4l2_params_buffer`.
+ *
+ * Currently only C3_ISP_PARAM_BUFFER_V0 is supported.
*
* The expected memory layout of the parameters buffer is::
*
@@ -561,4 +509,10 @@ struct c3_isp_params_cfg {
__u8 data[C3_ISP_PARAMS_MAX_SIZE];
};
+#ifdef __KERNEL__
+/* Make sure the header is type-convertible to the generic v4l2 params one */
+static_assert((sizeof(struct c3_isp_params_cfg) - C3_ISP_PARAMS_MAX_SIZE) ==
+ sizeof(struct v4l2_params_buffer));
+#endif /* __KERNEL__ */
+
#endif
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v5 4/8] media: Documentation: uapi: Add V4L2 extensible parameters
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
` (2 preceding siblings ...)
2025-09-15 17:18 ` [PATCH v5 3/8] media: uapi: Convert Amlogic C3 " Jacopo Mondi
@ 2025-09-15 17:18 ` Jacopo Mondi
2025-10-06 1:17 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c Jacopo Mondi
` (4 subsequent siblings)
8 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
Add documentation for extensible parameters format to the V4L2
userspace API documentation.
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
.../media/v4l/extensible-parameters.rst | 97 ++++++++++++++++++++++
.../userspace-api/media/v4l/meta-formats.rst | 1 +
MAINTAINERS | 1 +
3 files changed, 99 insertions(+)
diff --git a/Documentation/userspace-api/media/v4l/extensible-parameters.rst b/Documentation/userspace-api/media/v4l/extensible-parameters.rst
new file mode 100644
index 0000000000000000000000000000000000000000..e95c84f90c1b472360306d97c9b27123cd4bb6af
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/extensible-parameters.rst
@@ -0,0 +1,97 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+
+.. _extensible-parameters:
+
+*************************************
+V4L2 extensible ISP parameters format
+*************************************
+
+ISP configuration
+=================
+
+ISP configuration parameters are computed by userspace and programmed into a
+*parameters buffer* which is queued to the ISP driver on a per-frame basis. The
+layout of the *parameters buffer* generally reflects the ISP peripheral
+registers layout and is, for this reason, platform specific.
+
+The ISP configuration parameters are passed to the ISP driver through a metadata
+output video node, using the :c:type:`v4l2_meta_format` interface. Each ISP
+driver defines a metadata format that implements the configuration parameters
+layout.
+
+Metadata output formats that describe ISP configuration parameters are most of
+the time realized by implementing C structures that reflect the registers layout
+and gets populated by userspace before queueing the buffer to the ISP. Each
+C structure usually corresponds to one ISP *processing block*, with each block
+implementing one of the ISP supported features.
+
+The uAPI/ABI problem
+--------------------
+
+By upstreaming data types that describe the configuration parameters layout,
+driver developers make them part of the Linux kernel ABI. As it sometimes
+happens for most peripherals in Linux, ISP drivers development is often an
+iterative process, where sometimes not all the hardware features are supported
+in the first version that lands in the kernel, and some parts of the interface
+have to later be modified for bug-fixes or improvements.
+
+If any later bug-fix/improvement requires changes to the metadata output format,
+this is considered an ABI-breakage that is strictly forbidden by the Linux
+kernel policies. For this reason, each new iteration of an ISP driver support
+would require defining a new metadata output format, implying that drivers have
+to be made ready to handle several different configuration formats.
+
+Support for generic ISP parameters buffer has been designed with the goal of
+being:
+
+- Extensible: new features can be added later on without breaking the existing
+ interface
+- Versioned: different versions of the format can be defined without
+ breaking the existing interface
+
+The extensible parameters format
+================================
+
+Extensible configuration parameters formats are realized by a defining a single
+C structure that contains a few control parameters and a binary buffer where
+userspace programs a variable number of *ISP configuration blocks* data.
+
+The generic :c:type:`v4l2_params_buffer` defines a base type that each driver
+can use by properly sizing the data buffer array by providing a definition of
+maximum supported parameters buffer size.
+
+Each *ISP configuration block* is identified by an header and contains the
+parameters for that specific block.
+
+The generic :c:type:`v4l2_params_block_header` defines a base type that each
+driver can re-use as it is or extend appropriately.
+
+Userspace applications are responsible for correctly populating the parameters
+block header fields (type, flags and size) and the block-specific parameters.
+
+When userspace wants to configure and enable an ISP block it shall fully
+populate the block configuration and set the V4L2_PARAMS_FL_BLOCK_ENABLE
+bit in the flags field.
+
+When userspace simply wants to disable an ISP block the
+V4L2_PARAMS_FL_BLOCK_DISABLE bit should be set in flags field. The driver
+ignores the rest of the block configuration structure in this case.
+
+If a new configuration of an ISP block has to be applied, userspace shall fully
+populate the ISP block configuration and omit setting the
+V4L2_PARAMS_FL_BLOCK_ENABLE and V4L2_PARAMS_FL_BLOCK_DISABLE bits in
+the flags field.
+
+Setting both the V4L2_PARAMS_FL_BLOCK_ENABLE and V4L2_PARAMS_FL_BLOCK_DISABLE
+bits in the flags field is not allowed and not accepted.
+
+Any further development that happens after the ISP driver has been merged in
+Linux and which requires supporting new ISP features can be implemented by
+adding new blocks definition without invalidating the existing ones. Similarly,
+any change to the existing ISP configuration blocks can be handled by versioning
+them, again without invalidating the existing ones.
+
+V4L2 extensible parameters uAPI data types
+==========================================
+
+.. kernel-doc:: include/uapi/linux/media/v4l2-isp.h
diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst
index 0de80328c36bf148051a19abe9e5241234ddfe5c..b900ed6af7bd9ad49baf7b5a9eef9423f8abfbcb 100644
--- a/Documentation/userspace-api/media/v4l/meta-formats.rst
+++ b/Documentation/userspace-api/media/v4l/meta-formats.rst
@@ -12,6 +12,7 @@ These formats are used for the :ref:`metadata` interface only.
.. toctree::
:maxdepth: 1
+ extensible-parameters
metafmt-c3-isp
metafmt-d4xx
metafmt-generic
diff --git a/MAINTAINERS b/MAINTAINERS
index e82c3d0758d6033fe8fcd56ffde2c03c4319fd11..abba872cb63f1430a49a2afbace4b9f9958c3991 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26414,6 +26414,7 @@ V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
+F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
F: include/uapi/linux/media/v4l2-isp.h
VF610 NAND DRIVER
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
` (3 preceding siblings ...)
2025-09-15 17:18 ` [PATCH v5 4/8] media: Documentation: uapi: Add V4L2 extensible parameters Jacopo Mondi
@ 2025-09-15 17:18 ` Jacopo Mondi
2025-10-06 0:47 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 6/8] media: rkisp1: Use v4l2-isp for validation Jacopo Mondi
` (3 subsequent siblings)
8 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
Add to the v4l2 framework helper functions to support drivers
when validating a buffer of extensible ISP parameters.
Introduce new types in include/media/v4l2-isp.h that drivers shall use
in order to comply with the generic ISP parameters validation procedure,
and add helper functionss to v4l2-isp.c to perform blocks and buffer
validation.
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
MAINTAINERS | 2 +
drivers/media/v4l2-core/Kconfig | 4 ++
drivers/media/v4l2-core/Makefile | 1 +
drivers/media/v4l2-core/v4l2-isp.c | 108 +++++++++++++++++++++++++++++++++++++
include/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++
5 files changed, 215 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index abba872cb63f1430a49a2afbace4b9f9958c3991..5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26415,6 +26415,8 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
+F: drivers/media/v4l2-core/v4l2-isp.c
+F: include/media/v4l2-isp.h
F: include/uapi/linux/media/v4l2-isp.h
VF610 NAND DRIVER
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 331b8e535e5bbf33f22638b2ae8bc764ad5fc407..d50ccac9733cc39a43426ae7e7996dd0b5b45186 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -82,3 +82,7 @@ config V4L2_CCI_I2C
depends on I2C
select REGMAP_I2C
select V4L2_CCI
+
+config V4L2_ISP
+ tristate
+ depends on VIDEOBUF2_CORE
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
index 2177b9d63a8ffc1127c5a70118249a2ff63cd759..329f0eadce994cc1c8580beb435f68fa7e2a7aeb 100644
--- a/drivers/media/v4l2-core/Makefile
+++ b/drivers/media/v4l2-core/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o
obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
obj-$(CONFIG_V4L2_H264) += v4l2-h264.o
+obj-$(CONFIG_V4L2_ISP) += v4l2-isp.o
obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o
obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o
diff --git a/drivers/media/v4l2-core/v4l2-isp.c b/drivers/media/v4l2-core/v4l2-isp.c
new file mode 100644
index 0000000000000000000000000000000000000000..e350bdaf53b5502e1ec2a4989c20df1100ab2d2a
--- /dev/null
+++ b/drivers/media/v4l2-core/v4l2-isp.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Video4Linux2 generic ISP parameters and statistics support
+ *
+ * Copyright (C) 2025 Ideas On Board Oy
+ * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+
+#include <media/videobuf2-core.h>
+#include <media/v4l2-isp.h>
+
+int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
+ size_t max_size)
+{
+ size_t header_size = offsetof(struct v4l2_params_buffer, data);
+ struct v4l2_params_buffer *buffer = vb2_plane_vaddr(vb, 0);
+ size_t payload_size = vb2_get_plane_payload(vb, 0);
+ size_t buffer_size;
+
+ /* Payload size can't be greater than the destination buffer size */
+ if (payload_size > max_size) {
+ dev_dbg(dev, "Payload size is too large: %zu\n", payload_size);
+ return -EINVAL;
+ }
+
+ /* Payload size can't be smaller than the header size */
+ if (payload_size < header_size) {
+ dev_dbg(dev, "Payload size is too small: %zu\n", payload_size);
+ return -EINVAL;
+ }
+
+ /* Validate the size reported in the parameter buffer header */
+ buffer_size = header_size + buffer->data_size;
+ if (buffer_size != payload_size) {
+ dev_dbg(dev, "Data size %zu and payload size %zu are different\n",
+ buffer_size, payload_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_params_buffer_validate);
+
+int v4l2_params_blocks_validate(struct device *dev,
+ const struct v4l2_params_buffer *buffer,
+ const struct v4l2_params_handler *handlers,
+ size_t num_handlers)
+{
+ size_t block_offset = 0;
+ size_t buffer_size;
+
+ /* Walk the list of parameter blocks and validate them. */
+ buffer_size = buffer->data_size;
+ while (buffer_size >= sizeof(struct v4l2_params_block_header)) {
+ const struct v4l2_params_handler *handler;
+ const struct v4l2_params_block_header *block;
+
+ /* Validate block sizes and types against the handlers. */
+ block = (const struct v4l2_params_block_header *)
+ (buffer->data + block_offset);
+
+ if (block->type >= num_handlers) {
+ dev_dbg(dev, "Invalid parameters block type\n");
+ return -EINVAL;
+ }
+
+ if (block->size > buffer_size) {
+ dev_dbg(dev, "Premature end of parameters data\n");
+ return -EINVAL;
+ }
+
+ /* It's invalid to specify both ENABLE and DISABLE. */
+ if ((block->flags & (V4L2_PARAMS_FL_BLOCK_ENABLE |
+ V4L2_PARAMS_FL_BLOCK_DISABLE)) ==
+ (V4L2_PARAMS_FL_BLOCK_ENABLE |
+ V4L2_PARAMS_FL_BLOCK_DISABLE)) {
+ dev_dbg(dev, "Invalid parameters block flags\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Match the block reported size against the handler's expected
+ * one, but allow the block to only contain the header in
+ * case it is going to be disabled.
+ */
+ handler = &handlers[block->type];
+ if (block->size != handler->size &&
+ (!(block->flags & V4L2_PARAMS_FL_BLOCK_DISABLE) ||
+ block->size != sizeof(*block))) {
+ dev_dbg(dev, "Invalid parameters block size\n");
+ return -EINVAL;
+ }
+
+ block_offset += block->size;
+ buffer_size -= block->size;
+ }
+
+ if (buffer_size) {
+ dev_dbg(dev, "Unexpected data after the parameters buffer end\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_params_blocks_validate);
diff --git a/include/media/v4l2-isp.h b/include/media/v4l2-isp.h
new file mode 100644
index 0000000000000000000000000000000000000000..2ad62c6169eef3d0fb8d245de56cc6bd7e6227e4
--- /dev/null
+++ b/include/media/v4l2-isp.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Video4Linux2 generic ISP parameters and statistics support
+ *
+ * Copyright (C) 2025 Ideas On Board Oy
+ * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+ */
+
+#ifndef V4L2_PARAMS_H_
+#define V4L2_PARAMS_H_
+
+#include <linux/media/v4l2-isp.h>
+
+struct device;
+struct vb2_buffer;
+
+/**
+ * typedef v4l2_params_block_handler - V4L2 extensible format block handler
+ * @arg: pointer the driver-specific argument
+ * @block: the ISP configuration block to handle
+ *
+ * Defines the function signature of the functions that handle an ISP block
+ * configuration.
+ */
+typedef void (*v4l2_params_block_handler)(void *arg,
+ const struct v4l2_params_block_header *block);
+
+/**
+ * struct v4l2_params_handler - V4L2 extensible format handler
+ * @size: the block expected size
+ * @handler: the block handler function
+ *
+ * The v4l2_params_handler defines the type that driver making use of the
+ * V4L2 extensible parameters shall use to define their own ISP block
+ * handlers.
+ *
+ * Drivers shall prepare a list of handlers, one for each supported ISP block
+ * and correctly populate the structure's field with the expected block @size
+ * (used for validation) and a pointer to each block @handler function.
+ */
+struct v4l2_params_handler {
+ size_t size;
+ v4l2_params_block_handler handler;
+};
+
+/**
+ * v4l2_params_buffer_validate - Validate a V4L2 extensible parameters buffer
+ * @dev: the driver's device pointer
+ * @vb: the videobuf2 buffer
+ * @max_size: the maximum allowed buffer size
+ * @buffer_validate: callback to the driver-specific buffer validation
+ *
+ * Helper function that performs validation of an extensible parameters buffer.
+ *
+ * The helper is meant to be used by drivers to perform validation of the
+ * extensible parameters buffer size correctness.
+ *
+ * The @vb buffer as received from the vb2 .buf_prepare() operation is checked
+ * against @max_size and its validated to be large enough to accommodate at
+ * least one ISP configuration block. The effective buffer size is compared
+ * with the reported data size to make sure they match.
+ *
+ * Drivers should use this function to validate the buffer size correctness
+ * before performing a copy of the user-provided videobuf2 buffer content into a
+ * kernel-only memory buffer to prevent userspace from modifying the buffer
+ * content after it has been submitted to the driver.
+ */
+int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
+ size_t max_size);
+
+/**
+ * v4l2_params_blocks_validate - Validate V4L2 extensible parameters ISP
+ * configuration blocks
+ * @dev: the driver's device pointer
+ * @buffer: the extensible parameters configuration buffer
+ * @handlers: the list of block handlers
+ * @num_handlers: the number of block handlers
+ *
+ * Helper function that performs validation of the ISP configuration blocks in
+ * an extensible parameters buffer.
+ *
+ * The helper is meant to be used by drivers to perform validation of the
+ * ISP configuration data blocks. For each block in the extensible parameters
+ * buffer, its size and correctness are validated against its associated handler
+ * in the @handlers list.
+ *
+ * Drivers should use this function to validate the ISP configuration blocks
+ * after having validated the correctness of the vb2 buffer sizes by using the
+ * v4l2_params_buffer_validate() helper first. Once the buffer size has been
+ * validated, drivers should perform a copy of the user-provided buffer into a
+ * kernel-only memory buffer to prevent userspace from modifying the buffer
+ * content after it has been submitted to the driver, and then call this
+ * function to perform per-block validation.
+ */
+int v4l2_params_blocks_validate(struct device *dev,
+ const struct v4l2_params_buffer *buffer,
+ const struct v4l2_params_handler *handlers,
+ size_t num_handlers);
+
+#endif /* V4L2_PARAMS_H_ */
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v5 6/8] media: rkisp1: Use v4l2-isp for validation
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
` (4 preceding siblings ...)
2025-09-15 17:18 ` [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c Jacopo Mondi
@ 2025-09-15 17:18 ` Jacopo Mondi
2025-10-06 1:06 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 7/8] media: amlogic-c3: " Jacopo Mondi
` (2 subsequent siblings)
8 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
Convert rkisp1-params.c to use the new types for block handlers
defined in v4l2-isp.h and use the new helpers from v4l2-isp.c
to remove bolierplate code from the driver.
Break out from the handlers enumeration the 'group' and 'feature' flags
to a separate array and perform driver specific validation of these
fields separately.
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
drivers/media/platform/rockchip/rkisp1/Kconfig | 1 +
.../media/platform/rockchip/rkisp1/rkisp1-params.c | 441 ++++++++++-----------
2 files changed, 209 insertions(+), 233 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/Kconfig b/drivers/media/platform/rockchip/rkisp1/Kconfig
index 731c9acbf6efa33188617204d441fb0ea59adebc..f53eb1f3f3e7003d8e02c9236aeabb5ae8844f7b 100644
--- a/drivers/media/platform/rockchip/rkisp1/Kconfig
+++ b/drivers/media/platform/rockchip/rkisp1/Kconfig
@@ -10,6 +10,7 @@ config VIDEO_ROCKCHIP_ISP1
select VIDEOBUF2_VMALLOC
select V4L2_FWNODE
select GENERIC_PHY_MIPI_DPHY
+ select V4L2_ISP
default n
help
Enable this to support the Image Signal Processing (ISP) module
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index f1585f8fa0f478304f74317fd9dd09199c94ec82..de4e459fb556afb08891558dbf9d55b1973af8da 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -12,6 +12,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-isp.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-vmalloc.h> /* for ISP params */
@@ -40,30 +41,6 @@
#define RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS BIT(0)
#define RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC BIT(1)
-union rkisp1_ext_params_config {
- struct rkisp1_ext_params_block_header header;
- struct rkisp1_ext_params_bls_config bls;
- struct rkisp1_ext_params_dpcc_config dpcc;
- struct rkisp1_ext_params_sdg_config sdg;
- struct rkisp1_ext_params_lsc_config lsc;
- struct rkisp1_ext_params_awb_gain_config awbg;
- struct rkisp1_ext_params_flt_config flt;
- struct rkisp1_ext_params_bdm_config bdm;
- struct rkisp1_ext_params_ctk_config ctk;
- struct rkisp1_ext_params_goc_config goc;
- struct rkisp1_ext_params_dpf_config dpf;
- struct rkisp1_ext_params_dpf_strength_config dpfs;
- struct rkisp1_ext_params_cproc_config cproc;
- struct rkisp1_ext_params_ie_config ie;
- struct rkisp1_ext_params_awb_meas_config awbm;
- struct rkisp1_ext_params_hst_config hst;
- struct rkisp1_ext_params_aec_config aec;
- struct rkisp1_ext_params_afc_config afc;
- struct rkisp1_ext_params_compand_bls_config compand_bls;
- struct rkisp1_ext_params_compand_curve_config compand_curve;
- struct rkisp1_ext_params_wdr_config wdr;
-};
-
enum rkisp1_params_formats {
RKISP1_PARAMS_FIXED,
RKISP1_PARAMS_EXTENSIBLE,
@@ -1689,11 +1666,12 @@ static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params,
* Extensible parameters format handling
*/
-static void
-rkisp1_ext_params_bls(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_bls(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_bls_config *bls = &block->bls;
+ const struct rkisp1_ext_params_bls_config *bls =
+ (const struct rkisp1_ext_params_bls_config *)block;
+ struct rkisp1_params *params = dev;
if (bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
@@ -1709,11 +1687,12 @@ rkisp1_ext_params_bls(struct rkisp1_params *params,
RKISP1_CIF_ISP_BLS_ENA);
}
-static void
-rkisp1_ext_params_dpcc(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_dpcc(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
+ const struct rkisp1_ext_params_dpcc_config *dpcc =
+ (const struct rkisp1_ext_params_dpcc_config *)block;
+ struct rkisp1_params *params = dev;
if (dpcc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
@@ -1729,11 +1708,12 @@ rkisp1_ext_params_dpcc(struct rkisp1_params *params,
RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
}
-static void
-rkisp1_ext_params_sdg(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_sdg(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
+ const struct rkisp1_ext_params_sdg_config *sdg =
+ (const struct rkisp1_ext_params_sdg_config *)block;
+ struct rkisp1_params *params = dev;
if (sdg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1749,11 +1729,12 @@ rkisp1_ext_params_sdg(struct rkisp1_params *params,
RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
}
-static void
-rkisp1_ext_params_lsc(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_lsc(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
+ const struct rkisp1_ext_params_lsc_config *lsc =
+ (const struct rkisp1_ext_params_lsc_config *)block;
+ struct rkisp1_params *params = dev;
if (lsc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
@@ -1769,11 +1750,12 @@ rkisp1_ext_params_lsc(struct rkisp1_params *params,
RKISP1_CIF_ISP_LSC_CTRL_ENA);
}
-static void
-rkisp1_ext_params_awbg(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_awbg(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
+ const struct rkisp1_ext_params_awb_gain_config *awbg =
+ (const struct rkisp1_ext_params_awb_gain_config *)block;
+ struct rkisp1_params *params = dev;
if (awbg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1789,11 +1771,12 @@ rkisp1_ext_params_awbg(struct rkisp1_params *params,
RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
}
-static void
-rkisp1_ext_params_flt(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_flt(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_flt_config *flt = &block->flt;
+ const struct rkisp1_ext_params_flt_config *flt =
+ (const struct rkisp1_ext_params_flt_config *)block;
+ struct rkisp1_params *params = dev;
if (flt->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
@@ -1809,11 +1792,12 @@ rkisp1_ext_params_flt(struct rkisp1_params *params,
RKISP1_CIF_ISP_FLT_ENA);
}
-static void
-rkisp1_ext_params_bdm(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_bdm(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
+ const struct rkisp1_ext_params_bdm_config *bdm =
+ (const struct rkisp1_ext_params_bdm_config *)block;
+ struct rkisp1_params *params = dev;
if (bdm->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
@@ -1829,11 +1813,12 @@ rkisp1_ext_params_bdm(struct rkisp1_params *params,
RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
}
-static void
-rkisp1_ext_params_ctk(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_ctk(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
+ const struct rkisp1_ext_params_ctk_config *ctk =
+ (const struct rkisp1_ext_params_ctk_config *)block;
+ struct rkisp1_params *params = dev;
if (ctk->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_ctk_enable(params, false);
@@ -1847,11 +1832,12 @@ rkisp1_ext_params_ctk(struct rkisp1_params *params,
rkisp1_ctk_enable(params, true);
}
-static void
-rkisp1_ext_params_goc(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_goc(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_goc_config *goc = &block->goc;
+ const struct rkisp1_ext_params_goc_config *goc =
+ (const struct rkisp1_ext_params_goc_config *)block;
+ struct rkisp1_params *params = dev;
if (goc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1869,11 +1855,12 @@ rkisp1_ext_params_goc(struct rkisp1_params *params,
RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
}
-static void
-rkisp1_ext_params_dpf(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_dpf(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
+ const struct rkisp1_ext_params_dpf_config *dpf =
+ (const struct rkisp1_ext_params_dpf_config *)block;
+ struct rkisp1_params *params = dev;
if (dpf->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
@@ -1889,20 +1876,22 @@ rkisp1_ext_params_dpf(struct rkisp1_params *params,
RKISP1_CIF_ISP_DPF_MODE_EN);
}
-static void
-rkisp1_ext_params_dpfs(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_dpfs(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
+ const struct rkisp1_ext_params_dpf_strength_config *dpfs =
+ (const struct rkisp1_ext_params_dpf_strength_config *)block;
+ struct rkisp1_params *params = dev;
rkisp1_dpf_strength_config(params, &dpfs->config);
}
-static void
-rkisp1_ext_params_cproc(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_cproc(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
+ const struct rkisp1_ext_params_cproc_config *cproc =
+ (const struct rkisp1_ext_params_cproc_config *)block;
+ struct rkisp1_params *params = dev;
if (cproc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
@@ -1918,11 +1907,12 @@ rkisp1_ext_params_cproc(struct rkisp1_params *params,
RKISP1_CIF_C_PROC_CTR_ENABLE);
}
-static void
-rkisp1_ext_params_ie(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_ie(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_ie_config *ie = &block->ie;
+ const struct rkisp1_ext_params_ie_config *ie =
+ (const struct rkisp1_ext_params_ie_config *)block;
+ struct rkisp1_params *params = dev;
if (ie->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_ie_enable(params, false);
@@ -1936,11 +1926,12 @@ rkisp1_ext_params_ie(struct rkisp1_params *params,
rkisp1_ie_enable(params, true);
}
-static void
-rkisp1_ext_params_awbm(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_awbm(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
+ const struct rkisp1_ext_params_awb_meas_config *awbm =
+ (const struct rkisp1_ext_params_awb_meas_config *)block;
+ struct rkisp1_params *params = dev;
if (awbm->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
params->ops->awb_meas_enable(params, &awbm->config,
@@ -1956,11 +1947,12 @@ rkisp1_ext_params_awbm(struct rkisp1_params *params,
true);
}
-static void
-rkisp1_ext_params_hstm(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_hstm(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_hst_config *hst = &block->hst;
+ const struct rkisp1_ext_params_hst_config *hst =
+ (const struct rkisp1_ext_params_hst_config *)block;
+ struct rkisp1_params *params = dev;
if (hst->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
params->ops->hst_enable(params, &hst->config, false);
@@ -1974,11 +1966,12 @@ rkisp1_ext_params_hstm(struct rkisp1_params *params,
params->ops->hst_enable(params, &hst->config, true);
}
-static void
-rkisp1_ext_params_aecm(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_aecm(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_aec_config *aec = &block->aec;
+ const struct rkisp1_ext_params_aec_config *aec =
+ (const struct rkisp1_ext_params_aec_config *)block;
+ struct rkisp1_params *params = dev;
if (aec->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
@@ -1994,11 +1987,12 @@ rkisp1_ext_params_aecm(struct rkisp1_params *params,
RKISP1_CIF_ISP_EXP_ENA);
}
-static void
-rkisp1_ext_params_afcm(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_afcm(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_afc_config *afc = &block->afc;
+ const struct rkisp1_ext_params_afc_config *afc =
+ (const struct rkisp1_ext_params_afc_config *)block;
+ struct rkisp1_params *params = dev;
if (afc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
@@ -2014,11 +2008,12 @@ rkisp1_ext_params_afcm(struct rkisp1_params *params,
RKISP1_CIF_ISP_AFM_ENA);
}
-static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_compand_bls(void *dev,
+ const struct v4l2_params_block_header *block)
{
const struct rkisp1_ext_params_compand_bls_config *bls =
- &block->compand_bls;
+ (const struct rkisp1_ext_params_compand_bls_config *)block;
+ struct rkisp1_params *params = dev;
if (bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
@@ -2034,11 +2029,13 @@ static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
}
-static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void
+rkisp1_ext_params_compand_expand(void *dev,
+ const struct v4l2_params_block_header *block)
{
const struct rkisp1_ext_params_compand_curve_config *curve =
- &block->compand_curve;
+ (const struct rkisp1_ext_params_compand_curve_config *)block;
+ struct rkisp1_params *params = dev;
if (curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
@@ -2054,11 +2051,13 @@ static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
}
-static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void
+rkisp1_ext_params_compand_compress(void *dev,
+ const struct v4l2_params_block_header *block)
{
const struct rkisp1_ext_params_compand_curve_config *curve =
- &block->compand_curve;
+ (const struct rkisp1_ext_params_compand_curve_config *)block;
+ struct rkisp1_params *params = dev;
if (curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
@@ -2074,10 +2073,12 @@ static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
}
-static void rkisp1_ext_params_wdr(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *block)
+static void rkisp1_ext_params_wdr(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct rkisp1_ext_params_wdr_config *wdr = &block->wdr;
+ const struct rkisp1_ext_params_wdr_config *wdr =
+ (const struct rkisp1_ext_params_wdr_config *)block;
+ struct rkisp1_params *params = dev;
if (wdr->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_WDR_CTRL,
@@ -2093,123 +2094,163 @@ static void rkisp1_ext_params_wdr(struct rkisp1_params *params,
RKISP1_CIF_ISP_WDR_CTRL_ENABLE);
}
-typedef void (*rkisp1_block_handler)(struct rkisp1_params *params,
- const union rkisp1_ext_params_config *config);
-
-static const struct rkisp1_ext_params_handler {
- size_t size;
- rkisp1_block_handler handler;
+static const struct rkisp1_params_block_feature {
unsigned int group;
unsigned int features;
-} rkisp1_ext_params_handlers[] = {
+} rkisp1_ext_params_features[] = {
[RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS] = {
- .size = sizeof(struct rkisp1_ext_params_bls_config),
- .handler = rkisp1_ext_params_bls,
.group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
.features = RKISP1_FEATURE_BLS,
},
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_IE] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ .features = RKISP1_FEATURE_COMPAND,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ .features = RKISP1_FEATURE_COMPAND,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ .features = RKISP1_FEATURE_COMPAND,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR] = {
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ },
+};
+
+static const struct v4l2_params_handler rkisp1_ext_params_handlers[] = {
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS] = {
+ .size = sizeof(struct rkisp1_ext_params_bls_config),
+ .handler = rkisp1_ext_params_bls,
+ },
[RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC] = {
.size = sizeof(struct rkisp1_ext_params_dpcc_config),
.handler = rkisp1_ext_params_dpcc,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG] = {
.size = sizeof(struct rkisp1_ext_params_sdg_config),
.handler = rkisp1_ext_params_sdg,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN] = {
.size = sizeof(struct rkisp1_ext_params_awb_gain_config),
.handler = rkisp1_ext_params_awbg,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT] = {
.size = sizeof(struct rkisp1_ext_params_flt_config),
.handler = rkisp1_ext_params_flt,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM] = {
.size = sizeof(struct rkisp1_ext_params_bdm_config),
.handler = rkisp1_ext_params_bdm,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK] = {
.size = sizeof(struct rkisp1_ext_params_ctk_config),
.handler = rkisp1_ext_params_ctk,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC] = {
.size = sizeof(struct rkisp1_ext_params_goc_config),
.handler = rkisp1_ext_params_goc,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF] = {
.size = sizeof(struct rkisp1_ext_params_dpf_config),
.handler = rkisp1_ext_params_dpf,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH] = {
.size = sizeof(struct rkisp1_ext_params_dpf_strength_config),
.handler = rkisp1_ext_params_dpfs,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC] = {
.size = sizeof(struct rkisp1_ext_params_cproc_config),
.handler = rkisp1_ext_params_cproc,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_IE] = {
.size = sizeof(struct rkisp1_ext_params_ie_config),
.handler = rkisp1_ext_params_ie,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC] = {
.size = sizeof(struct rkisp1_ext_params_lsc_config),
.handler = rkisp1_ext_params_lsc,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS] = {
.size = sizeof(struct rkisp1_ext_params_awb_meas_config),
.handler = rkisp1_ext_params_awbm,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS] = {
.size = sizeof(struct rkisp1_ext_params_hst_config),
.handler = rkisp1_ext_params_hstm,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS] = {
.size = sizeof(struct rkisp1_ext_params_aec_config),
.handler = rkisp1_ext_params_aecm,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS] = {
.size = sizeof(struct rkisp1_ext_params_afc_config),
.handler = rkisp1_ext_params_afcm,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
.size = sizeof(struct rkisp1_ext_params_compand_bls_config),
.handler = rkisp1_ext_params_compand_bls,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
- .features = RKISP1_FEATURE_COMPAND,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
.size = sizeof(struct rkisp1_ext_params_compand_curve_config),
.handler = rkisp1_ext_params_compand_expand,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
- .features = RKISP1_FEATURE_COMPAND,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
.size = sizeof(struct rkisp1_ext_params_compand_curve_config),
.handler = rkisp1_ext_params_compand_compress,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
- .features = RKISP1_FEATURE_COMPAND,
},
[RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR] = {
.size = sizeof(struct rkisp1_ext_params_wdr_config),
.handler = rkisp1_ext_params_wdr,
- .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
};
@@ -2224,31 +2265,33 @@ static void rkisp1_ext_params_config(struct rkisp1_params *params,
/* Walk the list of parameter blocks and process them. */
while (block_offset < cfg->data_size) {
- const struct rkisp1_ext_params_handler *block_handler;
- const union rkisp1_ext_params_config *block;
+ const struct rkisp1_params_block_feature *block_features;
+ const struct v4l2_params_handler *block_handler;
+ const struct v4l2_params_block_header *block;
- block = (const union rkisp1_ext_params_config *)
+ block = (const struct v4l2_params_block_header *)
&cfg->data[block_offset];
- block_offset += block->header.size;
+ block_offset += block->size;
/*
* Make sure the block is supported by the platform and in the
* list of groups to configure.
*/
- block_handler = &rkisp1_ext_params_handlers[block->header.type];
- if (!(block_handler->group & block_group_mask))
+ block_features = &rkisp1_ext_params_features[block->type];
+ if (!(block_features->group & block_group_mask))
continue;
- if ((params->rkisp1->info->features & block_handler->features) !=
- block_handler->features)
+ if ((params->rkisp1->info->features & block_features->features)
+ != block_features->features)
continue;
+ block_handler = &rkisp1_ext_params_handlers[block->type];
block_handler->handler(params, block);
- if (block->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)
- params->enabled_blocks &= ~BIT(block->header.type);
- else if (block->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE)
- params->enabled_blocks |= BIT(block->header.type);
+ if (block->flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)
+ params->enabled_blocks &= ~BIT(block->type);
+ else if (block->flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE)
+ params->enabled_blocks |= BIT(block->type);
}
}
@@ -2646,31 +2689,24 @@ static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
- size_t header_size = offsetof(struct rkisp1_ext_params_cfg, data);
struct rkisp1_ext_params_cfg *cfg = params_buf->cfg;
size_t payload_size = vb2_get_plane_payload(vb, 0);
struct rkisp1_ext_params_cfg *usr_cfg =
vb2_plane_vaddr(&vbuf->vb2_buf, 0);
- size_t block_offset = 0;
- size_t cfg_size;
+ int ret;
- /*
- * Validate the buffer payload size before copying the parameters. The
- * payload has to be smaller than the destination buffer size and larger
- * than the header size.
- */
- if (payload_size > params->metafmt->buffersize) {
+ /* Only v1 is supported at the moment. */
+ if (usr_cfg->version != RKISP1_EXT_PARAM_BUFFER_V1) {
dev_dbg(params->rkisp1->dev,
- "Too large buffer payload size %zu\n", payload_size);
+ "Unsupported extensible parameters version: %u\n",
+ usr_cfg->version);
return -EINVAL;
}
- if (payload_size < header_size) {
- dev_dbg(params->rkisp1->dev,
- "Buffer payload %zu smaller than header size %zu\n",
- payload_size, header_size);
- return -EINVAL;
- }
+ ret = v4l2_params_buffer_validate(params->rkisp1->dev, vb,
+ params->metafmt->buffersize);
+ if (ret)
+ return ret;
/*
* Copy the parameters buffer to the internal scratch buffer to avoid
@@ -2678,71 +2714,10 @@ static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
*/
memcpy(cfg, usr_cfg, payload_size);
- /* Only v1 is supported at the moment. */
- if (cfg->version != RKISP1_EXT_PARAM_BUFFER_V1) {
- dev_dbg(params->rkisp1->dev,
- "Unsupported extensible format version: %u\n",
- cfg->version);
- return -EINVAL;
- }
-
- /* Validate the size reported in the parameters buffer header. */
- cfg_size = header_size + cfg->data_size;
- if (cfg_size != payload_size) {
- dev_dbg(params->rkisp1->dev,
- "Data size %zu different than buffer payload size %zu\n",
- cfg_size, payload_size);
- return -EINVAL;
- }
-
- /* Walk the list of parameter blocks and validate them. */
- cfg_size = cfg->data_size;
- while (cfg_size >= sizeof(struct rkisp1_ext_params_block_header)) {
- const struct rkisp1_ext_params_block_header *block;
- const struct rkisp1_ext_params_handler *handler;
-
- block = (const struct rkisp1_ext_params_block_header *)
- &cfg->data[block_offset];
-
- if (block->type >= ARRAY_SIZE(rkisp1_ext_params_handlers)) {
- dev_dbg(params->rkisp1->dev,
- "Invalid parameters block type\n");
- return -EINVAL;
- }
-
- if (block->size > cfg_size) {
- dev_dbg(params->rkisp1->dev,
- "Premature end of parameters data\n");
- return -EINVAL;
- }
-
- if ((block->flags & (RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE |
- RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)) ==
- (RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE |
- RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)) {
- dev_dbg(params->rkisp1->dev,
- "Invalid parameters block flags\n");
- return -EINVAL;
- }
-
- handler = &rkisp1_ext_params_handlers[block->type];
- if (block->size != handler->size) {
- dev_dbg(params->rkisp1->dev,
- "Invalid parameters block size\n");
- return -EINVAL;
- }
-
- block_offset += block->size;
- cfg_size -= block->size;
- }
-
- if (cfg_size) {
- dev_dbg(params->rkisp1->dev,
- "Unexpected data after the parameters buffer end\n");
- return -EINVAL;
- }
-
- return 0;
+ return v4l2_params_blocks_validate(params->rkisp1->dev,
+ (struct v4l2_params_buffer *)cfg,
+ rkisp1_ext_params_handlers,
+ ARRAY_SIZE(rkisp1_ext_params_handlers));
}
static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
@@ -2842,13 +2817,13 @@ static int rkisp1_params_ctrl_init(struct rkisp1_params *params)
v4l2_ctrl_handler_init(¶ms->ctrls, 1);
for (unsigned int i = 0; i < ARRAY_SIZE(rkisp1_ext_params_handlers); i++) {
- const struct rkisp1_ext_params_handler *block_handler;
+ const struct rkisp1_params_block_feature *block_features;
- block_handler = &rkisp1_ext_params_handlers[i];
+ block_features = &rkisp1_ext_params_features[i];
ctrl_config.max |= BIT(i);
- if ((params->rkisp1->info->features & block_handler->features) !=
- block_handler->features)
+ if ((params->rkisp1->info->features & block_features->features)
+ != block_features->features)
continue;
ctrl_config.def |= BIT(i);
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v5 7/8] media: amlogic-c3: Use v4l2-isp for validation
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
` (5 preceding siblings ...)
2025-09-15 17:18 ` [PATCH v5 6/8] media: rkisp1: Use v4l2-isp for validation Jacopo Mondi
@ 2025-09-15 17:18 ` Jacopo Mondi
2025-09-15 17:18 ` [PATCH v5 8/8] media: Documentation: kapi: Add v4l2 generic ISP support Jacopo Mondi
2025-10-02 8:17 ` [PATCH v5 0/8] media: Introduce V4L2 " Sakari Ailus
8 siblings, 0 replies; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
Convert c3-ispa-params.c to use the new types fro block handlers
defined in v4l2-isp.h and use the new helpers from v4l2-isp.c
to remove boilerplate code from the driver.
Reviewed-by: Keke Li <keke.li@amlogic.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
drivers/media/platform/amlogic/c3/isp/Kconfig | 1 +
.../media/platform/amlogic/c3/isp/c3-isp-params.c | 248 +++++++--------------
2 files changed, 83 insertions(+), 166 deletions(-)
diff --git a/drivers/media/platform/amlogic/c3/isp/Kconfig b/drivers/media/platform/amlogic/c3/isp/Kconfig
index 02c62a50a5e88eac665e27abf163e5d654faed3f..809208cd7e3aa7ca0821cb07366ec73a47edb278 100644
--- a/drivers/media/platform/amlogic/c3/isp/Kconfig
+++ b/drivers/media/platform/amlogic/c3/isp/Kconfig
@@ -10,6 +10,7 @@ config VIDEO_C3_ISP
select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
+ select V4L2_ISP
help
Video4Linux2 driver for Amlogic C3 ISP pipeline.
The C3 ISP is used for processing raw images and
diff --git a/drivers/media/platform/amlogic/c3/isp/c3-isp-params.c b/drivers/media/platform/amlogic/c3/isp/c3-isp-params.c
index c80667dd766210d2b2e1ee60c8254a5814b9d81b..0e9d19c84bd429a142aa18fcb490925059d5d77c 100644
--- a/drivers/media/platform/amlogic/c3/isp/c3-isp-params.c
+++ b/drivers/media/platform/amlogic/c3/isp/c3-isp-params.c
@@ -8,65 +8,27 @@
#include <linux/pm_runtime.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-isp.h>
#include <media/v4l2-mc.h>
#include <media/videobuf2-vmalloc.h>
#include "c3-isp-common.h"
#include "c3-isp-regs.h"
-/*
- * union c3_isp_params_block - Generalisation of a parameter block
- *
- * This union allows the driver to treat a block as a generic struct to this
- * union and safely access the header and block-specific struct without having
- * to resort to casting. The header member is accessed first, and the type field
- * checked which allows the driver to determine which of the other members
- * should be used.
- *
- * @header: The shared header struct embedded as the first member
- * of all the possible other members. This member would be
- * accessed first and the type field checked to determine
- * which of the other members should be accessed.
- * @awb_gains: For header.type == C3_ISP_PARAMS_BLOCK_AWB_GAINS
- * @awb_cfg: For header.type == C3_ISP_PARAMS_BLOCK_AWB_CONFIG
- * @ae_cfg: For header.type == C3_ISP_PARAMS_BLOCK_AE_CONFIG
- * @af_cfg: For header.type == C3_ISP_PARAMS_BLOCK_AF_CONFIG
- * @pst_gamma: For header.type == C3_ISP_PARAMS_BLOCK_PST_GAMMA
- * @ccm: For header.type == C3_ISP_PARAMS_BLOCK_CCM
- * @csc: For header.type == C3_ISP_PARAMS_BLOCK_CSC
- * @blc: For header.type == C3_ISP_PARAMS_BLOCK_BLC
- */
-union c3_isp_params_block {
- struct c3_isp_params_block_header header;
- struct c3_isp_params_awb_gains awb_gains;
- struct c3_isp_params_awb_config awb_cfg;
- struct c3_isp_params_ae_config ae_cfg;
- struct c3_isp_params_af_config af_cfg;
- struct c3_isp_params_pst_gamma pst_gamma;
- struct c3_isp_params_ccm ccm;
- struct c3_isp_params_csc csc;
- struct c3_isp_params_blc blc;
-};
-
-typedef void (*c3_isp_block_handler)(struct c3_isp_device *isp,
- const union c3_isp_params_block *block);
-
-struct c3_isp_params_handler {
- size_t size;
- c3_isp_block_handler handler;
-};
-
#define to_c3_isp_params_buffer(vbuf) \
container_of(vbuf, struct c3_isp_params_buffer, vb)
/* Hardware configuration */
-static void c3_isp_params_cfg_awb_gains(struct c3_isp_device *isp,
- const union c3_isp_params_block *block)
+static void
+c3_isp_params_cfg_awb_gains(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct c3_isp_params_awb_gains *awb_gains = &block->awb_gains;
+ const struct c3_isp_params_awb_gains *awb_gains =
+ (const struct c3_isp_params_awb_gains *)block;
+ struct c3_isp_device *isp = dev;
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
c3_isp_update_bits(isp, ISP_TOP_BEO_CTRL,
ISP_TOP_BEO_CTRL_WB_EN_MASK,
ISP_TOP_BEO_CTRL_WB_DIS);
@@ -89,7 +51,7 @@ static void c3_isp_params_cfg_awb_gains(struct c3_isp_device *isp,
ISP_LSWB_WB_GAIN2_IR_GAIN_MASK,
ISP_LSWB_WB_GAIN2_IR_GAIN(awb_gains->gb_gain));
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
c3_isp_update_bits(isp, ISP_TOP_BEO_CTRL,
ISP_TOP_BEO_CTRL_WB_EN_MASK,
ISP_TOP_BEO_CTRL_WB_EN);
@@ -151,12 +113,15 @@ static void c3_isp_params_awb_cood(struct c3_isp_device *isp,
ISP_AWB_IDX_DATA_VIDX_DATA(cfg->vert_coord[i]));
}
-static void c3_isp_params_cfg_awb_config(struct c3_isp_device *isp,
- const union c3_isp_params_block *block)
+static void
+c3_isp_params_cfg_awb_config(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct c3_isp_params_awb_config *awb_cfg = &block->awb_cfg;
+ const struct c3_isp_params_awb_config *awb_cfg =
+ (const struct c3_isp_params_awb_config *)block;
+ struct c3_isp_device *isp = dev;
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
c3_isp_update_bits(isp, ISP_TOP_3A_STAT_CRTL,
ISP_TOP_3A_STAT_CRTL_AWB_STAT_EN_MASK,
ISP_TOP_3A_STAT_CRTL_AWB_STAT_DIS);
@@ -205,7 +170,7 @@ static void c3_isp_params_cfg_awb_config(struct c3_isp_device *isp,
c3_isp_params_awb_wt(isp, awb_cfg);
c3_isp_params_awb_cood(isp, awb_cfg);
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
c3_isp_update_bits(isp, ISP_TOP_3A_STAT_CRTL,
ISP_TOP_3A_STAT_CRTL_AWB_STAT_EN_MASK,
ISP_TOP_3A_STAT_CRTL_AWB_STAT_EN);
@@ -268,12 +233,15 @@ static void c3_isp_params_ae_cood(struct c3_isp_device *isp,
ISP_AE_IDX_DATA_VIDX_DATA(cfg->vert_coord[i]));
}
-static void c3_isp_params_cfg_ae_config(struct c3_isp_device *isp,
- const union c3_isp_params_block *block)
+static void
+c3_isp_params_cfg_ae_config(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct c3_isp_params_ae_config *ae_cfg = &block->ae_cfg;
+ const struct c3_isp_params_ae_config *ae_cfg =
+ (const struct c3_isp_params_ae_config *)block;
+ struct c3_isp_device *isp = dev;
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
c3_isp_update_bits(isp, ISP_TOP_3A_STAT_CRTL,
ISP_TOP_3A_STAT_CRTL_AE_STAT_EN_MASK,
ISP_TOP_3A_STAT_CRTL_AE_STAT_DIS);
@@ -303,7 +271,7 @@ static void c3_isp_params_cfg_ae_config(struct c3_isp_device *isp,
c3_isp_params_ae_wt(isp, ae_cfg);
c3_isp_params_ae_cood(isp, ae_cfg);
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
c3_isp_update_bits(isp, ISP_TOP_3A_STAT_CRTL,
ISP_TOP_3A_STAT_CRTL_AE_STAT_EN_MASK,
ISP_TOP_3A_STAT_CRTL_AE_STAT_EN);
@@ -326,12 +294,15 @@ static void c3_isp_params_af_cood(struct c3_isp_device *isp,
ISP_AF_IDX_DATA_VIDX_DATA(cfg->vert_coord[i]));
}
-static void c3_isp_params_cfg_af_config(struct c3_isp_device *isp,
- const union c3_isp_params_block *block)
+static void
+c3_isp_params_cfg_af_config(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct c3_isp_params_af_config *af_cfg = &block->af_cfg;
+ const struct c3_isp_params_af_config *af_cfg =
+ (const struct c3_isp_params_af_config *)block;
+ struct c3_isp_device *isp = dev;
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
c3_isp_update_bits(isp, ISP_TOP_3A_STAT_CRTL,
ISP_TOP_3A_STAT_CRTL_AF_STAT_EN_MASK,
ISP_TOP_3A_STAT_CRTL_AF_STAT_DIS);
@@ -351,20 +322,23 @@ static void c3_isp_params_cfg_af_config(struct c3_isp_device *isp,
c3_isp_params_af_cood(isp, af_cfg);
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
c3_isp_update_bits(isp, ISP_TOP_3A_STAT_CRTL,
ISP_TOP_3A_STAT_CRTL_AF_STAT_EN_MASK,
ISP_TOP_3A_STAT_CRTL_AF_STAT_EN);
}
-static void c3_isp_params_cfg_pst_gamma(struct c3_isp_device *isp,
- const union c3_isp_params_block *block)
+static void
+c3_isp_params_cfg_pst_gamma(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct c3_isp_params_pst_gamma *gm = &block->pst_gamma;
+ const struct c3_isp_params_pst_gamma *gm =
+ (const struct c3_isp_params_pst_gamma *)block;
+ struct c3_isp_device *isp = dev;
unsigned int base;
unsigned int i;
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
c3_isp_update_bits(isp, ISP_TOP_BED_CTRL,
ISP_TOP_BED_CTRL_PST_GAMMA_EN_MASK,
ISP_TOP_BED_CTRL_PST_GAMMA_DIS);
@@ -393,19 +367,21 @@ static void c3_isp_params_cfg_pst_gamma(struct c3_isp_device *isp,
}
}
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
c3_isp_update_bits(isp, ISP_TOP_BED_CTRL,
ISP_TOP_BED_CTRL_PST_GAMMA_EN_MASK,
ISP_TOP_BED_CTRL_PST_GAMMA_EN);
}
/* Configure 3 x 3 ccm matrix */
-static void c3_isp_params_cfg_ccm(struct c3_isp_device *isp,
- const union c3_isp_params_block *block)
+static void c3_isp_params_cfg_ccm(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct c3_isp_params_ccm *ccm = &block->ccm;
+ const struct c3_isp_params_ccm *ccm =
+ (const struct c3_isp_params_ccm *)block;
+ struct c3_isp_device *isp = dev;
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
c3_isp_update_bits(isp, ISP_TOP_BED_CTRL,
ISP_TOP_BED_CTRL_CCM_EN_MASK,
ISP_TOP_BED_CTRL_CCM_DIS);
@@ -442,19 +418,21 @@ static void c3_isp_params_cfg_ccm(struct c3_isp_device *isp,
ISP_CCM_MTX_22_23_RS_MTX_22_MASK,
ISP_CCM_MTX_22_23_RS_MTX_22(ccm->matrix[2][2]));
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
c3_isp_update_bits(isp, ISP_TOP_BED_CTRL,
ISP_TOP_BED_CTRL_CCM_EN_MASK,
ISP_TOP_BED_CTRL_CCM_EN);
}
/* Configure color space conversion matrix parameters */
-static void c3_isp_params_cfg_csc(struct c3_isp_device *isp,
- const union c3_isp_params_block *block)
+static void c3_isp_params_cfg_csc(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct c3_isp_params_csc *csc = &block->csc;
+ const struct c3_isp_params_csc *csc =
+ (const struct c3_isp_params_csc *)block;
+ struct c3_isp_device *isp = dev;
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
c3_isp_update_bits(isp, ISP_TOP_BED_CTRL,
ISP_TOP_BED_CTRL_CM0_EN_MASK,
ISP_TOP_BED_CTRL_CM0_DIS);
@@ -491,19 +469,21 @@ static void c3_isp_params_cfg_csc(struct c3_isp_device *isp,
ISP_CM0_COEF22_OUP_OFST0_MTX_22_MASK,
ISP_CM0_COEF22_OUP_OFST0_MTX_22(csc->matrix[2][2]));
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
c3_isp_update_bits(isp, ISP_TOP_BED_CTRL,
ISP_TOP_BED_CTRL_CM0_EN_MASK,
ISP_TOP_BED_CTRL_CM0_EN);
}
/* Set blc offset of each color channel */
-static void c3_isp_params_cfg_blc(struct c3_isp_device *isp,
- const union c3_isp_params_block *block)
+static void c3_isp_params_cfg_blc(void *dev,
+ const struct v4l2_params_block_header *block)
{
- const struct c3_isp_params_blc *blc = &block->blc;
+ const struct c3_isp_params_blc *blc =
+ (const struct c3_isp_params_blc *)block;
+ struct c3_isp_device *isp = dev;
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_DISABLE) {
c3_isp_update_bits(isp, ISP_TOP_BEO_CTRL,
ISP_TOP_BEO_CTRL_BLC_EN_MASK,
ISP_TOP_BEO_CTRL_BLC_DIS);
@@ -517,13 +497,13 @@ static void c3_isp_params_cfg_blc(struct c3_isp_device *isp,
ISP_LSWB_BLC_OFST1_GB_OFST(blc->gb_ofst) |
ISP_LSWB_BLC_OFST1_B_OFST(blc->b_ofst));
- if (block->header.flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
+ if (block->flags & C3_ISP_PARAMS_BLOCK_FL_ENABLE)
c3_isp_update_bits(isp, ISP_TOP_BEO_CTRL,
ISP_TOP_BEO_CTRL_BLC_EN_MASK,
ISP_TOP_BEO_CTRL_BLC_EN);
}
-static const struct c3_isp_params_handler c3_isp_params_handlers[] = {
+static const struct v4l2_params_handler c3_isp_params_handlers[] = {
[C3_ISP_PARAMS_BLOCK_AWB_GAINS] = {
.size = sizeof(struct c3_isp_params_awb_gains),
.handler = c3_isp_params_cfg_awb_gains,
@@ -568,16 +548,16 @@ static void c3_isp_params_cfg_blocks(struct c3_isp_params *params)
/* Walk the list of parameter blocks and process them */
while (block_offset < config->data_size) {
- const struct c3_isp_params_handler *block_handler;
- const union c3_isp_params_block *block;
+ const struct v4l2_params_handler *block_handler;
+ const struct v4l2_params_block_header *block;
- block = (const union c3_isp_params_block *)
+ block = (const struct v4l2_params_block_header *)
&config->data[block_offset];
- block_handler = &c3_isp_params_handlers[block->header.type];
+ block_handler = &c3_isp_params_handlers[block->type];
block_handler->handler(params->isp, block);
- block_offset += block->header.size;
+ block_offset += block->size;
}
}
@@ -771,26 +751,22 @@ static int c3_isp_params_vb2_buf_prepare(struct vb2_buffer *vb)
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct c3_isp_params_buffer *buf = to_c3_isp_params_buffer(vbuf);
struct c3_isp_params *params = vb2_get_drv_priv(vb->vb2_queue);
- struct c3_isp_params_cfg *cfg = buf->cfg;
struct c3_isp_params_cfg *usr_cfg = vb2_plane_vaddr(vb, 0);
size_t payload_size = vb2_get_plane_payload(vb, 0);
- size_t header_size = offsetof(struct c3_isp_params_cfg, data);
- size_t block_offset = 0;
- size_t cfg_size;
+ struct c3_isp_params_cfg *cfg = buf->cfg;
+ int ret;
- /* Payload size can't be greater than the destination buffer size */
- if (payload_size > params->vfmt.fmt.meta.buffersize) {
- dev_dbg(params->isp->dev,
- "Payload size is too large: %zu\n", payload_size);
+ /* Only v0 is supported at the moment */
+ if (usr_cfg->version != C3_ISP_PARAMS_BUFFER_V0) {
+ dev_dbg(params->isp->dev, "Invalid params buffer version: %u\n",
+ usr_cfg->version);
return -EINVAL;
}
- /* Payload size can't be smaller than the header size */
- if (payload_size < header_size) {
- dev_dbg(params->isp->dev,
- "Payload size is too small: %zu\n", payload_size);
- return -EINVAL;
- }
+ ret = v4l2_params_buffer_validate(params->isp->dev, vb,
+ params->vfmt.fmt.meta.buffersize);
+ if (ret)
+ return ret;
/*
* Use the internal scratch buffer to avoid userspace modifying
@@ -798,70 +774,10 @@ static int c3_isp_params_vb2_buf_prepare(struct vb2_buffer *vb)
*/
memcpy(cfg, usr_cfg, payload_size);
- /* Only v0 is supported at the moment */
- if (cfg->version != C3_ISP_PARAMS_BUFFER_V0) {
- dev_dbg(params->isp->dev,
- "Invalid params buffer version: %u\n", cfg->version);
- return -EINVAL;
- }
-
- /* Validate the size reported in the parameter buffer header */
- cfg_size = header_size + cfg->data_size;
- if (cfg_size != payload_size) {
- dev_dbg(params->isp->dev,
- "Data size %zu and payload size %zu are different\n",
- cfg_size, payload_size);
- return -EINVAL;
- }
-
- /* Walk the list of parameter blocks and validate them */
- cfg_size = cfg->data_size;
- while (cfg_size >= sizeof(struct c3_isp_params_block_header)) {
- const struct c3_isp_params_block_header *block;
- const struct c3_isp_params_handler *handler;
-
- block = (struct c3_isp_params_block_header *)
- &cfg->data[block_offset];
-
- if (block->type >= ARRAY_SIZE(c3_isp_params_handlers)) {
- dev_dbg(params->isp->dev,
- "Invalid params block type\n");
- return -EINVAL;
- }
-
- if (block->size > cfg_size) {
- dev_dbg(params->isp->dev,
- "Block size is greater than cfg size\n");
- return -EINVAL;
- }
-
- if ((block->flags & (C3_ISP_PARAMS_BLOCK_FL_ENABLE |
- C3_ISP_PARAMS_BLOCK_FL_DISABLE)) ==
- (C3_ISP_PARAMS_BLOCK_FL_ENABLE |
- C3_ISP_PARAMS_BLOCK_FL_DISABLE)) {
- dev_dbg(params->isp->dev,
- "Invalid parameters block flags\n");
- return -EINVAL;
- }
-
- handler = &c3_isp_params_handlers[block->type];
- if (block->size != handler->size) {
- dev_dbg(params->isp->dev,
- "Invalid params block size\n");
- return -EINVAL;
- }
-
- block_offset += block->size;
- cfg_size -= block->size;
- }
-
- if (cfg_size) {
- dev_dbg(params->isp->dev,
- "Unexpected data after the params buffer end\n");
- return -EINVAL;
- }
-
- return 0;
+ return v4l2_params_blocks_validate(params->isp->dev,
+ (struct v4l2_params_buffer *)cfg,
+ c3_isp_params_handlers,
+ ARRAY_SIZE(c3_isp_params_handlers));
}
static int c3_isp_params_vb2_buf_init(struct vb2_buffer *vb)
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v5 8/8] media: Documentation: kapi: Add v4l2 generic ISP support
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
` (6 preceding siblings ...)
2025-09-15 17:18 ` [PATCH v5 7/8] media: amlogic-c3: " Jacopo Mondi
@ 2025-09-15 17:18 ` Jacopo Mondi
2025-10-06 1:18 ` Laurent Pinchart
2025-10-02 8:17 ` [PATCH v5 0/8] media: Introduce V4L2 " Sakari Ailus
8 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-09-15 17:18 UTC (permalink / raw)
To: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Sakari Ailus,
Antoine Bouyer
Cc: linux-kernel, linux-media, linux-rockchip, linux-arm-kernel,
Jacopo Mondi
Add to the driver-api documentation the v4l2-isp.h types and
helpers documentation.
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
Documentation/driver-api/media/v4l2-core.rst | 1 +
Documentation/driver-api/media/v4l2-isp.rst | 37 ++++++++++++++++++++++++++++
MAINTAINERS | 1 +
3 files changed, 39 insertions(+)
diff --git a/Documentation/driver-api/media/v4l2-core.rst b/Documentation/driver-api/media/v4l2-core.rst
index ad987c34ad2a8460bb95e97adc4d850d624e0b81..a5f5102c64cca57b57b54ab95882b26286fb27de 100644
--- a/Documentation/driver-api/media/v4l2-core.rst
+++ b/Documentation/driver-api/media/v4l2-core.rst
@@ -27,3 +27,4 @@ Video4Linux devices
v4l2-common
v4l2-tveeprom
v4l2-jpeg
+ v4l2-isp
diff --git a/Documentation/driver-api/media/v4l2-isp.rst b/Documentation/driver-api/media/v4l2-isp.rst
new file mode 100644
index 0000000000000000000000000000000000000000..d778aa799347bfd0a95bd6887dd944ddad0fe4d1
--- /dev/null
+++ b/Documentation/driver-api/media/v4l2-isp.rst
@@ -0,0 +1,37 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+V4L2 generic ISP parameters and statistics support
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ISP configuration parameters and statistics are processed and collected by
+drivers and exchanged with userspace through data types that usually
+reflect the ISP peripheral registers layout.
+
+Each ISP driver defines its own metadata format for parameters and statistics,
+and exposing the registers layout in the format definition, part of the Linux
+kernel uAPI/uABI interface, makes it really hard, if not impossible, to extend
+the format in a backward compatible way to support new hardware blocks or
+different revisions of the same peripheral IP.
+
+For these reasons Video4Linux2 defines generic types for ISP configuration
+parameters and statistics with a set of associated helpers to support drivers
+and users using generic types.
+
+Generic ISP configuration parameters
+====================================
+
+Drivers can use the generic and extensible configuration parameters format by
+re-using the types defined in the include/uapi/linux/media/v4l2-isp.h uAPI
+header file.
+
+The uAPI header defines generic types which the driver is expected to re-use and
+provide definitions for the types of supported ISP blocks, their control
+flags and the expected maximum size of a buffer of parameters.
+
+When a driver receives a buffer of parameters from userspace it shall validate
+it by using the helper functions and types available in include/media/v4l2-isp.h
+before accessing the buffer to apply the parameters to the hardware registers.
+
+Generic ISP support driver documentation
+========================================
+.. kernel-doc:: include/media/v4l2-isp.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1..b0c5e6c2b21a5d5ebc63d2ae8b5c1b68fa912b33 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26414,6 +26414,7 @@ V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
+F: Documentation/driver-api/media/v4l2-isp.rst
F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
F: drivers/media/v4l2-core/v4l2-isp.c
F: include/media/v4l2-isp.h
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH v5 0/8] media: Introduce V4L2 generic ISP support
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
` (7 preceding siblings ...)
2025-09-15 17:18 ` [PATCH v5 8/8] media: Documentation: kapi: Add v4l2 generic ISP support Jacopo Mondi
@ 2025-10-02 8:17 ` Sakari Ailus
8 siblings, 0 replies; 32+ messages in thread
From: Sakari Ailus @ 2025-10-02 8:17 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Laurent Pinchart, Keke Li,
Mauro Carvalho Chehab, Heiko Stuebner, Dan Scally, Antoine Bouyer,
linux-kernel, linux-media, linux-rockchip, linux-arm-kernel
Hi Jacopo,
On Mon, Sep 15, 2025 at 07:18:09PM +0200, Jacopo Mondi wrote:
> Extensible parameters meta formats have been introduced in the Linux
> kernel v6.12 initially to support different revision of the RkISP1 ISP
> implemented in different SoC. In order to avoid breaking userspace
> everytime an ISP configuration block is added or modified in the uAPI
> these new formats, which are versionated and extensible by their
> definition have been introduced.
>
> See for reference:
> e9d05e9d5db1 ("media: uapi: rkisp1-config: Add extensible params format")
> 6c53a7b68c5d ("media: rkisp1: Implement extensible params support")
>
> The Amlogic C3 ISP driver followed shortly, introducing an extensible
> format for the ISP configuration:
>
> 6d406187ebc0 ("media: uapi: Add stats info and parameters buffer for C3 ISP")
>
> with a very similar, if not identical, implementation of the routines to
> validate and handle the ISP configuration in the ISP driver in the
> c3-isp-params.c file.
>
> fb2e135208f3 ("media: platform: Add C3 ISP driver")
>
> With the recent upstreaming attempt of the Mali C55 ISP driver from Dan,
> a third user of extensible parameters is going to be itroduced in the
> kernel, duplicating again in the driver the procedure for validating and
> handling the ISP configuration blocks
>
> https://patchwork.linuxtv.org/project/linux-media/patch/20250624-c55-v10-15-54f3d4196990@ideasonboard.com/
>
> To avoid duplicating again the validation routines and common types
> definition, this series introduces v4l2-isp.c/.h for the kAPI
> and v4l2-isp.h for the uAPI and re-organize the RkISP1
> and Amlogic C3 drivers to use the common types and the helper validation
> routines.
>
> The v4l2-isp abstraction will be augmented to support statistcs as well.
>
> If the here proposed approach is accepted, I propose to rebase the Mali
> C55 driver on top of this series, to use the new common types and
> helpers.
>
> I have been able to test this on RkISP1 but not on C3.
Thank you for working on this.
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
--
Kind regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-09-15 17:18 ` [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types Jacopo Mondi
@ 2025-10-05 0:06 ` Laurent Pinchart
2025-10-06 0:07 ` Laurent Pinchart
2025-10-06 8:15 ` Dan Scally
0 siblings, 2 replies; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-05 0:06 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Jacopo,
Thank you for the patch.
On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
> Introduce v4l2-isp.h in the Linux kernel uAPI.
>
> The header includes types for generic ISP configuration parameters
> and will be extended in future with support for generic ISP statistics
s/in future/in the future/
(and you can reflow the commit message)
> formats.
>
> Generic ISP parameters support is provided by introducing two new
> types that represent an extensible and versioned buffer of ISP
> configuration parameters.
>
> The v4l2_params_block_header structure represents the header to be
> prepend to each ISP configuration block and the v4l2_params_buffer type
> represents the base type for the configuration parameters buffer.
The second part of the sentence describes the same structure as the next
paragraph.
> The v4l2_params_buffer represents the container for the ISP
> configuration data block. The generic type is defined with a 0-sized
> data member that the ISP driver implementations shall properly size
> according to their capabilities.
This will be easier to understand if you describe v4l2_params_buffer
first.
The commit message would benefit from being rewritten.
> [Add v4l2_params_buffer_size()]
> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> MAINTAINERS | 6 +++
> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 106 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
> F: drivers/media/i2c/vd56g3.c
> F: drivers/media/i2c/vgxy61.c
>
> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> +L: linux-media@vger.kernel.org
> +S: Maintained
> +F: include/uapi/linux/media/v4l2-isp.h
> +
> VF610 NAND DRIVER
> M: Stefan Agner <stefan@agner.ch>
> L: linux-mtd@lists.infradead.org
> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
> --- /dev/null
> +++ b/include/uapi/linux/media/v4l2-isp.h
> @@ -0,0 +1,100 @@
> +/* 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 <jacopo.mondi@ideasonboard.com>
> + */
> +
> +#ifndef _UAPI_V4L2_ISP_H_
> +#define _UAPI_V4L2_ISP_H_
> +
> +#include <linux/stddef.h>
> +#include <linux/types.h>
> +
> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
> +
> +/*
> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
> + *
> + * Driver-specific flags should be defined as:
> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
s/PLATFORM/DRIVER/
> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
> + */
> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
> +
> +/**
> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
> + * driver inspects this common header to discern the block type and its size and
> + * properly handle the block content.
The last sentence is not relevant for the UAPI.
> + *
> + * 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_FL_* and
> + * driver-specific flags specified by the driver 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
I think the fields usually go right after the structure name, followed
by the rest of the documentation.
> + */
> +struct v4l2_params_block_header {
> + __u16 type;
> + __u16 flags;
> + __u32 size;
> +} __attribute__((aligned(8)));
> +
> +/**
> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
> + *
> + * Users of the v4l2 extensible parameters will have differing sized data arrays
> + * depending on their specific parameter buffers. Drivers and userspace will
> + * need to be able to calculate the appropriate size of the struct to
> + * accommodate all ISP configuration blocks provided by the platform.
> + * This macro provides a convenient tool for the calculation.
> + *
> + * @max_params_size: The total size of the ISP configuration blocks
> + */
> +#define v4l2_params_buffer_size(max_params_size) \
> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
This isn't used in this series as far as I can tell, and neither is it
used in your libcamera implementation. I'd drop the macro (as well as
the mention in the commit message).
> +
> +/**
> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
> + *
> + * This struct contains the configuration parameters of the ISP algorithms,
s/struct/structure/
> + * serialized by userspace into a data buffer. Each configuration parameter
> + * block is represented by a block-specific structure which contains a
> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
I think you can drop "nor overlaps", nobody in their right mind should
think the blocks could be overlayed :-)
> + * the effective size, in bytes, of the @data buffer.
> + *
> + * @version: The parameters buffer version (driver-specific)
> + * @data_size: The configuration data effective size, excluding this header
> + * @data: The configuration data
Move the fields up just after the structure name.
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> + */
> +struct v4l2_params_buffer {
> + __u32 version;
> + __u32 data_size;
> + __u8 data[] __counted_by(data_size);
> +};
> +
> +#endif /* _UAPI_V4L2_ISP_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 2/8] media: uapi: Convert RkISP1 to V4L2 extensible params
2025-09-15 17:18 ` [PATCH v5 2/8] media: uapi: Convert RkISP1 to V4L2 extensible params Jacopo Mondi
@ 2025-10-05 0:18 ` Laurent Pinchart
2025-10-06 8:17 ` Dan Scally
0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-05 0:18 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Jacopo,
Thank you for the patch.
On Mon, Sep 15, 2025 at 07:18:11PM +0200, Jacopo Mondi wrote:
> With the introduction of common types for extensible parameters
> format, convert the rkisp1-config.h header to use the new types.
>
> Factor-out the documentation that is now part of the common header
> and only keep the driver-specific on in place.
>
> The conversion to use common types doesn't impact userspace as the
> new types are either identical to the ones already existing in the
> RkISP1 uAPI or are 1-to-1 type convertible.
>
> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> include/uapi/linux/rkisp1-config.h | 104 ++++++++-----------------------------
> 1 file changed, 22 insertions(+), 82 deletions(-)
>
> diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
> index 3b060ea6eed71b87d79abc8401eae4e9c9f5323a..b90d94d3a852fb0af0fe447649487e9e80aca795 100644
> --- a/include/uapi/linux/rkisp1-config.h
> +++ b/include/uapi/linux/rkisp1-config.h
> @@ -7,8 +7,13 @@
> #ifndef _UAPI_RKISP1_CONFIG_H
> #define _UAPI_RKISP1_CONFIG_H
>
> +#ifdef __KERNEL__
> +#include <linux/build_bug.h>
> +#endif /* __KERNEL__ */
> #include <linux/types.h>
>
> +#include <linux/media/v4l2-isp.h>
> +
> /* Defect Pixel Cluster Detection */
> #define RKISP1_CIF_ISP_MODULE_DPCC (1U << 0)
> /* Black Level Subtraction */
> @@ -1158,79 +1163,26 @@ enum rkisp1_ext_params_block_type {
> RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR,
> };
>
> -#define RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE (1U << 0)
> -#define RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE (1U << 1)
> +/* For backward compatibility */
> +#define RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE V4L2_PARAMS_FL_BLOCK_DISABLE
> +#define RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE V4L2_PARAMS_FL_BLOCK_ENABLE
>
> /* A bitmask of parameters blocks supported on the current hardware. */
> #define RKISP1_CID_SUPPORTED_PARAMS_BLOCKS (V4L2_CID_USER_RKISP1_BASE + 0x01)
>
> /**
> - * struct rkisp1_ext_params_block_header - RkISP1 extensible parameters block
> - * header
> + * rkisp1_ext_params_block_header - RkISP1 extensible parameters block 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
> - * 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.
> + * blocks and is identical to :c:type:`v4l2_params_block_header`.
> *
> - * The @type field is one of the values enumerated by
> + * The type field is one of the values enumerated by
> * :c:type:`rkisp1_ext_params_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 is a bitmask of per-block flags RKISP1_EXT_PARAMS_FL_*.
> - *
> - * When userspace wants to configure and enable an ISP block it shall fully
> - * populate the block configuration and set the
> - * RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE bit in the @flags field.
> - *
> - * When userspace simply wants to disable an ISP block the
> - * RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bit should be set in @flags field. The
> - * driver ignores the rest of the block configuration structure in this case.
> - *
> - * If a new configuration of an ISP block has to be applied userspace shall
> - * fully populate the ISP block configuration and omit setting the
> - * RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE and RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bits
> - * in the @flags field.
> - *
> - * Setting both the RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE and
> - * RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bits in the @flags field is not allowed
> - * and not accepted by the driver.
> - *
> - * Userspace is responsible for correctly populating the parameters block header
> - * fields (@type, @flags and @size) and the block-specific parameters.
> - *
> - * For example:
> + * interpreted by the driver.
> *
> - * .. code-block:: c
> - *
> - * void populate_bls(struct rkisp1_ext_params_block_header *block) {
> - * struct rkisp1_ext_params_bls_config *bls =
> - * (struct rkisp1_ext_params_bls_config *)block;
> - *
> - * bls->header.type = RKISP1_EXT_PARAMS_BLOCK_ID_BLS;
> - * bls->header.flags = RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE;
> - * bls->header.size = sizeof(*bls);
> - *
> - * bls->config.enable_auto = 0;
> - * bls->config.fixed_val.r = blackLevelRed_;
> - * bls->config.fixed_val.gr = blackLevelGreenR_;
> - * bls->config.fixed_val.gb = blackLevelGreenB_;
> - * bls->config.fixed_val.b = blackLevelBlue_;
> - * }
> - *
> - * @type: The parameters block type, see
> - * :c:type:`rkisp1_ext_params_block_type`
> - * @flags: A bitmask of block flags
> - * @size: Size (in bytes) of the parameters block, including this header
> + * The flags field is a bitmask of per-block flags RKISP1_EXT_PARAMS_FL_*.
> */
> -struct rkisp1_ext_params_block_header {
> - __u16 type;
> - __u16 flags;
> - __u32 size;
> -};
> +#define rkisp1_ext_params_block_header v4l2_params_block_header
>
> /**
> * struct rkisp1_ext_params_bls_config - RkISP1 extensible params BLS config
> @@ -1594,21 +1546,7 @@ enum rksip1_ext_param_buffer_version {
> /**
> * struct rkisp1_ext_params_cfg - RkISP1 extensible parameters configuration
> *
> - * This struct contains the configuration parameters of the RkISP1 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:`rkisp1_ext_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.
> + * This is the driver-specific implementation of :c:type:`v4l2_params_buffer`.
> *
> * Currently the single RKISP1_EXT_PARAM_BUFFER_V1 version is supported.
> * When a new format version will be added, a mechanism for userspace to query
> @@ -1624,11 +1562,6 @@ enum rksip1_ext_param_buffer_version {
> * the maximum value represents the blocks supported by the kernel driver,
> * independently of the device instance.
> *
> - * 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 @data_size field with
> - * the effective size, in bytes, of the @data buffer.
> - *
> * The expected memory layout of the parameters buffer is::
> *
> * +-------------------- struct rkisp1_ext_params_cfg -------------------+
> @@ -1678,4 +1611,11 @@ struct rkisp1_ext_params_cfg {
> __u8 data[RKISP1_EXT_PARAMS_MAX_SIZE];
> };
>
> +#ifdef __KERNEL__
> +/* Make sure the header is type-convertible to the generic v4l2 params one */
> +static_assert((sizeof(struct rkisp1_ext_params_cfg) -
> + RKISP1_EXT_PARAMS_MAX_SIZE) ==
> + sizeof(struct v4l2_params_buffer));
> +#endif /* __KERNEL__ */
> +
> #endif /* _UAPI_RKISP1_CONFIG_H */
>
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 3/8] media: uapi: Convert Amlogic C3 to V4L2 extensible params
2025-09-15 17:18 ` [PATCH v5 3/8] media: uapi: Convert Amlogic C3 " Jacopo Mondi
@ 2025-10-05 0:24 ` Laurent Pinchart
0 siblings, 0 replies; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-05 0:24 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Jacopo,
Thank you for the patch.
On Mon, Sep 15, 2025 at 07:18:12PM +0200, Jacopo Mondi wrote:
> With the introduction of common types for extensible parameters
> format, convert the c3-isp-config.h header to use the new types.
>
> Factor-out the documentation that is now part of the common header
> and only keep the driver-specific on in place.
>
> The conversion to use common types doesn't impact userspace as the
> new types are either identical to the ones already existing in the
> C3 ISP uAPI or are 1-to-1 type convertible.
You can reflow the commit message.
> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> Reviewed-by: Keke Li <keke.li@amlogic.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> include/uapi/linux/media/amlogic/c3-isp-config.h | 86 ++++++------------------
> 1 file changed, 20 insertions(+), 66 deletions(-)
>
> diff --git a/include/uapi/linux/media/amlogic/c3-isp-config.h b/include/uapi/linux/media/amlogic/c3-isp-config.h
> index ed085ea62a574932c7ad8d59d34b2c5c74a597d8..bf6de55b27a7d4d15effcca5525865650d9070fb 100644
> --- a/include/uapi/linux/media/amlogic/c3-isp-config.h
> +++ b/include/uapi/linux/media/amlogic/c3-isp-config.h
> @@ -6,8 +6,13 @@
> #ifndef _UAPI_C3_ISP_CONFIG_H_
> #define _UAPI_C3_ISP_CONFIG_H_
>
> +#ifdef __KERNEL__
> +#include <linux/build_bug.h>
> +#endif /* __KERNEL__ */
> #include <linux/types.h>
>
> +#include <linux/media/v4l2-isp.h>
> +
> /*
> * Frames are split into zones of almost equal width and height - a zone is a
> * rectangular tile of a frame. The metering blocks within the ISP collect
> @@ -176,62 +181,22 @@ enum c3_isp_params_block_type {
> C3_ISP_PARAMS_BLOCK_SENTINEL
> };
>
> -#define C3_ISP_PARAMS_BLOCK_FL_DISABLE (1U << 0)
> -#define C3_ISP_PARAMS_BLOCK_FL_ENABLE (1U << 1)
> +/* For backward compatibility */
> +#define C3_ISP_PARAMS_BLOCK_FL_DISABLE V4L2_PARAMS_FL_BLOCK_DISABLE
> +#define C3_ISP_PARAMS_BLOCK_FL_ENABLE V4L2_PARAMS_FL_BLOCK_ENABLE
>
> /**
> * struct c3_isp_params_block_header - C3 ISP parameter block 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
> - * 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.
+ * blocks and is identical to :c:type:`v4l2_params_block_header`.
> *
> * The @type field is one of the values enumerated by
s/@type/type/
Please compile the documentation for the next version. I expect the
'struct c3_isp_params_block_header' above to not be appreciated by
sphinx as there's no corresponding structure.
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> * :c:type:`c3_isp_params_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 is a bitmask of per-block flags C3_ISP_PARAMS_FL*.
> - *
> - * When userspace wants to disable an ISP block the
> - * C3_ISP_PARAMS_BLOCK_FL_DISABLED bit should be set in the @flags field. In
> - * this case userspace may optionally omit the remainder of the configuration
> - * block, which will be ignored by the driver.
> - *
> - * When a new configuration of an ISP block needs to be applied userspace
> - * shall fully populate the ISP block and omit setting the
> - * C3_ISP_PARAMS_BLOCK_FL_DISABLED bit in the @flags field.
> - *
> - * Userspace is responsible for correctly populating the parameters block header
> - * fields (@type, @flags and @size) and the block-specific parameters.
> - *
> - * For example:
> - *
> - * .. code-block:: c
> + * interpreted by the driver.
> *
> - * void populate_pst_gamma(struct c3_isp_params_block_header *block) {
> - * struct c3_isp_params_pst_gamma *gamma =
> - * (struct c3_isp_params_pst_gamma *)block;
> - *
> - * gamma->header.type = C3_ISP_PARAMS_BLOCK_PST_GAMMA;
> - * gamma->header.flags = C3_ISP_PARAMS_BLOCK_FL_ENABLE;
> - * gamma->header.size = sizeof(*gamma);
> - *
> - * for (unsigned int i = 0; i < 129; i++)
> - * gamma->pst_gamma_lut[i] = i;
> - * }
> - *
> - * @type: The parameters block type from :c:type:`c3_isp_params_block_type`
> - * @flags: A bitmask of block flags
> - * @size: Size (in bytes) of the parameters block, including this header
> + * The flags field is a bitmask of per-block flags C3_ISP_PARAMS_FL_*.
> */
> -struct c3_isp_params_block_header {
> - __u16 type;
> - __u16 flags;
> - __u32 size;
> -};
> +#define c3_isp_params_block_header v4l2_params_block_header
>
> /**
> * struct c3_isp_params_awb_gains - Gains for auto-white balance
> @@ -498,26 +463,9 @@ struct c3_isp_params_blc {
> /**
> * struct c3_isp_params_cfg - C3 ISP configuration parameters
> *
> - * This struct contains the configuration parameters of the C3 ISP
> - * algorithms, serialized by userspace into an opaque data buffer. Each
> - * configuration parameter block is represented by a block-specific structure
> - * which contains a :c:type:`c3_isp_param_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 should 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 revision and return an error if the desired revision 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.
> + * This is the driver-specific implementation of :c:type:`v4l2_params_buffer`.
> + *
> + * Currently only C3_ISP_PARAM_BUFFER_V0 is supported.
> *
> * The expected memory layout of the parameters buffer is::
> *
> @@ -561,4 +509,10 @@ struct c3_isp_params_cfg {
> __u8 data[C3_ISP_PARAMS_MAX_SIZE];
> };
>
> +#ifdef __KERNEL__
> +/* Make sure the header is type-convertible to the generic v4l2 params one */
> +static_assert((sizeof(struct c3_isp_params_cfg) - C3_ISP_PARAMS_MAX_SIZE) ==
> + sizeof(struct v4l2_params_buffer));
> +#endif /* __KERNEL__ */
> +
> #endif
>
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-05 0:06 ` Laurent Pinchart
@ 2025-10-06 0:07 ` Laurent Pinchart
2025-10-06 8:15 ` Dan Scally
1 sibling, 0 replies; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 0:07 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On Sun, Oct 05, 2025 at 03:06:04AM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
> > Introduce v4l2-isp.h in the Linux kernel uAPI.
> >
> > The header includes types for generic ISP configuration parameters
> > and will be extended in future with support for generic ISP statistics
>
> s/in future/in the future/
>
> (and you can reflow the commit message)
>
> > formats.
> >
> > Generic ISP parameters support is provided by introducing two new
> > types that represent an extensible and versioned buffer of ISP
> > configuration parameters.
> >
> > The v4l2_params_block_header structure represents the header to be
> > prepend to each ISP configuration block and the v4l2_params_buffer type
> > represents the base type for the configuration parameters buffer.
>
> The second part of the sentence describes the same structure as the next
> paragraph.
>
> > The v4l2_params_buffer represents the container for the ISP
> > configuration data block. The generic type is defined with a 0-sized
> > data member that the ISP driver implementations shall properly size
> > according to their capabilities.
>
> This will be easier to understand if you describe v4l2_params_buffer
> first.
>
> The commit message would benefit from being rewritten.
>
> > [Add v4l2_params_buffer_size()]
> > Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > ---
> > MAINTAINERS | 6 +++
> > include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
> > 2 files changed, 106 insertions(+)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
> > F: drivers/media/i2c/vd56g3.c
> > F: drivers/media/i2c/vgxy61.c
> >
> > +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
> > +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > +L: linux-media@vger.kernel.org
> > +S: Maintained
> > +F: include/uapi/linux/media/v4l2-isp.h
> > +
> > VF610 NAND DRIVER
> > M: Stefan Agner <stefan@agner.ch>
> > L: linux-mtd@lists.infradead.org
> > diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
> > --- /dev/null
> > +++ b/include/uapi/linux/media/v4l2-isp.h
> > @@ -0,0 +1,100 @@
> > +/* 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 <jacopo.mondi@ideasonboard.com>
> > + */
> > +
> > +#ifndef _UAPI_V4L2_ISP_H_
> > +#define _UAPI_V4L2_ISP_H_
> > +
> > +#include <linux/stddef.h>
> > +#include <linux/types.h>
> > +
> > +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
> > +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
It occurred to me that, now that this is part of v4l2-isp.h, we should
probably prefer everything with v4l2_isp_. This would become
V4L2_ISP_PARAMS_FL_BLOCK_DISABLE, and same for the structures below.
Sorry for not noticing earlier.
> > +
> > +/*
> > + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
> > + *
> > + * Driver-specific flags should be defined as:
> > + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
>
> s/PLATFORM/DRIVER/
>
> > + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
> > + */
> > +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
> > +
> > +/**
> > + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
> > + * driver inspects this common header to discern the block type and its size and
> > + * properly handle the block content.
>
> The last sentence is not relevant for the UAPI.
>
> > + *
> > + * 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_FL_* and
> > + * driver-specific flags specified by the driver 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
>
> I think the fields usually go right after the structure name, followed
> by the rest of the documentation.
>
> > + */
> > +struct v4l2_params_block_header {
> > + __u16 type;
> > + __u16 flags;
> > + __u32 size;
> > +} __attribute__((aligned(8)));
> > +
> > +/**
> > + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
> > + *
> > + * Users of the v4l2 extensible parameters will have differing sized data arrays
> > + * depending on their specific parameter buffers. Drivers and userspace will
> > + * need to be able to calculate the appropriate size of the struct to
> > + * accommodate all ISP configuration blocks provided by the platform.
> > + * This macro provides a convenient tool for the calculation.
> > + *
> > + * @max_params_size: The total size of the ISP configuration blocks
> > + */
> > +#define v4l2_params_buffer_size(max_params_size) \
> > + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
>
> This isn't used in this series as far as I can tell, and neither is it
> used in your libcamera implementation. I'd drop the macro (as well as
> the mention in the commit message).
>
> > +
> > +/**
> > + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
> > + *
> > + * This struct contains the configuration parameters of the ISP algorithms,
>
> s/struct/structure/
>
> > + * serialized by userspace into a data buffer. Each configuration parameter
> > + * block is represented by a block-specific structure which contains a
> > + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
>
> I think you can drop "nor overlaps", nobody in their right mind should
> think the blocks could be overlayed :-)
>
> > + * the effective size, in bytes, of the @data buffer.
> > + *
> > + * @version: The parameters buffer version (driver-specific)
> > + * @data_size: The configuration data effective size, excluding this header
> > + * @data: The configuration data
>
> Move the fields up just after the structure name.
>
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>
> > + */
> > +struct v4l2_params_buffer {
> > + __u32 version;
> > + __u32 data_size;
> > + __u8 data[] __counted_by(data_size);
> > +};
> > +
> > +#endif /* _UAPI_V4L2_ISP_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c
2025-09-15 17:18 ` [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c Jacopo Mondi
@ 2025-10-06 0:47 ` Laurent Pinchart
2025-10-06 1:08 ` Laurent Pinchart
0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 0:47 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Jacopo,
Thank you for the patch.
On Mon, Sep 15, 2025 at 07:18:14PM +0200, Jacopo Mondi wrote:
> Add to the v4l2 framework helper functions to support drivers
s/v4l2/V4L2/
> when validating a buffer of extensible ISP parameters.
>
> Introduce new types in include/media/v4l2-isp.h that drivers shall use
> in order to comply with the generic ISP parameters validation procedure,
> and add helper functionss to v4l2-isp.c to perform blocks and buffer
> validation.
>
> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> MAINTAINERS | 2 +
> drivers/media/v4l2-core/Kconfig | 4 ++
> drivers/media/v4l2-core/Makefile | 1 +
> drivers/media/v4l2-core/v4l2-isp.c | 108 +++++++++++++++++++++++++++++++++++++
> include/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++
> 5 files changed, 215 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index abba872cb63f1430a49a2afbace4b9f9958c3991..5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -26415,6 +26415,8 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> L: linux-media@vger.kernel.org
> S: Maintained
> F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
> +F: drivers/media/v4l2-core/v4l2-isp.c
> +F: include/media/v4l2-isp.h
> F: include/uapi/linux/media/v4l2-isp.h
>
> VF610 NAND DRIVER
> diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
> index 331b8e535e5bbf33f22638b2ae8bc764ad5fc407..d50ccac9733cc39a43426ae7e7996dd0b5b45186 100644
> --- a/drivers/media/v4l2-core/Kconfig
> +++ b/drivers/media/v4l2-core/Kconfig
> @@ -82,3 +82,7 @@ config V4L2_CCI_I2C
> depends on I2C
> select REGMAP_I2C
> select V4L2_CCI
> +
> +config V4L2_ISP
> + tristate
> + depends on VIDEOBUF2_CORE
> diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> index 2177b9d63a8ffc1127c5a70118249a2ff63cd759..329f0eadce994cc1c8580beb435f68fa7e2a7aeb 100644
> --- a/drivers/media/v4l2-core/Makefile
> +++ b/drivers/media/v4l2-core/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o
> obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
> obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
> obj-$(CONFIG_V4L2_H264) += v4l2-h264.o
> +obj-$(CONFIG_V4L2_ISP) += v4l2-isp.o
> obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o
> obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
> obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o
> diff --git a/drivers/media/v4l2-core/v4l2-isp.c b/drivers/media/v4l2-core/v4l2-isp.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..e350bdaf53b5502e1ec2a4989c20df1100ab2d2a
> --- /dev/null
> +++ b/drivers/media/v4l2-core/v4l2-isp.c
> @@ -0,0 +1,108 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Video4Linux2 generic ISP parameters and statistics support
> + *
> + * Copyright (C) 2025 Ideas On Board Oy
> + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/device.h>
> +
> +#include <media/videobuf2-core.h>
> +#include <media/v4l2-isp.h>
v4l2-isp goes first.
> +
> +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> + size_t max_size)
> +{
> + size_t header_size = offsetof(struct v4l2_params_buffer, data);
> + struct v4l2_params_buffer *buffer = vb2_plane_vaddr(vb, 0);
> + size_t payload_size = vb2_get_plane_payload(vb, 0);
> + size_t buffer_size;
> +
> + /* Payload size can't be greater than the destination buffer size */
> + if (payload_size > max_size) {
> + dev_dbg(dev, "Payload size is too large: %zu\n", payload_size);
> + return -EINVAL;
> + }
> +
> + /* Payload size can't be smaller than the header size */
> + if (payload_size < header_size) {
> + dev_dbg(dev, "Payload size is too small: %zu\n", payload_size);
> + return -EINVAL;
> + }
> +
> + /* Validate the size reported in the parameter buffer header */
> + buffer_size = header_size + buffer->data_size;
> + if (buffer_size != payload_size) {
> + dev_dbg(dev, "Data size %zu and payload size %zu are different\n",
> + buffer_size, payload_size);
> + return -EINVAL;
> + }
This check needs to go to v4l2_params_blocks_validate() as it has to be
performed on the data after copying.
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_params_buffer_validate);
> +
> +int v4l2_params_blocks_validate(struct device *dev,
> + const struct v4l2_params_buffer *buffer,
> + const struct v4l2_params_handler *handlers,
> + size_t num_handlers)
> +{
> + size_t block_offset = 0;
> + size_t buffer_size;
> +
> + /* Walk the list of parameter blocks and validate them. */
> + buffer_size = buffer->data_size;
> + while (buffer_size >= sizeof(struct v4l2_params_block_header)) {
> + const struct v4l2_params_handler *handler;
> + const struct v4l2_params_block_header *block;
> +
> + /* Validate block sizes and types against the handlers. */
> + block = (const struct v4l2_params_block_header *)
> + (buffer->data + block_offset);
> +
> + if (block->type >= num_handlers) {
> + dev_dbg(dev, "Invalid parameters block type\n");
I'd print the type and offset in the message to ease debugging.
> + return -EINVAL;
> + }
> +
> + if (block->size > buffer_size) {
> + dev_dbg(dev, "Premature end of parameters data\n");
> + return -EINVAL;
> + }
> +
> + /* It's invalid to specify both ENABLE and DISABLE. */
> + if ((block->flags & (V4L2_PARAMS_FL_BLOCK_ENABLE |
> + V4L2_PARAMS_FL_BLOCK_DISABLE)) ==
> + (V4L2_PARAMS_FL_BLOCK_ENABLE |
> + V4L2_PARAMS_FL_BLOCK_DISABLE)) {
> + dev_dbg(dev, "Invalid parameters block flags\n");
Same here (print the flags and offset).
> + return -EINVAL;
> + }
> +
> + /*
> + * Match the block reported size against the handler's expected
> + * one, but allow the block to only contain the header in
> + * case it is going to be disabled.
> + */
> + handler = &handlers[block->type];
> + if (block->size != handler->size &&
> + (!(block->flags & V4L2_PARAMS_FL_BLOCK_DISABLE) ||
> + block->size != sizeof(*block))) {
> + dev_dbg(dev, "Invalid parameters block size\n");
And here too (print the size and offset).
> + return -EINVAL;
> + }
> +
> + block_offset += block->size;
> + buffer_size -= block->size;
> + }
> +
> + if (buffer_size) {
> + dev_dbg(dev, "Unexpected data after the parameters buffer end\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_params_blocks_validate);
> diff --git a/include/media/v4l2-isp.h b/include/media/v4l2-isp.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..2ad62c6169eef3d0fb8d245de56cc6bd7e6227e4
> --- /dev/null
> +++ b/include/media/v4l2-isp.h
> @@ -0,0 +1,100 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Video4Linux2 generic ISP parameters and statistics support
> + *
> + * Copyright (C) 2025 Ideas On Board Oy
> + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> + */
> +
> +#ifndef V4L2_PARAMS_H_
> +#define V4L2_PARAMS_H_
V4L2_ISP_H_
> +
> +#include <linux/media/v4l2-isp.h>
> +
> +struct device;
> +struct vb2_buffer;
> +
> +/**
> + * typedef v4l2_params_block_handler - V4L2 extensible format block handler
As commented on 1/8, let's use the v4l2_isp_ prefix.
> + * @arg: pointer the driver-specific argument
> + * @block: the ISP configuration block to handle
> + *
> + * Defines the function signature of the functions that handle an ISP block
> + * configuration.
> + */
> +typedef void (*v4l2_params_block_handler)(void *arg,
> + const struct v4l2_params_block_header *block);
> +
> +/**
> + * struct v4l2_params_handler - V4L2 extensible format handler
> + * @size: the block expected size
> + * @handler: the block handler function
> + *
> + * The v4l2_params_handler defines the type that driver making use of the
> + * V4L2 extensible parameters shall use to define their own ISP block
> + * handlers.
> + *
> + * Drivers shall prepare a list of handlers, one for each supported ISP block
> + * and correctly populate the structure's field with the expected block @size
> + * (used for validation) and a pointer to each block @handler function.
> + */
> +struct v4l2_params_handler {
> + size_t size;
> + v4l2_params_block_handler handler;
> +};
> +
> +/**
> + * v4l2_params_buffer_validate - Validate a V4L2 extensible parameters buffer
As this is the pre-copy validation, what would you think of calling the
function v4l2_isp_params_pre_validate_buffer() ? The next function would
be called v4l2_isp_params_validate_buffer(), as they're both about
buffer validation. I'm also OK to keep the current names (with a
v4l2_isp_ prefix).
I'm also thinking that the copy could be moved to the helper, but it can
be done later.
> + * @dev: the driver's device pointer
> + * @vb: the videobuf2 buffer
> + * @max_size: the maximum allowed buffer size
> + * @buffer_validate: callback to the driver-specific buffer validation
You forgot to drop the documentation for this argument.
> + *
> + * Helper function that performs validation of an extensible parameters buffer.
> + *
> + * The helper is meant to be used by drivers to perform validation of the
> + * extensible parameters buffer size correctness.
> + *
> + * The @vb buffer as received from the vb2 .buf_prepare() operation is checked
> + * against @max_size and its validated to be large enough to accommodate at
> + * least one ISP configuration block. The effective buffer size is compared
> + * with the reported data size to make sure they match.
> + *
> + * Drivers should use this function to validate the buffer size correctness
> + * before performing a copy of the user-provided videobuf2 buffer content into a
> + * kernel-only memory buffer to prevent userspace from modifying the buffer
> + * content after it has been submitted to the driver.
> + */
> +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> + size_t max_size);
> +
> +/**
> + * v4l2_params_blocks_validate - Validate V4L2 extensible parameters ISP
> + * configuration blocks
> + * @dev: the driver's device pointer
> + * @buffer: the extensible parameters configuration buffer
> + * @handlers: the list of block handlers
array of block handlers
> + * @num_handlers: the number of block handlers
> + *
> + * Helper function that performs validation of the ISP configuration blocks in
> + * an extensible parameters buffer.
> + *
> + * The helper is meant to be used by drivers to perform validation of the
> + * ISP configuration data blocks. For each block in the extensible parameters
> + * buffer, its size and correctness are validated against its associated handler
> + * in the @handlers list.
You need to explain somewhere that the handlers array is indexed by
block type.
> + *
> + * Drivers should use this function to validate the ISP configuration blocks
> + * after having validated the correctness of the vb2 buffer sizes by using the
> + * v4l2_params_buffer_validate() helper first. Once the buffer size has been
> + * validated, drivers should perform a copy of the user-provided buffer into a
> + * kernel-only memory buffer to prevent userspace from modifying the buffer
> + * content after it has been submitted to the driver, and then call this
> + * function to perform per-block validation.
There's room for improvement in the documentation. I think it would be
clearer if you explained the big picture in
Documentation/userspace-api/media/v4l/extensible-parameters.rst
(pre-validation, copy and post-validation), and only focussed on what
those two functions do in their kerneldoc. That can be done later,
nothing that you say here is incorrect.
With the other comments addressed,
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> + */
> +int v4l2_params_blocks_validate(struct device *dev,
> + const struct v4l2_params_buffer *buffer,
> + const struct v4l2_params_handler *handlers,
> + size_t num_handlers);
> +
> +#endif /* V4L2_PARAMS_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 6/8] media: rkisp1: Use v4l2-isp for validation
2025-09-15 17:18 ` [PATCH v5 6/8] media: rkisp1: Use v4l2-isp for validation Jacopo Mondi
@ 2025-10-06 1:06 ` Laurent Pinchart
0 siblings, 0 replies; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 1:06 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Jacopo,
Thank you for the patch.
On Mon, Sep 15, 2025 at 07:18:15PM +0200, Jacopo Mondi wrote:
> Convert rkisp1-params.c to use the new types for block handlers
> defined in v4l2-isp.h and use the new helpers from v4l2-isp.c
> to remove bolierplate code from the driver.
s/bolier/boiler/
>
> Break out from the handlers enumeration the 'group' and 'feature' flags
> to a separate array and perform driver specific validation of these
> fields separately.
>
> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> drivers/media/platform/rockchip/rkisp1/Kconfig | 1 +
> .../media/platform/rockchip/rkisp1/rkisp1-params.c | 441 ++++++++++-----------
> 2 files changed, 209 insertions(+), 233 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/Kconfig b/drivers/media/platform/rockchip/rkisp1/Kconfig
> index 731c9acbf6efa33188617204d441fb0ea59adebc..f53eb1f3f3e7003d8e02c9236aeabb5ae8844f7b 100644
> --- a/drivers/media/platform/rockchip/rkisp1/Kconfig
> +++ b/drivers/media/platform/rockchip/rkisp1/Kconfig
> @@ -10,6 +10,7 @@ config VIDEO_ROCKCHIP_ISP1
> select VIDEOBUF2_VMALLOC
> select V4L2_FWNODE
> select GENERIC_PHY_MIPI_DPHY
> + select V4L2_ISP
I wouldn't mind if you sorted the entries alphabetically while at it.
> default n
> help
> Enable this to support the Image Signal Processing (ISP) module
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index f1585f8fa0f478304f74317fd9dd09199c94ec82..de4e459fb556afb08891558dbf9d55b1973af8da 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -12,6 +12,7 @@
> #include <media/v4l2-common.h>
> #include <media/v4l2-event.h>
> #include <media/v4l2-ioctl.h>
> +#include <media/v4l2-isp.h>
> #include <media/videobuf2-core.h>
> #include <media/videobuf2-vmalloc.h> /* for ISP params */
>
> @@ -40,30 +41,6 @@
> #define RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS BIT(0)
> #define RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC BIT(1)
>
> -union rkisp1_ext_params_config {
> - struct rkisp1_ext_params_block_header header;
> - struct rkisp1_ext_params_bls_config bls;
> - struct rkisp1_ext_params_dpcc_config dpcc;
> - struct rkisp1_ext_params_sdg_config sdg;
> - struct rkisp1_ext_params_lsc_config lsc;
> - struct rkisp1_ext_params_awb_gain_config awbg;
> - struct rkisp1_ext_params_flt_config flt;
> - struct rkisp1_ext_params_bdm_config bdm;
> - struct rkisp1_ext_params_ctk_config ctk;
> - struct rkisp1_ext_params_goc_config goc;
> - struct rkisp1_ext_params_dpf_config dpf;
> - struct rkisp1_ext_params_dpf_strength_config dpfs;
> - struct rkisp1_ext_params_cproc_config cproc;
> - struct rkisp1_ext_params_ie_config ie;
> - struct rkisp1_ext_params_awb_meas_config awbm;
> - struct rkisp1_ext_params_hst_config hst;
> - struct rkisp1_ext_params_aec_config aec;
> - struct rkisp1_ext_params_afc_config afc;
> - struct rkisp1_ext_params_compand_bls_config compand_bls;
> - struct rkisp1_ext_params_compand_curve_config compand_curve;
> - struct rkisp1_ext_params_wdr_config wdr;
> -};
> -
> enum rkisp1_params_formats {
> RKISP1_PARAMS_FIXED,
> RKISP1_PARAMS_EXTENSIBLE,
> @@ -1689,11 +1666,12 @@ static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params,
> * Extensible parameters format handling
> */
>
> -static void
> -rkisp1_ext_params_bls(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_bls(void *dev,
dev is a weird name. I'd go for data or priv.
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_bls_config *bls = &block->bls;
> + const struct rkisp1_ext_params_bls_config *bls =
> + (const struct rkisp1_ext_params_bls_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> @@ -1709,11 +1687,12 @@ rkisp1_ext_params_bls(struct rkisp1_params *params,
> RKISP1_CIF_ISP_BLS_ENA);
> }
>
> -static void
> -rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_dpcc(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
> + const struct rkisp1_ext_params_dpcc_config *dpcc =
> + (const struct rkisp1_ext_params_dpcc_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (dpcc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> @@ -1729,11 +1708,12 @@ rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> }
>
> -static void
> -rkisp1_ext_params_sdg(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_sdg(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
> + const struct rkisp1_ext_params_sdg_config *sdg =
> + (const struct rkisp1_ext_params_sdg_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (sdg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1749,11 +1729,12 @@ rkisp1_ext_params_sdg(struct rkisp1_params *params,
> RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> }
>
> -static void
> -rkisp1_ext_params_lsc(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_lsc(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
> + const struct rkisp1_ext_params_lsc_config *lsc =
> + (const struct rkisp1_ext_params_lsc_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (lsc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> @@ -1769,11 +1750,12 @@ rkisp1_ext_params_lsc(struct rkisp1_params *params,
> RKISP1_CIF_ISP_LSC_CTRL_ENA);
> }
>
> -static void
> -rkisp1_ext_params_awbg(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_awbg(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
> + const struct rkisp1_ext_params_awb_gain_config *awbg =
> + (const struct rkisp1_ext_params_awb_gain_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (awbg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1789,11 +1771,12 @@ rkisp1_ext_params_awbg(struct rkisp1_params *params,
> RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> }
>
> -static void
> -rkisp1_ext_params_flt(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_flt(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_flt_config *flt = &block->flt;
> + const struct rkisp1_ext_params_flt_config *flt =
> + (const struct rkisp1_ext_params_flt_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (flt->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> @@ -1809,11 +1792,12 @@ rkisp1_ext_params_flt(struct rkisp1_params *params,
> RKISP1_CIF_ISP_FLT_ENA);
> }
>
> -static void
> -rkisp1_ext_params_bdm(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_bdm(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
> + const struct rkisp1_ext_params_bdm_config *bdm =
> + (const struct rkisp1_ext_params_bdm_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (bdm->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> @@ -1829,11 +1813,12 @@ rkisp1_ext_params_bdm(struct rkisp1_params *params,
> RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> }
>
> -static void
> -rkisp1_ext_params_ctk(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_ctk(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
> + const struct rkisp1_ext_params_ctk_config *ctk =
> + (const struct rkisp1_ext_params_ctk_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (ctk->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_ctk_enable(params, false);
> @@ -1847,11 +1832,12 @@ rkisp1_ext_params_ctk(struct rkisp1_params *params,
> rkisp1_ctk_enable(params, true);
> }
>
> -static void
> -rkisp1_ext_params_goc(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_goc(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_goc_config *goc = &block->goc;
> + const struct rkisp1_ext_params_goc_config *goc =
> + (const struct rkisp1_ext_params_goc_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (goc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1869,11 +1855,12 @@ rkisp1_ext_params_goc(struct rkisp1_params *params,
> RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> }
>
> -static void
> -rkisp1_ext_params_dpf(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_dpf(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
> + const struct rkisp1_ext_params_dpf_config *dpf =
> + (const struct rkisp1_ext_params_dpf_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (dpf->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> @@ -1889,20 +1876,22 @@ rkisp1_ext_params_dpf(struct rkisp1_params *params,
> RKISP1_CIF_ISP_DPF_MODE_EN);
> }
>
> -static void
> -rkisp1_ext_params_dpfs(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_dpfs(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
> + const struct rkisp1_ext_params_dpf_strength_config *dpfs =
> + (const struct rkisp1_ext_params_dpf_strength_config *)block;
> + struct rkisp1_params *params = dev;
>
> rkisp1_dpf_strength_config(params, &dpfs->config);
> }
>
> -static void
> -rkisp1_ext_params_cproc(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_cproc(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
> + const struct rkisp1_ext_params_cproc_config *cproc =
> + (const struct rkisp1_ext_params_cproc_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (cproc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
> @@ -1918,11 +1907,12 @@ rkisp1_ext_params_cproc(struct rkisp1_params *params,
> RKISP1_CIF_C_PROC_CTR_ENABLE);
> }
>
> -static void
> -rkisp1_ext_params_ie(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_ie(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_ie_config *ie = &block->ie;
> + const struct rkisp1_ext_params_ie_config *ie =
> + (const struct rkisp1_ext_params_ie_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (ie->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_ie_enable(params, false);
> @@ -1936,11 +1926,12 @@ rkisp1_ext_params_ie(struct rkisp1_params *params,
> rkisp1_ie_enable(params, true);
> }
>
> -static void
> -rkisp1_ext_params_awbm(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_awbm(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
> + const struct rkisp1_ext_params_awb_meas_config *awbm =
> + (const struct rkisp1_ext_params_awb_meas_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (awbm->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> params->ops->awb_meas_enable(params, &awbm->config,
> @@ -1956,11 +1947,12 @@ rkisp1_ext_params_awbm(struct rkisp1_params *params,
> true);
> }
>
> -static void
> -rkisp1_ext_params_hstm(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_hstm(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_hst_config *hst = &block->hst;
> + const struct rkisp1_ext_params_hst_config *hst =
> + (const struct rkisp1_ext_params_hst_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (hst->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> params->ops->hst_enable(params, &hst->config, false);
> @@ -1974,11 +1966,12 @@ rkisp1_ext_params_hstm(struct rkisp1_params *params,
> params->ops->hst_enable(params, &hst->config, true);
> }
>
> -static void
> -rkisp1_ext_params_aecm(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_aecm(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_aec_config *aec = &block->aec;
> + const struct rkisp1_ext_params_aec_config *aec =
> + (const struct rkisp1_ext_params_aec_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (aec->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> @@ -1994,11 +1987,12 @@ rkisp1_ext_params_aecm(struct rkisp1_params *params,
> RKISP1_CIF_ISP_EXP_ENA);
> }
>
> -static void
> -rkisp1_ext_params_afcm(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_afcm(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_afc_config *afc = &block->afc;
> + const struct rkisp1_ext_params_afc_config *afc =
> + (const struct rkisp1_ext_params_afc_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (afc->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> @@ -2014,11 +2008,12 @@ rkisp1_ext_params_afcm(struct rkisp1_params *params,
> RKISP1_CIF_ISP_AFM_ENA);
> }
>
> -static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_compand_bls(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> const struct rkisp1_ext_params_compand_bls_config *bls =
> - &block->compand_bls;
> + (const struct rkisp1_ext_params_compand_bls_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> @@ -2034,11 +2029,13 @@ static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
> RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> }
>
> -static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void
> +rkisp1_ext_params_compand_expand(void *dev,
> + const struct v4l2_params_block_header *block)
That doesn't match the wrap style of the other handlers.
> {
> const struct rkisp1_ext_params_compand_curve_config *curve =
> - &block->compand_curve;
> + (const struct rkisp1_ext_params_compand_curve_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> @@ -2054,11 +2051,13 @@ static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
> RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> }
>
> -static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void
> +rkisp1_ext_params_compand_compress(void *dev,
> + const struct v4l2_params_block_header *block)
Same here.
> {
> const struct rkisp1_ext_params_compand_curve_config *curve =
> - &block->compand_curve;
> + (const struct rkisp1_ext_params_compand_curve_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> @@ -2074,10 +2073,12 @@ static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
> RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> }
>
> -static void rkisp1_ext_params_wdr(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *block)
> +static void rkisp1_ext_params_wdr(void *dev,
> + const struct v4l2_params_block_header *block)
> {
> - const struct rkisp1_ext_params_wdr_config *wdr = &block->wdr;
> + const struct rkisp1_ext_params_wdr_config *wdr =
> + (const struct rkisp1_ext_params_wdr_config *)block;
> + struct rkisp1_params *params = dev;
>
> if (wdr->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
> rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_WDR_CTRL,
> @@ -2093,123 +2094,163 @@ static void rkisp1_ext_params_wdr(struct rkisp1_params *params,
> RKISP1_CIF_ISP_WDR_CTRL_ENABLE);
> }
>
> -typedef void (*rkisp1_block_handler)(struct rkisp1_params *params,
> - const union rkisp1_ext_params_config *config);
> -
> -static const struct rkisp1_ext_params_handler {
> - size_t size;
> - rkisp1_block_handler handler;
> +static const struct rkisp1_params_block_feature {
> unsigned int group;
> unsigned int features;
> -} rkisp1_ext_params_handlers[] = {
> +} rkisp1_ext_params_features[] = {
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS] = {
> - .size = sizeof(struct rkisp1_ext_params_bls_config),
> - .handler = rkisp1_ext_params_bls,
> .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> .features = RKISP1_FEATURE_BLS,
> },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_IE] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + .features = RKISP1_FEATURE_COMPAND,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + .features = RKISP1_FEATURE_COMPAND,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + .features = RKISP1_FEATURE_COMPAND,
> + },
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR] = {
> + .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> + },
> +};
> +
> +static const struct v4l2_params_handler rkisp1_ext_params_handlers[] = {
> + [RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS] = {
> + .size = sizeof(struct rkisp1_ext_params_bls_config),
> + .handler = rkisp1_ext_params_bls,
> + },
And now that I look at this, the v4l2_params_blocks_validate() function
never calls .handler(). It seems you could simply pass a list of block
sizes to the function. I'd call the structure
v4l2_isp_params_block_info, with a single size field. This means that
the block handler won't need to be a generic function anymore, it will
simplify this patch.
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC] = {
> .size = sizeof(struct rkisp1_ext_params_dpcc_config),
> .handler = rkisp1_ext_params_dpcc,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG] = {
> .size = sizeof(struct rkisp1_ext_params_sdg_config),
> .handler = rkisp1_ext_params_sdg,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN] = {
> .size = sizeof(struct rkisp1_ext_params_awb_gain_config),
> .handler = rkisp1_ext_params_awbg,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT] = {
> .size = sizeof(struct rkisp1_ext_params_flt_config),
> .handler = rkisp1_ext_params_flt,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM] = {
> .size = sizeof(struct rkisp1_ext_params_bdm_config),
> .handler = rkisp1_ext_params_bdm,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK] = {
> .size = sizeof(struct rkisp1_ext_params_ctk_config),
> .handler = rkisp1_ext_params_ctk,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC] = {
> .size = sizeof(struct rkisp1_ext_params_goc_config),
> .handler = rkisp1_ext_params_goc,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF] = {
> .size = sizeof(struct rkisp1_ext_params_dpf_config),
> .handler = rkisp1_ext_params_dpf,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH] = {
> .size = sizeof(struct rkisp1_ext_params_dpf_strength_config),
> .handler = rkisp1_ext_params_dpfs,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC] = {
> .size = sizeof(struct rkisp1_ext_params_cproc_config),
> .handler = rkisp1_ext_params_cproc,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_IE] = {
> .size = sizeof(struct rkisp1_ext_params_ie_config),
> .handler = rkisp1_ext_params_ie,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC] = {
> .size = sizeof(struct rkisp1_ext_params_lsc_config),
> .handler = rkisp1_ext_params_lsc,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS] = {
> .size = sizeof(struct rkisp1_ext_params_awb_meas_config),
> .handler = rkisp1_ext_params_awbm,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS] = {
> .size = sizeof(struct rkisp1_ext_params_hst_config),
> .handler = rkisp1_ext_params_hstm,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS] = {
> .size = sizeof(struct rkisp1_ext_params_aec_config),
> .handler = rkisp1_ext_params_aecm,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS] = {
> .size = sizeof(struct rkisp1_ext_params_afc_config),
> .handler = rkisp1_ext_params_afcm,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
> .size = sizeof(struct rkisp1_ext_params_compand_bls_config),
> .handler = rkisp1_ext_params_compand_bls,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> - .features = RKISP1_FEATURE_COMPAND,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
> .size = sizeof(struct rkisp1_ext_params_compand_curve_config),
> .handler = rkisp1_ext_params_compand_expand,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> - .features = RKISP1_FEATURE_COMPAND,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
> .size = sizeof(struct rkisp1_ext_params_compand_curve_config),
> .handler = rkisp1_ext_params_compand_compress,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> - .features = RKISP1_FEATURE_COMPAND,
> },
> [RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR] = {
> .size = sizeof(struct rkisp1_ext_params_wdr_config),
> .handler = rkisp1_ext_params_wdr,
> - .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> },
> };
>
> @@ -2224,31 +2265,33 @@ static void rkisp1_ext_params_config(struct rkisp1_params *params,
>
> /* Walk the list of parameter blocks and process them. */
> while (block_offset < cfg->data_size) {
> - const struct rkisp1_ext_params_handler *block_handler;
> - const union rkisp1_ext_params_config *block;
> + const struct rkisp1_params_block_feature *block_features;
> + const struct v4l2_params_handler *block_handler;
> + const struct v4l2_params_block_header *block;
>
> - block = (const union rkisp1_ext_params_config *)
> + block = (const struct v4l2_params_block_header *)
> &cfg->data[block_offset];
> - block_offset += block->header.size;
> + block_offset += block->size;
>
> /*
> * Make sure the block is supported by the platform and in the
> * list of groups to configure.
> */
> - block_handler = &rkisp1_ext_params_handlers[block->header.type];
> - if (!(block_handler->group & block_group_mask))
> + block_features = &rkisp1_ext_params_features[block->type];
> + if (!(block_features->group & block_group_mask))
> continue;
>
> - if ((params->rkisp1->info->features & block_handler->features) !=
> - block_handler->features)
> + if ((params->rkisp1->info->features & block_features->features)
> + != block_features->features)
> continue;
>
> + block_handler = &rkisp1_ext_params_handlers[block->type];
> block_handler->handler(params, block);
>
> - if (block->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)
> - params->enabled_blocks &= ~BIT(block->header.type);
> - else if (block->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE)
> - params->enabled_blocks |= BIT(block->header.type);
> + if (block->flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)
> + params->enabled_blocks &= ~BIT(block->type);
> + else if (block->flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE)
> + params->enabled_blocks |= BIT(block->type);
> }
> }
>
> @@ -2646,31 +2689,24 @@ static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> {
> struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> - size_t header_size = offsetof(struct rkisp1_ext_params_cfg, data);
> struct rkisp1_ext_params_cfg *cfg = params_buf->cfg;
> size_t payload_size = vb2_get_plane_payload(vb, 0);
> struct rkisp1_ext_params_cfg *usr_cfg =
> vb2_plane_vaddr(&vbuf->vb2_buf, 0);
> - size_t block_offset = 0;
> - size_t cfg_size;
> + int ret;
>
> - /*
> - * Validate the buffer payload size before copying the parameters. The
> - * payload has to be smaller than the destination buffer size and larger
> - * than the header size.
> - */
> - if (payload_size > params->metafmt->buffersize) {
> + /* Only v1 is supported at the moment. */
> + if (usr_cfg->version != RKISP1_EXT_PARAM_BUFFER_V1) {
I think versions should be defined in the v4l2-isp.h UAPI header and
shared between different drivers. The version defines the layout of the
standard structures. This can be done in an additional patch at the end
of the series.
> dev_dbg(params->rkisp1->dev,
> - "Too large buffer payload size %zu\n", payload_size);
> + "Unsupported extensible parameters version: %u\n",
> + usr_cfg->version);
> return -EINVAL;
> }
>
> - if (payload_size < header_size) {
> - dev_dbg(params->rkisp1->dev,
> - "Buffer payload %zu smaller than header size %zu\n",
> - payload_size, header_size);
> - return -EINVAL;
> - }
> + ret = v4l2_params_buffer_validate(params->rkisp1->dev, vb,
> + params->metafmt->buffersize);
> + if (ret)
> + return ret;
>
> /*
> * Copy the parameters buffer to the internal scratch buffer to avoid
> @@ -2678,71 +2714,10 @@ static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> */
> memcpy(cfg, usr_cfg, payload_size);
>
> - /* Only v1 is supported at the moment. */
> - if (cfg->version != RKISP1_EXT_PARAM_BUFFER_V1) {
> - dev_dbg(params->rkisp1->dev,
> - "Unsupported extensible format version: %u\n",
> - cfg->version);
> - return -EINVAL;
> - }
> -
> - /* Validate the size reported in the parameters buffer header. */
> - cfg_size = header_size + cfg->data_size;
> - if (cfg_size != payload_size) {
> - dev_dbg(params->rkisp1->dev,
> - "Data size %zu different than buffer payload size %zu\n",
> - cfg_size, payload_size);
> - return -EINVAL;
> - }
> -
> - /* Walk the list of parameter blocks and validate them. */
> - cfg_size = cfg->data_size;
> - while (cfg_size >= sizeof(struct rkisp1_ext_params_block_header)) {
> - const struct rkisp1_ext_params_block_header *block;
> - const struct rkisp1_ext_params_handler *handler;
> -
> - block = (const struct rkisp1_ext_params_block_header *)
> - &cfg->data[block_offset];
> -
> - if (block->type >= ARRAY_SIZE(rkisp1_ext_params_handlers)) {
> - dev_dbg(params->rkisp1->dev,
> - "Invalid parameters block type\n");
> - return -EINVAL;
> - }
> -
> - if (block->size > cfg_size) {
> - dev_dbg(params->rkisp1->dev,
> - "Premature end of parameters data\n");
> - return -EINVAL;
> - }
> -
> - if ((block->flags & (RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE |
> - RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)) ==
> - (RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE |
> - RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE)) {
> - dev_dbg(params->rkisp1->dev,
> - "Invalid parameters block flags\n");
> - return -EINVAL;
> - }
> -
> - handler = &rkisp1_ext_params_handlers[block->type];
> - if (block->size != handler->size) {
> - dev_dbg(params->rkisp1->dev,
> - "Invalid parameters block size\n");
> - return -EINVAL;
> - }
> -
> - block_offset += block->size;
> - cfg_size -= block->size;
> - }
> -
> - if (cfg_size) {
> - dev_dbg(params->rkisp1->dev,
> - "Unexpected data after the parameters buffer end\n");
> - return -EINVAL;
> - }
> -
> - return 0;
> + return v4l2_params_blocks_validate(params->rkisp1->dev,
> + (struct v4l2_params_buffer *)cfg,
> + rkisp1_ext_params_handlers,
> + ARRAY_SIZE(rkisp1_ext_params_handlers));
> }
>
> static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> @@ -2842,13 +2817,13 @@ static int rkisp1_params_ctrl_init(struct rkisp1_params *params)
> v4l2_ctrl_handler_init(¶ms->ctrls, 1);
>
> for (unsigned int i = 0; i < ARRAY_SIZE(rkisp1_ext_params_handlers); i++) {
> - const struct rkisp1_ext_params_handler *block_handler;
> + const struct rkisp1_params_block_feature *block_features;
>
> - block_handler = &rkisp1_ext_params_handlers[i];
> + block_features = &rkisp1_ext_params_features[i];
> ctrl_config.max |= BIT(i);
>
> - if ((params->rkisp1->info->features & block_handler->features) !=
> - block_handler->features)
> + if ((params->rkisp1->info->features & block_features->features)
> + != block_features->features)
> continue;
>
> ctrl_config.def |= BIT(i);
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c
2025-10-06 0:47 ` Laurent Pinchart
@ 2025-10-06 1:08 ` Laurent Pinchart
2025-10-06 10:28 ` Jacopo Mondi
0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 1:08 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On Mon, Oct 06, 2025 at 03:47:43AM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Mon, Sep 15, 2025 at 07:18:14PM +0200, Jacopo Mondi wrote:
> > Add to the v4l2 framework helper functions to support drivers
>
> s/v4l2/V4L2/
>
> > when validating a buffer of extensible ISP parameters.
> >
> > Introduce new types in include/media/v4l2-isp.h that drivers shall use
> > in order to comply with the generic ISP parameters validation procedure,
> > and add helper functionss to v4l2-isp.c to perform blocks and buffer
> > validation.
> >
> > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > ---
> > MAINTAINERS | 2 +
> > drivers/media/v4l2-core/Kconfig | 4 ++
> > drivers/media/v4l2-core/Makefile | 1 +
> > drivers/media/v4l2-core/v4l2-isp.c | 108 +++++++++++++++++++++++++++++++++++++
> > include/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++
> > 5 files changed, 215 insertions(+)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index abba872cb63f1430a49a2afbace4b9f9958c3991..5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -26415,6 +26415,8 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > L: linux-media@vger.kernel.org
> > S: Maintained
> > F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
> > +F: drivers/media/v4l2-core/v4l2-isp.c
> > +F: include/media/v4l2-isp.h
> > F: include/uapi/linux/media/v4l2-isp.h
> >
> > VF610 NAND DRIVER
> > diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
> > index 331b8e535e5bbf33f22638b2ae8bc764ad5fc407..d50ccac9733cc39a43426ae7e7996dd0b5b45186 100644
> > --- a/drivers/media/v4l2-core/Kconfig
> > +++ b/drivers/media/v4l2-core/Kconfig
> > @@ -82,3 +82,7 @@ config V4L2_CCI_I2C
> > depends on I2C
> > select REGMAP_I2C
> > select V4L2_CCI
> > +
> > +config V4L2_ISP
> > + tristate
> > + depends on VIDEOBUF2_CORE
> > diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> > index 2177b9d63a8ffc1127c5a70118249a2ff63cd759..329f0eadce994cc1c8580beb435f68fa7e2a7aeb 100644
> > --- a/drivers/media/v4l2-core/Makefile
> > +++ b/drivers/media/v4l2-core/Makefile
> > @@ -29,6 +29,7 @@ obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o
> > obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
> > obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
> > obj-$(CONFIG_V4L2_H264) += v4l2-h264.o
> > +obj-$(CONFIG_V4L2_ISP) += v4l2-isp.o
> > obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o
> > obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
> > obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o
> > diff --git a/drivers/media/v4l2-core/v4l2-isp.c b/drivers/media/v4l2-core/v4l2-isp.c
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..e350bdaf53b5502e1ec2a4989c20df1100ab2d2a
> > --- /dev/null
> > +++ b/drivers/media/v4l2-core/v4l2-isp.c
> > @@ -0,0 +1,108 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Video4Linux2 generic ISP parameters and statistics support
> > + *
> > + * Copyright (C) 2025 Ideas On Board Oy
> > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > + */
> > +
> > +#include <linux/bitops.h>
> > +#include <linux/device.h>
> > +
> > +#include <media/videobuf2-core.h>
> > +#include <media/v4l2-isp.h>
>
> v4l2-isp goes first.
>
> > +
> > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > + size_t max_size)
> > +{
> > + size_t header_size = offsetof(struct v4l2_params_buffer, data);
> > + struct v4l2_params_buffer *buffer = vb2_plane_vaddr(vb, 0);
> > + size_t payload_size = vb2_get_plane_payload(vb, 0);
> > + size_t buffer_size;
> > +
> > + /* Payload size can't be greater than the destination buffer size */
> > + if (payload_size > max_size) {
> > + dev_dbg(dev, "Payload size is too large: %zu\n", payload_size);
> > + return -EINVAL;
> > + }
> > +
> > + /* Payload size can't be smaller than the header size */
> > + if (payload_size < header_size) {
> > + dev_dbg(dev, "Payload size is too small: %zu\n", payload_size);
> > + return -EINVAL;
> > + }
> > +
> > + /* Validate the size reported in the parameter buffer header */
> > + buffer_size = header_size + buffer->data_size;
> > + if (buffer_size != payload_size) {
> > + dev_dbg(dev, "Data size %zu and payload size %zu are different\n",
> > + buffer_size, payload_size);
> > + return -EINVAL;
> > + }
>
> This check needs to go to v4l2_params_blocks_validate() as it has to be
> performed on the data after copying.
>
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(v4l2_params_buffer_validate);
> > +
> > +int v4l2_params_blocks_validate(struct device *dev,
> > + const struct v4l2_params_buffer *buffer,
> > + const struct v4l2_params_handler *handlers,
> > + size_t num_handlers)
> > +{
> > + size_t block_offset = 0;
> > + size_t buffer_size;
> > +
> > + /* Walk the list of parameter blocks and validate them. */
> > + buffer_size = buffer->data_size;
> > + while (buffer_size >= sizeof(struct v4l2_params_block_header)) {
> > + const struct v4l2_params_handler *handler;
> > + const struct v4l2_params_block_header *block;
> > +
> > + /* Validate block sizes and types against the handlers. */
> > + block = (const struct v4l2_params_block_header *)
> > + (buffer->data + block_offset);
> > +
> > + if (block->type >= num_handlers) {
> > + dev_dbg(dev, "Invalid parameters block type\n");
>
> I'd print the type and offset in the message to ease debugging.
>
> > + return -EINVAL;
> > + }
> > +
> > + if (block->size > buffer_size) {
> > + dev_dbg(dev, "Premature end of parameters data\n");
> > + return -EINVAL;
> > + }
> > +
> > + /* It's invalid to specify both ENABLE and DISABLE. */
> > + if ((block->flags & (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > + V4L2_PARAMS_FL_BLOCK_DISABLE)) ==
> > + (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > + V4L2_PARAMS_FL_BLOCK_DISABLE)) {
> > + dev_dbg(dev, "Invalid parameters block flags\n");
>
> Same here (print the flags and offset).
>
> > + return -EINVAL;
> > + }
> > +
> > + /*
> > + * Match the block reported size against the handler's expected
> > + * one, but allow the block to only contain the header in
> > + * case it is going to be disabled.
> > + */
> > + handler = &handlers[block->type];
> > + if (block->size != handler->size &&
> > + (!(block->flags & V4L2_PARAMS_FL_BLOCK_DISABLE) ||
> > + block->size != sizeof(*block))) {
> > + dev_dbg(dev, "Invalid parameters block size\n");
>
> And here too (print the size and offset).
>
> > + return -EINVAL;
> > + }
> > +
> > + block_offset += block->size;
> > + buffer_size -= block->size;
> > + }
> > +
> > + if (buffer_size) {
> > + dev_dbg(dev, "Unexpected data after the parameters buffer end\n");
> > + return -EINVAL;
> > + }
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(v4l2_params_blocks_validate);
> > diff --git a/include/media/v4l2-isp.h b/include/media/v4l2-isp.h
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..2ad62c6169eef3d0fb8d245de56cc6bd7e6227e4
> > --- /dev/null
> > +++ b/include/media/v4l2-isp.h
> > @@ -0,0 +1,100 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Video4Linux2 generic ISP parameters and statistics support
> > + *
> > + * Copyright (C) 2025 Ideas On Board Oy
> > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > + */
> > +
> > +#ifndef V4L2_PARAMS_H_
> > +#define V4L2_PARAMS_H_
>
> V4L2_ISP_H_
>
> > +
> > +#include <linux/media/v4l2-isp.h>
> > +
> > +struct device;
> > +struct vb2_buffer;
> > +
> > +/**
> > + * typedef v4l2_params_block_handler - V4L2 extensible format block handler
>
> As commented on 1/8, let's use the v4l2_isp_ prefix.
>
> > + * @arg: pointer the driver-specific argument
> > + * @block: the ISP configuration block to handle
> > + *
> > + * Defines the function signature of the functions that handle an ISP block
> > + * configuration.
> > + */
> > +typedef void (*v4l2_params_block_handler)(void *arg,
> > + const struct v4l2_params_block_header *block);
> > +
> > +/**
> > + * struct v4l2_params_handler - V4L2 extensible format handler
> > + * @size: the block expected size
> > + * @handler: the block handler function
> > + *
> > + * The v4l2_params_handler defines the type that driver making use of the
> > + * V4L2 extensible parameters shall use to define their own ISP block
> > + * handlers.
> > + *
> > + * Drivers shall prepare a list of handlers, one for each supported ISP block
> > + * and correctly populate the structure's field with the expected block @size
> > + * (used for validation) and a pointer to each block @handler function.
> > + */
> > +struct v4l2_params_handler {
> > + size_t size;
> > + v4l2_params_block_handler handler;
> > +};
> > +
> > +/**
> > + * v4l2_params_buffer_validate - Validate a V4L2 extensible parameters buffer
>
> As this is the pre-copy validation, what would you think of calling the
> function v4l2_isp_params_pre_validate_buffer() ? The next function would
> be called v4l2_isp_params_validate_buffer(), as they're both about
> buffer validation. I'm also OK to keep the current names (with a
> v4l2_isp_ prefix).
>
> I'm also thinking that the copy could be moved to the helper, but it can
> be done later.
>
> > + * @dev: the driver's device pointer
> > + * @vb: the videobuf2 buffer
> > + * @max_size: the maximum allowed buffer size
> > + * @buffer_validate: callback to the driver-specific buffer validation
>
> You forgot to drop the documentation for this argument.
>
> > + *
> > + * Helper function that performs validation of an extensible parameters buffer.
> > + *
> > + * The helper is meant to be used by drivers to perform validation of the
> > + * extensible parameters buffer size correctness.
> > + *
> > + * The @vb buffer as received from the vb2 .buf_prepare() operation is checked
> > + * against @max_size and its validated to be large enough to accommodate at
> > + * least one ISP configuration block. The effective buffer size is compared
> > + * with the reported data size to make sure they match.
> > + *
> > + * Drivers should use this function to validate the buffer size correctness
> > + * before performing a copy of the user-provided videobuf2 buffer content into a
> > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > + * content after it has been submitted to the driver.
> > + */
> > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > + size_t max_size);
> > +
> > +/**
> > + * v4l2_params_blocks_validate - Validate V4L2 extensible parameters ISP
> > + * configuration blocks
> > + * @dev: the driver's device pointer
> > + * @buffer: the extensible parameters configuration buffer
> > + * @handlers: the list of block handlers
>
> array of block handlers
>
> > + * @num_handlers: the number of block handlers
> > + *
> > + * Helper function that performs validation of the ISP configuration blocks in
> > + * an extensible parameters buffer.
> > + *
> > + * The helper is meant to be used by drivers to perform validation of the
> > + * ISP configuration data blocks. For each block in the extensible parameters
> > + * buffer, its size and correctness are validated against its associated handler
> > + * in the @handlers list.
>
> You need to explain somewhere that the handlers array is indexed by
> block type.
>
> > + *
> > + * Drivers should use this function to validate the ISP configuration blocks
> > + * after having validated the correctness of the vb2 buffer sizes by using the
> > + * v4l2_params_buffer_validate() helper first. Once the buffer size has been
> > + * validated, drivers should perform a copy of the user-provided buffer into a
> > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > + * content after it has been submitted to the driver, and then call this
> > + * function to perform per-block validation.
>
> There's room for improvement in the documentation. I think it would be
> clearer if you explained the big picture in
> Documentation/userspace-api/media/v4l/extensible-parameters.rst
My bad, that should be Documentation/driver-api/media/v4l2-isp.rst.
> (pre-validation, copy and post-validation), and only focussed on what
> those two functions do in their kerneldoc. That can be done later,
> nothing that you say here is incorrect.
>
> With the other comments addressed,
>
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>
> > + */
> > +int v4l2_params_blocks_validate(struct device *dev,
> > + const struct v4l2_params_buffer *buffer,
> > + const struct v4l2_params_handler *handlers,
> > + size_t num_handlers);
> > +
> > +#endif /* V4L2_PARAMS_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 4/8] media: Documentation: uapi: Add V4L2 extensible parameters
2025-09-15 17:18 ` [PATCH v5 4/8] media: Documentation: uapi: Add V4L2 extensible parameters Jacopo Mondi
@ 2025-10-06 1:17 ` Laurent Pinchart
0 siblings, 0 replies; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 1:17 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Jacopo,
Thank you for the patch.
On Mon, Sep 15, 2025 at 07:18:13PM +0200, Jacopo Mondi wrote:
> Add documentation for extensible parameters format to the V4L2
> userspace API documentation.
>
> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> .../media/v4l/extensible-parameters.rst | 97 ++++++++++++++++++++++
> .../userspace-api/media/v4l/meta-formats.rst | 1 +
> MAINTAINERS | 1 +
> 3 files changed, 99 insertions(+)
>
> diff --git a/Documentation/userspace-api/media/v4l/extensible-parameters.rst b/Documentation/userspace-api/media/v4l/extensible-parameters.rst
> new file mode 100644
> index 0000000000000000000000000000000000000000..e95c84f90c1b472360306d97c9b27123cd4bb6af
> --- /dev/null
> +++ b/Documentation/userspace-api/media/v4l/extensible-parameters.rst
> @@ -0,0 +1,97 @@
> +.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
> +
> +.. _extensible-parameters:
> +
> +*************************************
> +V4L2 extensible ISP parameters format
> +*************************************
> +
> +ISP configuration
> +=================
> +
> +ISP configuration parameters are computed by userspace and programmed into a
> +*parameters buffer* which is queued to the ISP driver on a per-frame basis. The
> +layout of the *parameters buffer* generally reflects the ISP peripheral
> +registers layout and is, for this reason, platform specific.
I wouldn't talk about registers here, you can keep this more generic:
The parameters buffer contains ISP-specific parameters, its layout is
therefore driver-specific.
Except that the goal of this API is to standardize the layout...
> +
> +The ISP configuration parameters are passed to the ISP driver through a metadata
> +output video node, using the :c:type:`v4l2_meta_format` interface. Each ISP
> +driver defines a metadata format that implements the configuration parameters
> +layout.
> +
> +Metadata output formats that describe ISP configuration parameters are most of
> +the time realized by implementing C structures that reflect the registers layout
> +and gets populated by userspace before queueing the buffer to the ISP. Each
> +C structure usually corresponds to one ISP *processing block*, with each block
> +implementing one of the ISP supported features.
> +
> +The uAPI/ABI problem
> +--------------------
> +
> +By upstreaming data types that describe the configuration parameters layout,
> +driver developers make them part of the Linux kernel ABI. As it sometimes
> +happens for most peripherals in Linux, ISP drivers development is often an
> +iterative process, where sometimes not all the hardware features are supported
> +in the first version that lands in the kernel, and some parts of the interface
> +have to later be modified for bug-fixes or improvements.
> +
> +If any later bug-fix/improvement requires changes to the metadata output format,
> +this is considered an ABI-breakage that is strictly forbidden by the Linux
> +kernel policies. For this reason, each new iteration of an ISP driver support
> +would require defining a new metadata output format, implying that drivers have
> +to be made ready to handle several different configuration formats.
> +
> +Support for generic ISP parameters buffer has been designed with the goal of
> +being:
> +
> +- Extensible: new features can be added later on without breaking the existing
> + interface
> +- Versioned: different versions of the format can be defined without
> + breaking the existing interface
All this sounds more like material for a commit message, although I
suppose some design rationale could make sense in the documentation.
> +
> +The extensible parameters format
> +================================
> +
> +Extensible configuration parameters formats are realized by a defining a single
> +C structure that contains a few control parameters and a binary buffer where
"control parameters" is confusing here.
> +userspace programs a variable number of *ISP configuration blocks* data.
> +
> +The generic :c:type:`v4l2_params_buffer` defines a base type that each driver
> +can use by properly sizing the data buffer array by providing a definition of
> +maximum supported parameters buffer size.
> +
> +Each *ISP configuration block* is identified by an header and contains the
s/an header/a header/
> +parameters for that specific block.
> +
> +The generic :c:type:`v4l2_params_block_header` defines a base type that each
> +driver can re-use as it is or extend appropriately.
I'm sorry, extend how ?
> +
> +Userspace applications are responsible for correctly populating the parameters
> +block header fields (type, flags and size) and the block-specific parameters.
> +
> +When userspace wants to configure and enable an ISP block it shall fully
> +populate the block configuration and set the V4L2_PARAMS_FL_BLOCK_ENABLE
> +bit in the flags field.
> +
> +When userspace simply wants to disable an ISP block the
> +V4L2_PARAMS_FL_BLOCK_DISABLE bit should be set in flags field. The driver
> +ignores the rest of the block configuration structure in this case.
The implementation accepts a header with no data in that case. That
should either be documented here, or not supported.
> +
> +If a new configuration of an ISP block has to be applied, userspace shall fully
> +populate the ISP block configuration and omit setting the
> +V4L2_PARAMS_FL_BLOCK_ENABLE and V4L2_PARAMS_FL_BLOCK_DISABLE bits in
> +the flags field.
> +
> +Setting both the V4L2_PARAMS_FL_BLOCK_ENABLE and V4L2_PARAMS_FL_BLOCK_DISABLE
> +bits in the flags field is not allowed and not accepted.
> +
> +Any further development that happens after the ISP driver has been merged in
> +Linux and which requires supporting new ISP features can be implemented by
> +adding new blocks definition without invalidating the existing ones. Similarly,
> +any change to the existing ISP configuration blocks can be handled by versioning
> +them, again without invalidating the existing ones.
That versioning is unrelated to the version field in the buffer header,
it would be implemented by defining a new block type. This should be
clarified here.
There's lots of room for improvement here, the documentation is very
hard to follow for someone who is not deeply familiar with the concepts
already. With the comments above addressed there won't be anything
fundamentally incorrect though, so this file could be rewritten later.
> +
> +V4L2 extensible parameters uAPI data types
> +==========================================
> +
> +.. kernel-doc:: include/uapi/linux/media/v4l2-isp.h
> diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst
> index 0de80328c36bf148051a19abe9e5241234ddfe5c..b900ed6af7bd9ad49baf7b5a9eef9423f8abfbcb 100644
> --- a/Documentation/userspace-api/media/v4l/meta-formats.rst
> +++ b/Documentation/userspace-api/media/v4l/meta-formats.rst
> @@ -12,6 +12,7 @@ These formats are used for the :ref:`metadata` interface only.
> .. toctree::
> :maxdepth: 1
>
> + extensible-parameters
> metafmt-c3-isp
> metafmt-d4xx
> metafmt-generic
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e82c3d0758d6033fe8fcd56ffde2c03c4319fd11..abba872cb63f1430a49a2afbace4b9f9958c3991 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -26414,6 +26414,7 @@ V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
> M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> L: linux-media@vger.kernel.org
> S: Maintained
> +F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
> F: include/uapi/linux/media/v4l2-isp.h
>
> VF610 NAND DRIVER
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 8/8] media: Documentation: kapi: Add v4l2 generic ISP support
2025-09-15 17:18 ` [PATCH v5 8/8] media: Documentation: kapi: Add v4l2 generic ISP support Jacopo Mondi
@ 2025-10-06 1:18 ` Laurent Pinchart
0 siblings, 0 replies; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 1:18 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Jacopo,
Thank you for the patch.
On Mon, Sep 15, 2025 at 07:18:17PM +0200, Jacopo Mondi wrote:
> Add to the driver-api documentation the v4l2-isp.h types and
> helpers documentation.
>
> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> Documentation/driver-api/media/v4l2-core.rst | 1 +
> Documentation/driver-api/media/v4l2-isp.rst | 37 ++++++++++++++++++++++++++++
> MAINTAINERS | 1 +
> 3 files changed, 39 insertions(+)
>
> diff --git a/Documentation/driver-api/media/v4l2-core.rst b/Documentation/driver-api/media/v4l2-core.rst
> index ad987c34ad2a8460bb95e97adc4d850d624e0b81..a5f5102c64cca57b57b54ab95882b26286fb27de 100644
> --- a/Documentation/driver-api/media/v4l2-core.rst
> +++ b/Documentation/driver-api/media/v4l2-core.rst
> @@ -27,3 +27,4 @@ Video4Linux devices
> v4l2-common
> v4l2-tveeprom
> v4l2-jpeg
> + v4l2-isp
At what point we should structure the documentation. At one point :-)
> diff --git a/Documentation/driver-api/media/v4l2-isp.rst b/Documentation/driver-api/media/v4l2-isp.rst
> new file mode 100644
> index 0000000000000000000000000000000000000000..d778aa799347bfd0a95bd6887dd944ddad0fe4d1
> --- /dev/null
> +++ b/Documentation/driver-api/media/v4l2-isp.rst
> @@ -0,0 +1,37 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +V4L2 generic ISP parameters and statistics support
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +ISP configuration parameters and statistics are processed and collected by
> +drivers and exchanged with userspace through data types that usually
> +reflect the ISP peripheral registers layout.
> +
> +Each ISP driver defines its own metadata format for parameters and statistics,
> +and exposing the registers layout in the format definition, part of the Linux
> +kernel uAPI/uABI interface, makes it really hard, if not impossible, to extend
> +the format in a backward compatible way to support new hardware blocks or
> +different revisions of the same peripheral IP.
> +
> +For these reasons Video4Linux2 defines generic types for ISP configuration
> +parameters and statistics with a set of associated helpers to support drivers
> +and users using generic types.
> +
> +Generic ISP configuration parameters
> +====================================
> +
> +Drivers can use the generic and extensible configuration parameters format by
> +re-using the types defined in the include/uapi/linux/media/v4l2-isp.h uAPI
> +header file.
> +
> +The uAPI header defines generic types which the driver is expected to re-use and
> +provide definitions for the types of supported ISP blocks, their control
> +flags and the expected maximum size of a buffer of parameters.
> +
> +When a driver receives a buffer of parameters from userspace it shall validate
> +it by using the helper functions and types available in include/media/v4l2-isp.h
> +before accessing the buffer to apply the parameters to the hardware registers.
> +
Same comments are for the UAPI, I think this will need a full rewrite later.
> +Generic ISP support driver documentation
> +========================================
> +.. kernel-doc:: include/media/v4l2-isp.h
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1..b0c5e6c2b21a5d5ebc63d2ae8b5c1b68fa912b33 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -26414,6 +26414,7 @@ V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
> M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> L: linux-media@vger.kernel.org
> S: Maintained
> +F: Documentation/driver-api/media/v4l2-isp.rst
> F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
> F: drivers/media/v4l2-core/v4l2-isp.c
> F: include/media/v4l2-isp.h
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-05 0:06 ` Laurent Pinchart
2025-10-06 0:07 ` Laurent Pinchart
@ 2025-10-06 8:15 ` Dan Scally
2025-10-06 8:27 ` Laurent Pinchart
1 sibling, 1 reply; 32+ messages in thread
From: Dan Scally @ 2025-10-06 8:15 UTC (permalink / raw)
To: Laurent Pinchart, Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Sakari Ailus, Antoine Bouyer, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel
Morning Laurent, Jacopo
On 05/10/2025 01:06, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
>> Introduce v4l2-isp.h in the Linux kernel uAPI.
>>
>> The header includes types for generic ISP configuration parameters
>> and will be extended in future with support for generic ISP statistics
>
> s/in future/in the future/
>
> (and you can reflow the commit message)
>
>> formats.
>>
>> Generic ISP parameters support is provided by introducing two new
>> types that represent an extensible and versioned buffer of ISP
>> configuration parameters.
>>
>> The v4l2_params_block_header structure represents the header to be
>> prepend to each ISP configuration block and the v4l2_params_buffer type
>> represents the base type for the configuration parameters buffer.
>
> The second part of the sentence describes the same structure as the next
> paragraph.
>
>> The v4l2_params_buffer represents the container for the ISP
>> configuration data block. The generic type is defined with a 0-sized
>> data member that the ISP driver implementations shall properly size
>> according to their capabilities.
>
> This will be easier to understand if you describe v4l2_params_buffer
> first.
>
> The commit message would benefit from being rewritten.
>
>> [Add v4l2_params_buffer_size()]
>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
>> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>> ---
>> MAINTAINERS | 6 +++
>> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
>> 2 files changed, 106 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
>> F: drivers/media/i2c/vd56g3.c
>> F: drivers/media/i2c/vgxy61.c
>>
>> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
>> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>> +L: linux-media@vger.kernel.org
>> +S: Maintained
>> +F: include/uapi/linux/media/v4l2-isp.h
>> +
>> VF610 NAND DRIVER
>> M: Stefan Agner <stefan@agner.ch>
>> L: linux-mtd@lists.infradead.org
>> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
>> --- /dev/null
>> +++ b/include/uapi/linux/media/v4l2-isp.h
>> @@ -0,0 +1,100 @@
>> +/* 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 <jacopo.mondi@ideasonboard.com>
>> + */
>> +
>> +#ifndef _UAPI_V4L2_ISP_H_
>> +#define _UAPI_V4L2_ISP_H_
>> +
>> +#include <linux/stddef.h>
>> +#include <linux/types.h>
>> +
>> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
>> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
>> +
>> +/*
>> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
>> + *
>> + * Driver-specific flags should be defined as:
>> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
>
> s/PLATFORM/DRIVER/
>
>> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
>> + */
>> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
>> +
>> +/**
>> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
>> + * driver inspects this common header to discern the block type and its size and
>> + * properly handle the block content.
>
> The last sentence is not relevant for the UAPI.
>
>> + *
>> + * 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_FL_* and
>> + * driver-specific flags specified by the driver 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
>
> I think the fields usually go right after the structure name, followed
> by the rest of the documentation.
>
>> + */
>> +struct v4l2_params_block_header {
>> + __u16 type;
>> + __u16 flags;
>> + __u32 size;
>> +} __attribute__((aligned(8)));
>> +
>> +/**
>> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
>> + *
>> + * Users of the v4l2 extensible parameters will have differing sized data arrays
>> + * depending on their specific parameter buffers. Drivers and userspace will
>> + * need to be able to calculate the appropriate size of the struct to
>> + * accommodate all ISP configuration blocks provided by the platform.
>> + * This macro provides a convenient tool for the calculation.
>> + *
>> + * @max_params_size: The total size of the ISP configuration blocks
>> + */
>> +#define v4l2_params_buffer_size(max_params_size) \
>> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
>
> This isn't used in this series as far as I can tell, and neither is it
> used in your libcamera implementation. I'd drop the macro (as well as
> the mention in the commit message).
This is because the rkisp1 and c3 ISP implementations are already merged with a custom parameters
buffer struct defined at [1] and [2]. There the array size is set to the max size macro. This series
just asserts that the header part is a size match for struct v4l2_params_buffer to guarantee
compatibility, so throughout those drivers they can use sizeof(struct c3_isp_params_cfg) or the
rkisp equivalent and it's fine.
For new users that don't have a custom struct in their uAPI and are relying on struct
v4l2_params_buffer we can't just do sizeof(), so the idea was for this to provide a canonical way
for the size calculation to be done across both the kernel and userspace.
If we decide that it's worth keeping but want a user in this series to justify its inclusion, it
could be used in patches 2 and 3 - I'll reply to patch 2 in a second to indicate where.
Thanks
Dan
[1] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/rkisp1-config.h#L1675
[2]
https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/media/amlogic/c3-isp-config.h#L558>
>> +
>> +/**
>> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
>> + *
>> + * This struct contains the configuration parameters of the ISP algorithms,
>
> s/struct/structure/
>
>> + * serialized by userspace into a data buffer. Each configuration parameter
>> + * block is represented by a block-specific structure which contains a
>> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
>
> I think you can drop "nor overlaps", nobody in their right mind should
> think the blocks could be overlayed :-)
>
>> + * the effective size, in bytes, of the @data buffer.
>> + *
>> + * @version: The parameters buffer version (driver-specific)
>> + * @data_size: The configuration data effective size, excluding this header
>> + * @data: The configuration data
>
> Move the fields up just after the structure name.
>
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>
>> + */
>> +struct v4l2_params_buffer {
>> + __u32 version;
>> + __u32 data_size;
>> + __u8 data[] __counted_by(data_size);
>> +};
>> +
>> +#endif /* _UAPI_V4L2_ISP_H_ */
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 2/8] media: uapi: Convert RkISP1 to V4L2 extensible params
2025-10-05 0:18 ` Laurent Pinchart
@ 2025-10-06 8:17 ` Dan Scally
0 siblings, 0 replies; 32+ messages in thread
From: Dan Scally @ 2025-10-06 8:17 UTC (permalink / raw)
To: Laurent Pinchart, Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Sakari Ailus, Antoine Bouyer, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel
Hi Laurent, Jacopo
On 05/10/2025 01:18, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Mon, Sep 15, 2025 at 07:18:11PM +0200, Jacopo Mondi wrote:
>> With the introduction of common types for extensible parameters
>> format, convert the rkisp1-config.h header to use the new types.
>>
>> Factor-out the documentation that is now part of the common header
>> and only keep the driver-specific on in place.
>>
>> The conversion to use common types doesn't impact userspace as the
>> new types are either identical to the ones already existing in the
>> RkISP1 uAPI or are 1-to-1 type convertible.
>>
>> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>
>> ---
>> include/uapi/linux/rkisp1-config.h | 104 ++++++++-----------------------------
>> 1 file changed, 22 insertions(+), 82 deletions(-)
>>
>> diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
>> index 3b060ea6eed71b87d79abc8401eae4e9c9f5323a..b90d94d3a852fb0af0fe447649487e9e80aca795 100644
>> --- a/include/uapi/linux/rkisp1-config.h
>> +++ b/include/uapi/linux/rkisp1-config.h
>> @@ -7,8 +7,13 @@
>> #ifndef _UAPI_RKISP1_CONFIG_H
>> #define _UAPI_RKISP1_CONFIG_H
>>
>> +#ifdef __KERNEL__
>> +#include <linux/build_bug.h>
>> +#endif /* __KERNEL__ */
>> #include <linux/types.h>
>>
>> +#include <linux/media/v4l2-isp.h>
>> +
>> /* Defect Pixel Cluster Detection */
>> #define RKISP1_CIF_ISP_MODULE_DPCC (1U << 0)
>> /* Black Level Subtraction */
>> @@ -1158,79 +1163,26 @@ enum rkisp1_ext_params_block_type {
>> RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR,
>> };
>>
>> -#define RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE (1U << 0)
>> -#define RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE (1U << 1)
>> +/* For backward compatibility */
>> +#define RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE V4L2_PARAMS_FL_BLOCK_DISABLE
>> +#define RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE V4L2_PARAMS_FL_BLOCK_ENABLE
>>
>> /* A bitmask of parameters blocks supported on the current hardware. */
>> #define RKISP1_CID_SUPPORTED_PARAMS_BLOCKS (V4L2_CID_USER_RKISP1_BASE + 0x01)
>>
>> /**
>> - * struct rkisp1_ext_params_block_header - RkISP1 extensible parameters block
>> - * header
>> + * rkisp1_ext_params_block_header - RkISP1 extensible parameters block 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
>> - * 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.
>> + * blocks and is identical to :c:type:`v4l2_params_block_header`.
>> *
>> - * The @type field is one of the values enumerated by
>> + * The type field is one of the values enumerated by
>> * :c:type:`rkisp1_ext_params_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 is a bitmask of per-block flags RKISP1_EXT_PARAMS_FL_*.
>> - *
>> - * When userspace wants to configure and enable an ISP block it shall fully
>> - * populate the block configuration and set the
>> - * RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE bit in the @flags field.
>> - *
>> - * When userspace simply wants to disable an ISP block the
>> - * RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bit should be set in @flags field. The
>> - * driver ignores the rest of the block configuration structure in this case.
>> - *
>> - * If a new configuration of an ISP block has to be applied userspace shall
>> - * fully populate the ISP block configuration and omit setting the
>> - * RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE and RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bits
>> - * in the @flags field.
>> - *
>> - * Setting both the RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE and
>> - * RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE bits in the @flags field is not allowed
>> - * and not accepted by the driver.
>> - *
>> - * Userspace is responsible for correctly populating the parameters block header
>> - * fields (@type, @flags and @size) and the block-specific parameters.
>> - *
>> - * For example:
>> + * interpreted by the driver.
>> *
>> - * .. code-block:: c
>> - *
>> - * void populate_bls(struct rkisp1_ext_params_block_header *block) {
>> - * struct rkisp1_ext_params_bls_config *bls =
>> - * (struct rkisp1_ext_params_bls_config *)block;
>> - *
>> - * bls->header.type = RKISP1_EXT_PARAMS_BLOCK_ID_BLS;
>> - * bls->header.flags = RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE;
>> - * bls->header.size = sizeof(*bls);
>> - *
>> - * bls->config.enable_auto = 0;
>> - * bls->config.fixed_val.r = blackLevelRed_;
>> - * bls->config.fixed_val.gr = blackLevelGreenR_;
>> - * bls->config.fixed_val.gb = blackLevelGreenB_;
>> - * bls->config.fixed_val.b = blackLevelBlue_;
>> - * }
>> - *
>> - * @type: The parameters block type, see
>> - * :c:type:`rkisp1_ext_params_block_type`
>> - * @flags: A bitmask of block flags
>> - * @size: Size (in bytes) of the parameters block, including this header
>> + * The flags field is a bitmask of per-block flags RKISP1_EXT_PARAMS_FL_*.
>> */
>> -struct rkisp1_ext_params_block_header {
>> - __u16 type;
>> - __u16 flags;
>> - __u32 size;
>> -};
>> +#define rkisp1_ext_params_block_header v4l2_params_block_header
>>
>> /**
>> * struct rkisp1_ext_params_bls_config - RkISP1 extensible params BLS config
>> @@ -1594,21 +1546,7 @@ enum rksip1_ext_param_buffer_version {
>> /**
>> * struct rkisp1_ext_params_cfg - RkISP1 extensible parameters configuration
>> *
>> - * This struct contains the configuration parameters of the RkISP1 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:`rkisp1_ext_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.
>> + * This is the driver-specific implementation of :c:type:`v4l2_params_buffer`.
>> *
>> * Currently the single RKISP1_EXT_PARAM_BUFFER_V1 version is supported.
>> * When a new format version will be added, a mechanism for userspace to query
>> @@ -1624,11 +1562,6 @@ enum rksip1_ext_param_buffer_version {
>> * the maximum value represents the blocks supported by the kernel driver,
>> * independently of the device instance.
>> *
>> - * 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 @data_size field with
>> - * the effective size, in bytes, of the @data buffer.
>> - *
>> * The expected memory layout of the parameters buffer is::
>> *
>> * +-------------------- struct rkisp1_ext_params_cfg -------------------+
>> @@ -1678,4 +1611,11 @@ struct rkisp1_ext_params_cfg {
>> __u8 data[RKISP1_EXT_PARAMS_MAX_SIZE];
>> };
>>
>> +#ifdef __KERNEL__
>> +/* Make sure the header is type-convertible to the generic v4l2 params one */
>> +static_assert((sizeof(struct rkisp1_ext_params_cfg) -
>> + RKISP1_EXT_PARAMS_MAX_SIZE) ==
>> + sizeof(struct v4l2_params_buffer));
>> +#endif /* __KERNEL__ */
This is where I was thinking v4l2_params_buffer_size could be used:
static assert(sizeof(struct rkisp1_ext_params_cfg) ==
v4l2_params_buffer_size(RKISP1_EXT_PARAMS_MAX_SIZE))
Dan
>> +
>> #endif /* _UAPI_RKISP1_CONFIG_H */
>>
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-06 8:15 ` Dan Scally
@ 2025-10-06 8:27 ` Laurent Pinchart
2025-10-06 8:46 ` Dan Scally
0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 8:27 UTC (permalink / raw)
To: Dan Scally
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On Mon, Oct 06, 2025 at 09:15:47AM +0100, Daniel Scally wrote:
> On 05/10/2025 01:06, Laurent Pinchart wrote:
> > On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
> >> Introduce v4l2-isp.h in the Linux kernel uAPI.
> >>
> >> The header includes types for generic ISP configuration parameters
> >> and will be extended in future with support for generic ISP statistics
> >
> > s/in future/in the future/
> >
> > (and you can reflow the commit message)
> >
> >> formats.
> >>
> >> Generic ISP parameters support is provided by introducing two new
> >> types that represent an extensible and versioned buffer of ISP
> >> configuration parameters.
> >>
> >> The v4l2_params_block_header structure represents the header to be
> >> prepend to each ISP configuration block and the v4l2_params_buffer type
> >> represents the base type for the configuration parameters buffer.
> >
> > The second part of the sentence describes the same structure as the next
> > paragraph.
> >
> >> The v4l2_params_buffer represents the container for the ISP
> >> configuration data block. The generic type is defined with a 0-sized
> >> data member that the ISP driver implementations shall properly size
> >> according to their capabilities.
> >
> > This will be easier to understand if you describe v4l2_params_buffer
> > first.
> >
> > The commit message would benefit from being rewritten.
> >
> >> [Add v4l2_params_buffer_size()]
> >> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> >> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> >> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >> ---
> >> MAINTAINERS | 6 +++
> >> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
> >> 2 files changed, 106 insertions(+)
> >>
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
> >> F: drivers/media/i2c/vd56g3.c
> >> F: drivers/media/i2c/vgxy61.c
> >>
> >> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
> >> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >> +L: linux-media@vger.kernel.org
> >> +S: Maintained
> >> +F: include/uapi/linux/media/v4l2-isp.h
> >> +
> >> VF610 NAND DRIVER
> >> M: Stefan Agner <stefan@agner.ch>
> >> L: linux-mtd@lists.infradead.org
> >> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
> >> new file mode 100644
> >> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
> >> --- /dev/null
> >> +++ b/include/uapi/linux/media/v4l2-isp.h
> >> @@ -0,0 +1,100 @@
> >> +/* 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 <jacopo.mondi@ideasonboard.com>
> >> + */
> >> +
> >> +#ifndef _UAPI_V4L2_ISP_H_
> >> +#define _UAPI_V4L2_ISP_H_
> >> +
> >> +#include <linux/stddef.h>
> >> +#include <linux/types.h>
> >> +
> >> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
> >> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
> >> +
> >> +/*
> >> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
> >> + *
> >> + * Driver-specific flags should be defined as:
> >> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
> >
> > s/PLATFORM/DRIVER/
> >
> >> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
> >> + */
> >> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
> >> +
> >> +/**
> >> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
> >> + * driver inspects this common header to discern the block type and its size and
> >> + * properly handle the block content.
> >
> > The last sentence is not relevant for the UAPI.
> >
> >> + *
> >> + * 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_FL_* and
> >> + * driver-specific flags specified by the driver 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
> >
> > I think the fields usually go right after the structure name, followed
> > by the rest of the documentation.
> >
> >> + */
> >> +struct v4l2_params_block_header {
> >> + __u16 type;
> >> + __u16 flags;
> >> + __u32 size;
> >> +} __attribute__((aligned(8)));
> >> +
> >> +/**
> >> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
> >> + *
> >> + * Users of the v4l2 extensible parameters will have differing sized data arrays
> >> + * depending on their specific parameter buffers. Drivers and userspace will
> >> + * need to be able to calculate the appropriate size of the struct to
> >> + * accommodate all ISP configuration blocks provided by the platform.
> >> + * This macro provides a convenient tool for the calculation.
> >> + *
> >> + * @max_params_size: The total size of the ISP configuration blocks
> >> + */
> >> +#define v4l2_params_buffer_size(max_params_size) \
> >> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
> >
> > This isn't used in this series as far as I can tell, and neither is it
> > used in your libcamera implementation. I'd drop the macro (as well as
> > the mention in the commit message).
>
> This is because the rkisp1 and c3 ISP implementations are already merged with a custom parameters
> buffer struct defined at [1] and [2]. There the array size is set to the max size macro. This series
> just asserts that the header part is a size match for struct v4l2_params_buffer to guarantee
> compatibility, so throughout those drivers they can use sizeof(struct c3_isp_params_cfg) or the
> rkisp equivalent and it's fine.
>
> For new users that don't have a custom struct in their uAPI and are relying on struct
> v4l2_params_buffer we can't just do sizeof(), so the idea was for this to provide a canonical way
> for the size calculation to be done across both the kernel and userspace.
>
> If we decide that it's worth keeping but want a user in this series to justify its inclusion, it
> could be used in patches 2 and 3 - I'll reply to patch 2 in a second to indicate where.
Will it be used by userspace too for the Mali C55, or only by the kernel
driver ?
> [1] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/rkisp1-config.h#L1675
> [2] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/media/amlogic/c3-isp-config.h#L558>
>
> >> +
> >> +/**
> >> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
> >> + *
> >> + * This struct contains the configuration parameters of the ISP algorithms,
> >
> > s/struct/structure/
> >
> >> + * serialized by userspace into a data buffer. Each configuration parameter
> >> + * block is represented by a block-specific structure which contains a
> >> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
> >
> > I think you can drop "nor overlaps", nobody in their right mind should
> > think the blocks could be overlayed :-)
> >
> >> + * the effective size, in bytes, of the @data buffer.
> >> + *
> >> + * @version: The parameters buffer version (driver-specific)
> >> + * @data_size: The configuration data effective size, excluding this header
> >> + * @data: The configuration data
> >
> > Move the fields up just after the structure name.
> >
> > Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> >
> >> + */
> >> +struct v4l2_params_buffer {
> >> + __u32 version;
> >> + __u32 data_size;
> >> + __u8 data[] __counted_by(data_size);
> >> +};
> >> +
> >> +#endif /* _UAPI_V4L2_ISP_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-06 8:27 ` Laurent Pinchart
@ 2025-10-06 8:46 ` Dan Scally
2025-10-06 9:06 ` Laurent Pinchart
0 siblings, 1 reply; 32+ messages in thread
From: Dan Scally @ 2025-10-06 8:46 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On 06/10/2025 09:27, Laurent Pinchart wrote:
> On Mon, Oct 06, 2025 at 09:15:47AM +0100, Daniel Scally wrote:
>> On 05/10/2025 01:06, Laurent Pinchart wrote:
>>> On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
>>>> Introduce v4l2-isp.h in the Linux kernel uAPI.
>>>>
>>>> The header includes types for generic ISP configuration parameters
>>>> and will be extended in future with support for generic ISP statistics
>>>
>>> s/in future/in the future/
>>>
>>> (and you can reflow the commit message)
>>>
>>>> formats.
>>>>
>>>> Generic ISP parameters support is provided by introducing two new
>>>> types that represent an extensible and versioned buffer of ISP
>>>> configuration parameters.
>>>>
>>>> The v4l2_params_block_header structure represents the header to be
>>>> prepend to each ISP configuration block and the v4l2_params_buffer type
>>>> represents the base type for the configuration parameters buffer.
>>>
>>> The second part of the sentence describes the same structure as the next
>>> paragraph.
>>>
>>>> The v4l2_params_buffer represents the container for the ISP
>>>> configuration data block. The generic type is defined with a 0-sized
>>>> data member that the ISP driver implementations shall properly size
>>>> according to their capabilities.
>>>
>>> This will be easier to understand if you describe v4l2_params_buffer
>>> first.
>>>
>>> The commit message would benefit from being rewritten.
>>>
>>>> [Add v4l2_params_buffer_size()]
>>>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
>>>> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
>>>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>>> ---
>>>> MAINTAINERS | 6 +++
>>>> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
>>>> 2 files changed, 106 insertions(+)
>>>>
>>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>>> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
>>>> --- a/MAINTAINERS
>>>> +++ b/MAINTAINERS
>>>> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
>>>> F: drivers/media/i2c/vd56g3.c
>>>> F: drivers/media/i2c/vgxy61.c
>>>>
>>>> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
>>>> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>>> +L: linux-media@vger.kernel.org
>>>> +S: Maintained
>>>> +F: include/uapi/linux/media/v4l2-isp.h
>>>> +
>>>> VF610 NAND DRIVER
>>>> M: Stefan Agner <stefan@agner.ch>
>>>> L: linux-mtd@lists.infradead.org
>>>> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
>>>> new file mode 100644
>>>> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
>>>> --- /dev/null
>>>> +++ b/include/uapi/linux/media/v4l2-isp.h
>>>> @@ -0,0 +1,100 @@
>>>> +/* 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 <jacopo.mondi@ideasonboard.com>
>>>> + */
>>>> +
>>>> +#ifndef _UAPI_V4L2_ISP_H_
>>>> +#define _UAPI_V4L2_ISP_H_
>>>> +
>>>> +#include <linux/stddef.h>
>>>> +#include <linux/types.h>
>>>> +
>>>> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
>>>> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
>>>> +
>>>> +/*
>>>> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
>>>> + *
>>>> + * Driver-specific flags should be defined as:
>>>> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
>>>
>>> s/PLATFORM/DRIVER/
>>>
>>>> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
>>>> + */
>>>> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
>>>> +
>>>> +/**
>>>> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
>>>> + * driver inspects this common header to discern the block type and its size and
>>>> + * properly handle the block content.
>>>
>>> The last sentence is not relevant for the UAPI.
>>>
>>>> + *
>>>> + * 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_FL_* and
>>>> + * driver-specific flags specified by the driver 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
>>>
>>> I think the fields usually go right after the structure name, followed
>>> by the rest of the documentation.
>>>
>>>> + */
>>>> +struct v4l2_params_block_header {
>>>> + __u16 type;
>>>> + __u16 flags;
>>>> + __u32 size;
>>>> +} __attribute__((aligned(8)));
>>>> +
>>>> +/**
>>>> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
>>>> + *
>>>> + * Users of the v4l2 extensible parameters will have differing sized data arrays
>>>> + * depending on their specific parameter buffers. Drivers and userspace will
>>>> + * need to be able to calculate the appropriate size of the struct to
>>>> + * accommodate all ISP configuration blocks provided by the platform.
>>>> + * This macro provides a convenient tool for the calculation.
>>>> + *
>>>> + * @max_params_size: The total size of the ISP configuration blocks
>>>> + */
>>>> +#define v4l2_params_buffer_size(max_params_size) \
>>>> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
>>>
>>> This isn't used in this series as far as I can tell, and neither is it
>>> used in your libcamera implementation. I'd drop the macro (as well as
>>> the mention in the commit message).
>>
>> This is because the rkisp1 and c3 ISP implementations are already merged with a custom parameters
>> buffer struct defined at [1] and [2]. There the array size is set to the max size macro. This series
>> just asserts that the header part is a size match for struct v4l2_params_buffer to guarantee
>> compatibility, so throughout those drivers they can use sizeof(struct c3_isp_params_cfg) or the
>> rkisp equivalent and it's fine.
>>
>> For new users that don't have a custom struct in their uAPI and are relying on struct
>> v4l2_params_buffer we can't just do sizeof(), so the idea was for this to provide a canonical way
>> for the size calculation to be done across both the kernel and userspace.
>>
>> If we decide that it's worth keeping but want a user in this series to justify its inclusion, it
>> could be used in patches 2 and 3 - I'll reply to patch 2 in a second to indicate where.
>
> Will it be used by userspace too for the Mali C55, or only by the kernel
I have used it in userspace too.
Thanks
Dan
> driver ?
>
>> [1] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/rkisp1-config.h#L1675
>> [2] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/media/amlogic/c3-isp-config.h#L558>
>>
>>>> +
>>>> +/**
>>>> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
>>>> + *
>>>> + * This struct contains the configuration parameters of the ISP algorithms,
>>>
>>> s/struct/structure/
>>>
>>>> + * serialized by userspace into a data buffer. Each configuration parameter
>>>> + * block is represented by a block-specific structure which contains a
>>>> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
>>>
>>> I think you can drop "nor overlaps", nobody in their right mind should
>>> think the blocks could be overlayed :-)
>>>
>>>> + * the effective size, in bytes, of the @data buffer.
>>>> + *
>>>> + * @version: The parameters buffer version (driver-specific)
>>>> + * @data_size: The configuration data effective size, excluding this header
>>>> + * @data: The configuration data
>>>
>>> Move the fields up just after the structure name.
>>>
>>> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>>>
>>>> + */
>>>> +struct v4l2_params_buffer {
>>>> + __u32 version;
>>>> + __u32 data_size;
>>>> + __u8 data[] __counted_by(data_size);
>>>> +};
>>>> +
>>>> +#endif /* _UAPI_V4L2_ISP_H_ */
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-06 8:46 ` Dan Scally
@ 2025-10-06 9:06 ` Laurent Pinchart
2025-10-06 9:51 ` Dan Scally
0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 9:06 UTC (permalink / raw)
To: Dan Scally
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On Mon, Oct 06, 2025 at 09:46:26AM +0100, Daniel Scally wrote:
> On 06/10/2025 09:27, Laurent Pinchart wrote:
> > On Mon, Oct 06, 2025 at 09:15:47AM +0100, Daniel Scally wrote:
> >> On 05/10/2025 01:06, Laurent Pinchart wrote:
> >>> On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
> >>>> Introduce v4l2-isp.h in the Linux kernel uAPI.
> >>>>
> >>>> The header includes types for generic ISP configuration parameters
> >>>> and will be extended in future with support for generic ISP statistics
> >>>
> >>> s/in future/in the future/
> >>>
> >>> (and you can reflow the commit message)
> >>>
> >>>> formats.
> >>>>
> >>>> Generic ISP parameters support is provided by introducing two new
> >>>> types that represent an extensible and versioned buffer of ISP
> >>>> configuration parameters.
> >>>>
> >>>> The v4l2_params_block_header structure represents the header to be
> >>>> prepend to each ISP configuration block and the v4l2_params_buffer type
> >>>> represents the base type for the configuration parameters buffer.
> >>>
> >>> The second part of the sentence describes the same structure as the next
> >>> paragraph.
> >>>
> >>>> The v4l2_params_buffer represents the container for the ISP
> >>>> configuration data block. The generic type is defined with a 0-sized
> >>>> data member that the ISP driver implementations shall properly size
> >>>> according to their capabilities.
> >>>
> >>> This will be easier to understand if you describe v4l2_params_buffer
> >>> first.
> >>>
> >>> The commit message would benefit from being rewritten.
> >>>
> >>>> [Add v4l2_params_buffer_size()]
> >>>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> >>>> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> >>>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >>>> ---
> >>>> MAINTAINERS | 6 +++
> >>>> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
> >>>> 2 files changed, 106 insertions(+)
> >>>>
> >>>> diff --git a/MAINTAINERS b/MAINTAINERS
> >>>> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
> >>>> --- a/MAINTAINERS
> >>>> +++ b/MAINTAINERS
> >>>> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
> >>>> F: drivers/media/i2c/vd56g3.c
> >>>> F: drivers/media/i2c/vgxy61.c
> >>>>
> >>>> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
> >>>> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >>>> +L: linux-media@vger.kernel.org
> >>>> +S: Maintained
> >>>> +F: include/uapi/linux/media/v4l2-isp.h
> >>>> +
> >>>> VF610 NAND DRIVER
> >>>> M: Stefan Agner <stefan@agner.ch>
> >>>> L: linux-mtd@lists.infradead.org
> >>>> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
> >>>> new file mode 100644
> >>>> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
> >>>> --- /dev/null
> >>>> +++ b/include/uapi/linux/media/v4l2-isp.h
> >>>> @@ -0,0 +1,100 @@
> >>>> +/* 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 <jacopo.mondi@ideasonboard.com>
> >>>> + */
> >>>> +
> >>>> +#ifndef _UAPI_V4L2_ISP_H_
> >>>> +#define _UAPI_V4L2_ISP_H_
> >>>> +
> >>>> +#include <linux/stddef.h>
> >>>> +#include <linux/types.h>
> >>>> +
> >>>> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
> >>>> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
> >>>> +
> >>>> +/*
> >>>> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
> >>>> + *
> >>>> + * Driver-specific flags should be defined as:
> >>>> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
> >>>
> >>> s/PLATFORM/DRIVER/
> >>>
> >>>> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
> >>>> + */
> >>>> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
> >>>> +
> >>>> +/**
> >>>> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
> >>>> + * driver inspects this common header to discern the block type and its size and
> >>>> + * properly handle the block content.
> >>>
> >>> The last sentence is not relevant for the UAPI.
> >>>
> >>>> + *
> >>>> + * 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_FL_* and
> >>>> + * driver-specific flags specified by the driver 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
> >>>
> >>> I think the fields usually go right after the structure name, followed
> >>> by the rest of the documentation.
> >>>
> >>>> + */
> >>>> +struct v4l2_params_block_header {
> >>>> + __u16 type;
> >>>> + __u16 flags;
> >>>> + __u32 size;
> >>>> +} __attribute__((aligned(8)));
> >>>> +
> >>>> +/**
> >>>> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
> >>>> + *
> >>>> + * Users of the v4l2 extensible parameters will have differing sized data arrays
> >>>> + * depending on their specific parameter buffers. Drivers and userspace will
> >>>> + * need to be able to calculate the appropriate size of the struct to
> >>>> + * accommodate all ISP configuration blocks provided by the platform.
> >>>> + * This macro provides a convenient tool for the calculation.
> >>>> + *
> >>>> + * @max_params_size: The total size of the ISP configuration blocks
> >>>> + */
> >>>> +#define v4l2_params_buffer_size(max_params_size) \
> >>>> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
> >>>
> >>> This isn't used in this series as far as I can tell, and neither is it
> >>> used in your libcamera implementation. I'd drop the macro (as well as
> >>> the mention in the commit message).
> >>
> >> This is because the rkisp1 and c3 ISP implementations are already merged with a custom parameters
> >> buffer struct defined at [1] and [2]. There the array size is set to the max size macro. This series
> >> just asserts that the header part is a size match for struct v4l2_params_buffer to guarantee
> >> compatibility, so throughout those drivers they can use sizeof(struct c3_isp_params_cfg) or the
> >> rkisp equivalent and it's fine.
> >>
> >> For new users that don't have a custom struct in their uAPI and are relying on struct
> >> v4l2_params_buffer we can't just do sizeof(), so the idea was for this to provide a canonical way
> >> for the size calculation to be done across both the kernel and userspace.
> >>
> >> If we decide that it's worth keeping but want a user in this series to justify its inclusion, it
> >> could be used in patches 2 and 3 - I'll reply to patch 2 in a second to indicate where.
> >
> > Will it be used by userspace too for the Mali C55, or only by the kernel
>
> I have used it in userspace too.
Any pointer to the code ?
> > driver ?
> >
> >> [1] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/rkisp1-config.h#L1675
> >> [2] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/media/amlogic/c3-isp-config.h#L558>
> >>
> >>>> +
> >>>> +/**
> >>>> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
> >>>> + *
> >>>> + * This struct contains the configuration parameters of the ISP algorithms,
> >>>
> >>> s/struct/structure/
> >>>
> >>>> + * serialized by userspace into a data buffer. Each configuration parameter
> >>>> + * block is represented by a block-specific structure which contains a
> >>>> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
> >>>
> >>> I think you can drop "nor overlaps", nobody in their right mind should
> >>> think the blocks could be overlayed :-)
> >>>
> >>>> + * the effective size, in bytes, of the @data buffer.
> >>>> + *
> >>>> + * @version: The parameters buffer version (driver-specific)
> >>>> + * @data_size: The configuration data effective size, excluding this header
> >>>> + * @data: The configuration data
> >>>
> >>> Move the fields up just after the structure name.
> >>>
> >>> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> >>>
> >>>> + */
> >>>> +struct v4l2_params_buffer {
> >>>> + __u32 version;
> >>>> + __u32 data_size;
> >>>> + __u8 data[] __counted_by(data_size);
> >>>> +};
> >>>> +
> >>>> +#endif /* _UAPI_V4L2_ISP_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-06 9:06 ` Laurent Pinchart
@ 2025-10-06 9:51 ` Dan Scally
2025-10-06 9:58 ` Laurent Pinchart
0 siblings, 1 reply; 32+ messages in thread
From: Dan Scally @ 2025-10-06 9:51 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Laurent
On 06/10/2025 10:06, Laurent Pinchart wrote:
> On Mon, Oct 06, 2025 at 09:46:26AM +0100, Daniel Scally wrote:
>> On 06/10/2025 09:27, Laurent Pinchart wrote:
>>> On Mon, Oct 06, 2025 at 09:15:47AM +0100, Daniel Scally wrote:
>>>> On 05/10/2025 01:06, Laurent Pinchart wrote:
>>>>> On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
>>>>>> Introduce v4l2-isp.h in the Linux kernel uAPI.
>>>>>>
>>>>>> The header includes types for generic ISP configuration parameters
>>>>>> and will be extended in future with support for generic ISP statistics
>>>>>
>>>>> s/in future/in the future/
>>>>>
>>>>> (and you can reflow the commit message)
>>>>>
>>>>>> formats.
>>>>>>
>>>>>> Generic ISP parameters support is provided by introducing two new
>>>>>> types that represent an extensible and versioned buffer of ISP
>>>>>> configuration parameters.
>>>>>>
>>>>>> The v4l2_params_block_header structure represents the header to be
>>>>>> prepend to each ISP configuration block and the v4l2_params_buffer type
>>>>>> represents the base type for the configuration parameters buffer.
>>>>>
>>>>> The second part of the sentence describes the same structure as the next
>>>>> paragraph.
>>>>>
>>>>>> The v4l2_params_buffer represents the container for the ISP
>>>>>> configuration data block. The generic type is defined with a 0-sized
>>>>>> data member that the ISP driver implementations shall properly size
>>>>>> according to their capabilities.
>>>>>
>>>>> This will be easier to understand if you describe v4l2_params_buffer
>>>>> first.
>>>>>
>>>>> The commit message would benefit from being rewritten.
>>>>>
>>>>>> [Add v4l2_params_buffer_size()]
>>>>>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
>>>>>> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
>>>>>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>>>>> ---
>>>>>> MAINTAINERS | 6 +++
>>>>>> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
>>>>>> 2 files changed, 106 insertions(+)
>>>>>>
>>>>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>>>>> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
>>>>>> --- a/MAINTAINERS
>>>>>> +++ b/MAINTAINERS
>>>>>> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
>>>>>> F: drivers/media/i2c/vd56g3.c
>>>>>> F: drivers/media/i2c/vgxy61.c
>>>>>>
>>>>>> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
>>>>>> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>>>>> +L: linux-media@vger.kernel.org
>>>>>> +S: Maintained
>>>>>> +F: include/uapi/linux/media/v4l2-isp.h
>>>>>> +
>>>>>> VF610 NAND DRIVER
>>>>>> M: Stefan Agner <stefan@agner.ch>
>>>>>> L: linux-mtd@lists.infradead.org
>>>>>> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
>>>>>> new file mode 100644
>>>>>> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
>>>>>> --- /dev/null
>>>>>> +++ b/include/uapi/linux/media/v4l2-isp.h
>>>>>> @@ -0,0 +1,100 @@
>>>>>> +/* 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 <jacopo.mondi@ideasonboard.com>
>>>>>> + */
>>>>>> +
>>>>>> +#ifndef _UAPI_V4L2_ISP_H_
>>>>>> +#define _UAPI_V4L2_ISP_H_
>>>>>> +
>>>>>> +#include <linux/stddef.h>
>>>>>> +#include <linux/types.h>
>>>>>> +
>>>>>> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
>>>>>> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
>>>>>> +
>>>>>> +/*
>>>>>> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
>>>>>> + *
>>>>>> + * Driver-specific flags should be defined as:
>>>>>> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
>>>>>
>>>>> s/PLATFORM/DRIVER/
>>>>>
>>>>>> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
>>>>>> + */
>>>>>> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
>>>>>> +
>>>>>> +/**
>>>>>> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
>>>>>> + * driver inspects this common header to discern the block type and its size and
>>>>>> + * properly handle the block content.
>>>>>
>>>>> The last sentence is not relevant for the UAPI.
>>>>>
>>>>>> + *
>>>>>> + * 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_FL_* and
>>>>>> + * driver-specific flags specified by the driver 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
>>>>>
>>>>> I think the fields usually go right after the structure name, followed
>>>>> by the rest of the documentation.
>>>>>
>>>>>> + */
>>>>>> +struct v4l2_params_block_header {
>>>>>> + __u16 type;
>>>>>> + __u16 flags;
>>>>>> + __u32 size;
>>>>>> +} __attribute__((aligned(8)));
>>>>>> +
>>>>>> +/**
>>>>>> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
>>>>>> + *
>>>>>> + * Users of the v4l2 extensible parameters will have differing sized data arrays
>>>>>> + * depending on their specific parameter buffers. Drivers and userspace will
>>>>>> + * need to be able to calculate the appropriate size of the struct to
>>>>>> + * accommodate all ISP configuration blocks provided by the platform.
>>>>>> + * This macro provides a convenient tool for the calculation.
>>>>>> + *
>>>>>> + * @max_params_size: The total size of the ISP configuration blocks
>>>>>> + */
>>>>>> +#define v4l2_params_buffer_size(max_params_size) \
>>>>>> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
>>>>>
>>>>> This isn't used in this series as far as I can tell, and neither is it
>>>>> used in your libcamera implementation. I'd drop the macro (as well as
>>>>> the mention in the commit message).
>>>>
>>>> This is because the rkisp1 and c3 ISP implementations are already merged with a custom parameters
>>>> buffer struct defined at [1] and [2]. There the array size is set to the max size macro. This series
>>>> just asserts that the header part is a size match for struct v4l2_params_buffer to guarantee
>>>> compatibility, so throughout those drivers they can use sizeof(struct c3_isp_params_cfg) or the
>>>> rkisp equivalent and it's fine.
>>>>
>>>> For new users that don't have a custom struct in their uAPI and are relying on struct
>>>> v4l2_params_buffer we can't just do sizeof(), so the idea was for this to provide a canonical way
>>>> for the size calculation to be done across both the kernel and userspace.
>>>>
>>>> If we decide that it's worth keeping but want a user in this series to justify its inclusion, it
>>>> could be used in patches 2 and 3 - I'll reply to patch 2 in a second to indicate where.
>>>
>>> Will it be used by userspace too for the Mali C55, or only by the kernel
>>
>> I have used it in userspace too.
>
> Any pointer to the code ?
I didn't post my commits to adapt the mali-c55 IPA to the extensible parameters, but it's basically
the same as Jacopo's patch here:
https://lists.libcamera.org/pipermail/libcamera-devel/2025-October/053567.html
And the change I made using the macro was in IPAMaliC55::fillParams():
- memset(params, 0, sizeof(mali_c55_params_buffer));
+ memset(params, 0, v4l2_params_buffer_size(MALI_C55_PARAMS_MAX_SIZE));
Dan
>
>>> driver ?
>>>
>>>> [1] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/rkisp1-config.h#L1675
>>>> [2] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/media/amlogic/c3-isp-config.h#L558>
>>>>
>>>>>> +
>>>>>> +/**
>>>>>> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
>>>>>> + *
>>>>>> + * This struct contains the configuration parameters of the ISP algorithms,
>>>>>
>>>>> s/struct/structure/
>>>>>
>>>>>> + * serialized by userspace into a data buffer. Each configuration parameter
>>>>>> + * block is represented by a block-specific structure which contains a
>>>>>> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
>>>>>
>>>>> I think you can drop "nor overlaps", nobody in their right mind should
>>>>> think the blocks could be overlayed :-)
>>>>>
>>>>>> + * the effective size, in bytes, of the @data buffer.
>>>>>> + *
>>>>>> + * @version: The parameters buffer version (driver-specific)
>>>>>> + * @data_size: The configuration data effective size, excluding this header
>>>>>> + * @data: The configuration data
>>>>>
>>>>> Move the fields up just after the structure name.
>>>>>
>>>>> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>>>>>
>>>>>> + */
>>>>>> +struct v4l2_params_buffer {
>>>>>> + __u32 version;
>>>>>> + __u32 data_size;
>>>>>> + __u8 data[] __counted_by(data_size);
>>>>>> +};
>>>>>> +
>>>>>> +#endif /* _UAPI_V4L2_ISP_H_ */
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-06 9:51 ` Dan Scally
@ 2025-10-06 9:58 ` Laurent Pinchart
2025-10-06 10:26 ` Dan Scally
0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 9:58 UTC (permalink / raw)
To: Dan Scally
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On Mon, Oct 06, 2025 at 10:51:33AM +0100, Daniel Scally wrote:
> On 06/10/2025 10:06, Laurent Pinchart wrote:
> > On Mon, Oct 06, 2025 at 09:46:26AM +0100, Daniel Scally wrote:
> >> On 06/10/2025 09:27, Laurent Pinchart wrote:
> >>> On Mon, Oct 06, 2025 at 09:15:47AM +0100, Daniel Scally wrote:
> >>>> On 05/10/2025 01:06, Laurent Pinchart wrote:
> >>>>> On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
> >>>>>> Introduce v4l2-isp.h in the Linux kernel uAPI.
> >>>>>>
> >>>>>> The header includes types for generic ISP configuration parameters
> >>>>>> and will be extended in future with support for generic ISP statistics
> >>>>>
> >>>>> s/in future/in the future/
> >>>>>
> >>>>> (and you can reflow the commit message)
> >>>>>
> >>>>>> formats.
> >>>>>>
> >>>>>> Generic ISP parameters support is provided by introducing two new
> >>>>>> types that represent an extensible and versioned buffer of ISP
> >>>>>> configuration parameters.
> >>>>>>
> >>>>>> The v4l2_params_block_header structure represents the header to be
> >>>>>> prepend to each ISP configuration block and the v4l2_params_buffer type
> >>>>>> represents the base type for the configuration parameters buffer.
> >>>>>
> >>>>> The second part of the sentence describes the same structure as the next
> >>>>> paragraph.
> >>>>>
> >>>>>> The v4l2_params_buffer represents the container for the ISP
> >>>>>> configuration data block. The generic type is defined with a 0-sized
> >>>>>> data member that the ISP driver implementations shall properly size
> >>>>>> according to their capabilities.
> >>>>>
> >>>>> This will be easier to understand if you describe v4l2_params_buffer
> >>>>> first.
> >>>>>
> >>>>> The commit message would benefit from being rewritten.
> >>>>>
> >>>>>> [Add v4l2_params_buffer_size()]
> >>>>>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> >>>>>> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> >>>>>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >>>>>> ---
> >>>>>> MAINTAINERS | 6 +++
> >>>>>> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
> >>>>>> 2 files changed, 106 insertions(+)
> >>>>>>
> >>>>>> diff --git a/MAINTAINERS b/MAINTAINERS
> >>>>>> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
> >>>>>> --- a/MAINTAINERS
> >>>>>> +++ b/MAINTAINERS
> >>>>>> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
> >>>>>> F: drivers/media/i2c/vd56g3.c
> >>>>>> F: drivers/media/i2c/vgxy61.c
> >>>>>>
> >>>>>> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
> >>>>>> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >>>>>> +L: linux-media@vger.kernel.org
> >>>>>> +S: Maintained
> >>>>>> +F: include/uapi/linux/media/v4l2-isp.h
> >>>>>> +
> >>>>>> VF610 NAND DRIVER
> >>>>>> M: Stefan Agner <stefan@agner.ch>
> >>>>>> L: linux-mtd@lists.infradead.org
> >>>>>> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
> >>>>>> new file mode 100644
> >>>>>> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
> >>>>>> --- /dev/null
> >>>>>> +++ b/include/uapi/linux/media/v4l2-isp.h
> >>>>>> @@ -0,0 +1,100 @@
> >>>>>> +/* 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 <jacopo.mondi@ideasonboard.com>
> >>>>>> + */
> >>>>>> +
> >>>>>> +#ifndef _UAPI_V4L2_ISP_H_
> >>>>>> +#define _UAPI_V4L2_ISP_H_
> >>>>>> +
> >>>>>> +#include <linux/stddef.h>
> >>>>>> +#include <linux/types.h>
> >>>>>> +
> >>>>>> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
> >>>>>> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
> >>>>>> +
> >>>>>> +/*
> >>>>>> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
> >>>>>> + *
> >>>>>> + * Driver-specific flags should be defined as:
> >>>>>> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
> >>>>>
> >>>>> s/PLATFORM/DRIVER/
> >>>>>
> >>>>>> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
> >>>>>> + */
> >>>>>> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
> >>>>>> +
> >>>>>> +/**
> >>>>>> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
> >>>>>> + * driver inspects this common header to discern the block type and its size and
> >>>>>> + * properly handle the block content.
> >>>>>
> >>>>> The last sentence is not relevant for the UAPI.
> >>>>>
> >>>>>> + *
> >>>>>> + * 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_FL_* and
> >>>>>> + * driver-specific flags specified by the driver 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
> >>>>>
> >>>>> I think the fields usually go right after the structure name, followed
> >>>>> by the rest of the documentation.
> >>>>>
> >>>>>> + */
> >>>>>> +struct v4l2_params_block_header {
> >>>>>> + __u16 type;
> >>>>>> + __u16 flags;
> >>>>>> + __u32 size;
> >>>>>> +} __attribute__((aligned(8)));
> >>>>>> +
> >>>>>> +/**
> >>>>>> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
> >>>>>> + *
> >>>>>> + * Users of the v4l2 extensible parameters will have differing sized data arrays
> >>>>>> + * depending on their specific parameter buffers. Drivers and userspace will
> >>>>>> + * need to be able to calculate the appropriate size of the struct to
> >>>>>> + * accommodate all ISP configuration blocks provided by the platform.
> >>>>>> + * This macro provides a convenient tool for the calculation.
> >>>>>> + *
> >>>>>> + * @max_params_size: The total size of the ISP configuration blocks
> >>>>>> + */
> >>>>>> +#define v4l2_params_buffer_size(max_params_size) \
> >>>>>> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
> >>>>>
> >>>>> This isn't used in this series as far as I can tell, and neither is it
> >>>>> used in your libcamera implementation. I'd drop the macro (as well as
> >>>>> the mention in the commit message).
> >>>>
> >>>> This is because the rkisp1 and c3 ISP implementations are already merged with a custom parameters
> >>>> buffer struct defined at [1] and [2]. There the array size is set to the max size macro. This series
> >>>> just asserts that the header part is a size match for struct v4l2_params_buffer to guarantee
> >>>> compatibility, so throughout those drivers they can use sizeof(struct c3_isp_params_cfg) or the
> >>>> rkisp equivalent and it's fine.
> >>>>
> >>>> For new users that don't have a custom struct in their uAPI and are relying on struct
> >>>> v4l2_params_buffer we can't just do sizeof(), so the idea was for this to provide a canonical way
> >>>> for the size calculation to be done across both the kernel and userspace.
> >>>>
> >>>> If we decide that it's worth keeping but want a user in this series to justify its inclusion, it
> >>>> could be used in patches 2 and 3 - I'll reply to patch 2 in a second to indicate where.
> >>>
> >>> Will it be used by userspace too for the Mali C55, or only by the kernel
> >>
> >> I have used it in userspace too.
> >
> > Any pointer to the code ?
>
> I didn't post my commits to adapt the mali-c55 IPA to the extensible parameters, but it's basically
> the same as Jacopo's patch here:
> https://lists.libcamera.org/pipermail/libcamera-devel/2025-October/053567.html
>
> And the change I made using the macro was in IPAMaliC55::fillParams():
>
> - memset(params, 0, sizeof(mali_c55_params_buffer));
> + memset(params, 0, v4l2_params_buffer_size(MALI_C55_PARAMS_MAX_SIZE));
Given that the buffer should be sized for the worst case, wouldn't it be
better to memset .planes()[0].data().size() ?
> >>> driver ?
> >>>
> >>>> [1] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/rkisp1-config.h#L1675
> >>>> [2] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/media/amlogic/c3-isp-config.h#L558>
> >>>>
> >>>>>> +
> >>>>>> +/**
> >>>>>> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
> >>>>>> + *
> >>>>>> + * This struct contains the configuration parameters of the ISP algorithms,
> >>>>>
> >>>>> s/struct/structure/
> >>>>>
> >>>>>> + * serialized by userspace into a data buffer. Each configuration parameter
> >>>>>> + * block is represented by a block-specific structure which contains a
> >>>>>> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
> >>>>>
> >>>>> I think you can drop "nor overlaps", nobody in their right mind should
> >>>>> think the blocks could be overlayed :-)
> >>>>>
> >>>>>> + * the effective size, in bytes, of the @data buffer.
> >>>>>> + *
> >>>>>> + * @version: The parameters buffer version (driver-specific)
> >>>>>> + * @data_size: The configuration data effective size, excluding this header
> >>>>>> + * @data: The configuration data
> >>>>>
> >>>>> Move the fields up just after the structure name.
> >>>>>
> >>>>> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> >>>>>
> >>>>>> + */
> >>>>>> +struct v4l2_params_buffer {
> >>>>>> + __u32 version;
> >>>>>> + __u32 data_size;
> >>>>>> + __u8 data[] __counted_by(data_size);
> >>>>>> +};
> >>>>>> +
> >>>>>> +#endif /* _UAPI_V4L2_ISP_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-06 9:58 ` Laurent Pinchart
@ 2025-10-06 10:26 ` Dan Scally
2025-10-06 14:47 ` Laurent Pinchart
0 siblings, 1 reply; 32+ messages in thread
From: Dan Scally @ 2025-10-06 10:26 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
Hi Laurent
On 06/10/2025 10:58, Laurent Pinchart wrote:
> On Mon, Oct 06, 2025 at 10:51:33AM +0100, Daniel Scally wrote:
>> On 06/10/2025 10:06, Laurent Pinchart wrote:
>>> On Mon, Oct 06, 2025 at 09:46:26AM +0100, Daniel Scally wrote:
>>>> On 06/10/2025 09:27, Laurent Pinchart wrote:
>>>>> On Mon, Oct 06, 2025 at 09:15:47AM +0100, Daniel Scally wrote:
>>>>>> On 05/10/2025 01:06, Laurent Pinchart wrote:
>>>>>>> On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
>>>>>>>> Introduce v4l2-isp.h in the Linux kernel uAPI.
>>>>>>>>
>>>>>>>> The header includes types for generic ISP configuration parameters
>>>>>>>> and will be extended in future with support for generic ISP statistics
>>>>>>>
>>>>>>> s/in future/in the future/
>>>>>>>
>>>>>>> (and you can reflow the commit message)
>>>>>>>
>>>>>>>> formats.
>>>>>>>>
>>>>>>>> Generic ISP parameters support is provided by introducing two new
>>>>>>>> types that represent an extensible and versioned buffer of ISP
>>>>>>>> configuration parameters.
>>>>>>>>
>>>>>>>> The v4l2_params_block_header structure represents the header to be
>>>>>>>> prepend to each ISP configuration block and the v4l2_params_buffer type
>>>>>>>> represents the base type for the configuration parameters buffer.
>>>>>>>
>>>>>>> The second part of the sentence describes the same structure as the next
>>>>>>> paragraph.
>>>>>>>
>>>>>>>> The v4l2_params_buffer represents the container for the ISP
>>>>>>>> configuration data block. The generic type is defined with a 0-sized
>>>>>>>> data member that the ISP driver implementations shall properly size
>>>>>>>> according to their capabilities.
>>>>>>>
>>>>>>> This will be easier to understand if you describe v4l2_params_buffer
>>>>>>> first.
>>>>>>>
>>>>>>> The commit message would benefit from being rewritten.
>>>>>>>
>>>>>>>> [Add v4l2_params_buffer_size()]
>>>>>>>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
>>>>>>>> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
>>>>>>>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>>>>>>> ---
>>>>>>>> MAINTAINERS | 6 +++
>>>>>>>> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
>>>>>>>> 2 files changed, 106 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>>>>>>> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
>>>>>>>> --- a/MAINTAINERS
>>>>>>>> +++ b/MAINTAINERS
>>>>>>>> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
>>>>>>>> F: drivers/media/i2c/vd56g3.c
>>>>>>>> F: drivers/media/i2c/vgxy61.c
>>>>>>>>
>>>>>>>> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
>>>>>>>> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>>>>>>> +L: linux-media@vger.kernel.org
>>>>>>>> +S: Maintained
>>>>>>>> +F: include/uapi/linux/media/v4l2-isp.h
>>>>>>>> +
>>>>>>>> VF610 NAND DRIVER
>>>>>>>> M: Stefan Agner <stefan@agner.ch>
>>>>>>>> L: linux-mtd@lists.infradead.org
>>>>>>>> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
>>>>>>>> new file mode 100644
>>>>>>>> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/include/uapi/linux/media/v4l2-isp.h
>>>>>>>> @@ -0,0 +1,100 @@
>>>>>>>> +/* 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 <jacopo.mondi@ideasonboard.com>
>>>>>>>> + */
>>>>>>>> +
>>>>>>>> +#ifndef _UAPI_V4L2_ISP_H_
>>>>>>>> +#define _UAPI_V4L2_ISP_H_
>>>>>>>> +
>>>>>>>> +#include <linux/stddef.h>
>>>>>>>> +#include <linux/types.h>
>>>>>>>> +
>>>>>>>> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
>>>>>>>> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
>>>>>>>> +
>>>>>>>> +/*
>>>>>>>> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
>>>>>>>> + *
>>>>>>>> + * Driver-specific flags should be defined as:
>>>>>>>> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
>>>>>>>
>>>>>>> s/PLATFORM/DRIVER/
>>>>>>>
>>>>>>>> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
>>>>>>>> + */
>>>>>>>> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
>>>>>>>> + * driver inspects this common header to discern the block type and its size and
>>>>>>>> + * properly handle the block content.
>>>>>>>
>>>>>>> The last sentence is not relevant for the UAPI.
>>>>>>>
>>>>>>>> + *
>>>>>>>> + * 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_FL_* and
>>>>>>>> + * driver-specific flags specified by the driver 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
>>>>>>>
>>>>>>> I think the fields usually go right after the structure name, followed
>>>>>>> by the rest of the documentation.
>>>>>>>
>>>>>>>> + */
>>>>>>>> +struct v4l2_params_block_header {
>>>>>>>> + __u16 type;
>>>>>>>> + __u16 flags;
>>>>>>>> + __u32 size;
>>>>>>>> +} __attribute__((aligned(8)));
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
>>>>>>>> + *
>>>>>>>> + * Users of the v4l2 extensible parameters will have differing sized data arrays
>>>>>>>> + * depending on their specific parameter buffers. Drivers and userspace will
>>>>>>>> + * need to be able to calculate the appropriate size of the struct to
>>>>>>>> + * accommodate all ISP configuration blocks provided by the platform.
>>>>>>>> + * This macro provides a convenient tool for the calculation.
>>>>>>>> + *
>>>>>>>> + * @max_params_size: The total size of the ISP configuration blocks
>>>>>>>> + */
>>>>>>>> +#define v4l2_params_buffer_size(max_params_size) \
>>>>>>>> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
>>>>>>>
>>>>>>> This isn't used in this series as far as I can tell, and neither is it
>>>>>>> used in your libcamera implementation. I'd drop the macro (as well as
>>>>>>> the mention in the commit message).
>>>>>>
>>>>>> This is because the rkisp1 and c3 ISP implementations are already merged with a custom parameters
>>>>>> buffer struct defined at [1] and [2]. There the array size is set to the max size macro. This series
>>>>>> just asserts that the header part is a size match for struct v4l2_params_buffer to guarantee
>>>>>> compatibility, so throughout those drivers they can use sizeof(struct c3_isp_params_cfg) or the
>>>>>> rkisp equivalent and it's fine.
>>>>>>
>>>>>> For new users that don't have a custom struct in their uAPI and are relying on struct
>>>>>> v4l2_params_buffer we can't just do sizeof(), so the idea was for this to provide a canonical way
>>>>>> for the size calculation to be done across both the kernel and userspace.
>>>>>>
>>>>>> If we decide that it's worth keeping but want a user in this series to justify its inclusion, it
>>>>>> could be used in patches 2 and 3 - I'll reply to patch 2 in a second to indicate where.
>>>>>
>>>>> Will it be used by userspace too for the Mali C55, or only by the kernel
>>>>
>>>> I have used it in userspace too.
>>>
>>> Any pointer to the code ?
>>
>> I didn't post my commits to adapt the mali-c55 IPA to the extensible parameters, but it's basically
>> the same as Jacopo's patch here:
>> https://lists.libcamera.org/pipermail/libcamera-devel/2025-October/053567.html
>>
>> And the change I made using the macro was in IPAMaliC55::fillParams():
Just for context, that function currently is:
void IPAMaliC55::fillParams(unsigned int request,
[[maybe_unused]] uint32_t bufferId)
{
struct mali_c55_params_buffer *params;
IPAFrameContext &frameContext = context_.frameContexts.get(request);
params = reinterpret_cast<mali_c55_params_buffer *>(
buffers_.at(bufferId).planes()[0].data());
memset(params, 0, sizeof(mali_c55_params_buffer));
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);
}
size_t bytesused = offsetof(struct mali_c55_params_buffer, data) + params->total_size;
paramsComputed.emit(request, bytesused);
}
>>
>> - memset(params, 0, sizeof(mali_c55_params_buffer));
>> + memset(params, 0, v4l2_params_buffer_size(MALI_C55_PARAMS_MAX_SIZE));
>
> Given that the buffer should be sized for the worst case, wouldn't it be
> better to memset .planes()[0].data().size() ?
Won't buffers_.at(bufferId).planes()[0].size() be the same as
v4l2_params_buffer_size(MALI_C55_PARAMS_MAX_SIZE)? I am under the impression that that size will
come ultimately from .queue_setup() which will be setting the sizes with:
sizes[0] = v4l2_params_buffer_size(MALI_C55_PARAMS_MAX_SIZE);
In that sense I suppose that that would remove the need for v4l2_params_buffer_size() to be used in
userspace and we could just fallback to struct_size_t() within the kernel though.
>
>>>>> driver ?
>>>>>
>>>>>> [1] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/rkisp1-config.h#L1675
>>>>>> [2] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/media/amlogic/c3-isp-config.h#L558>
>>>>>>
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
>>>>>>>> + *
>>>>>>>> + * This struct contains the configuration parameters of the ISP algorithms,
>>>>>>>
>>>>>>> s/struct/structure/
>>>>>>>
>>>>>>>> + * serialized by userspace into a data buffer. Each configuration parameter
>>>>>>>> + * block is represented by a block-specific structure which contains a
>>>>>>>> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
>>>>>>>
>>>>>>> I think you can drop "nor overlaps", nobody in their right mind should
>>>>>>> think the blocks could be overlayed :-)
>>>>>>>
>>>>>>>> + * the effective size, in bytes, of the @data buffer.
>>>>>>>> + *
>>>>>>>> + * @version: The parameters buffer version (driver-specific)
>>>>>>>> + * @data_size: The configuration data effective size, excluding this header
>>>>>>>> + * @data: The configuration data
>>>>>>>
>>>>>>> Move the fields up just after the structure name.
>>>>>>>
>>>>>>> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>>>>>>>
>>>>>>>> + */
>>>>>>>> +struct v4l2_params_buffer {
>>>>>>>> + __u32 version;
>>>>>>>> + __u32 data_size;
>>>>>>>> + __u8 data[] __counted_by(data_size);
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +#endif /* _UAPI_V4L2_ISP_H_ */
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c
2025-10-06 1:08 ` Laurent Pinchart
@ 2025-10-06 10:28 ` Jacopo Mondi
2025-10-06 14:51 ` Laurent Pinchart
0 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-10-06 10:28 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Dan Scally, Sakari Ailus, Antoine Bouyer,
linux-kernel, linux-media, linux-rockchip, linux-arm-kernel
Hi Laurent
On Mon, Oct 06, 2025 at 04:08:06AM +0300, Laurent Pinchart wrote:
> On Mon, Oct 06, 2025 at 03:47:43AM +0300, Laurent Pinchart wrote:
> > Hi Jacopo,
> >
> > Thank you for the patch.
> >
> > On Mon, Sep 15, 2025 at 07:18:14PM +0200, Jacopo Mondi wrote:
> > > Add to the v4l2 framework helper functions to support drivers
> >
> > s/v4l2/V4L2/
> >
> > > when validating a buffer of extensible ISP parameters.
> > >
> > > Introduce new types in include/media/v4l2-isp.h that drivers shall use
> > > in order to comply with the generic ISP parameters validation procedure,
> > > and add helper functionss to v4l2-isp.c to perform blocks and buffer
> > > validation.
> > >
> > > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > ---
> > > MAINTAINERS | 2 +
> > > drivers/media/v4l2-core/Kconfig | 4 ++
> > > drivers/media/v4l2-core/Makefile | 1 +
> > > drivers/media/v4l2-core/v4l2-isp.c | 108 +++++++++++++++++++++++++++++++++++++
> > > include/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++
> > > 5 files changed, 215 insertions(+)
> > >
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index abba872cb63f1430a49a2afbace4b9f9958c3991..5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -26415,6 +26415,8 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > L: linux-media@vger.kernel.org
> > > S: Maintained
> > > F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
> > > +F: drivers/media/v4l2-core/v4l2-isp.c
> > > +F: include/media/v4l2-isp.h
> > > F: include/uapi/linux/media/v4l2-isp.h
> > >
> > > VF610 NAND DRIVER
> > > diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
> > > index 331b8e535e5bbf33f22638b2ae8bc764ad5fc407..d50ccac9733cc39a43426ae7e7996dd0b5b45186 100644
> > > --- a/drivers/media/v4l2-core/Kconfig
> > > +++ b/drivers/media/v4l2-core/Kconfig
> > > @@ -82,3 +82,7 @@ config V4L2_CCI_I2C
> > > depends on I2C
> > > select REGMAP_I2C
> > > select V4L2_CCI
> > > +
> > > +config V4L2_ISP
> > > + tristate
> > > + depends on VIDEOBUF2_CORE
> > > diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> > > index 2177b9d63a8ffc1127c5a70118249a2ff63cd759..329f0eadce994cc1c8580beb435f68fa7e2a7aeb 100644
> > > --- a/drivers/media/v4l2-core/Makefile
> > > +++ b/drivers/media/v4l2-core/Makefile
> > > @@ -29,6 +29,7 @@ obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o
> > > obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
> > > obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
> > > obj-$(CONFIG_V4L2_H264) += v4l2-h264.o
> > > +obj-$(CONFIG_V4L2_ISP) += v4l2-isp.o
> > > obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o
> > > obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
> > > obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o
> > > diff --git a/drivers/media/v4l2-core/v4l2-isp.c b/drivers/media/v4l2-core/v4l2-isp.c
> > > new file mode 100644
> > > index 0000000000000000000000000000000000000000..e350bdaf53b5502e1ec2a4989c20df1100ab2d2a
> > > --- /dev/null
> > > +++ b/drivers/media/v4l2-core/v4l2-isp.c
> > > @@ -0,0 +1,108 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > +/*
> > > + * Video4Linux2 generic ISP parameters and statistics support
> > > + *
> > > + * Copyright (C) 2025 Ideas On Board Oy
> > > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > + */
> > > +
> > > +#include <linux/bitops.h>
> > > +#include <linux/device.h>
> > > +
> > > +#include <media/videobuf2-core.h>
> > > +#include <media/v4l2-isp.h>
> >
> > v4l2-isp goes first.
> >
> > > +
> > > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > > + size_t max_size)
> > > +{
> > > + size_t header_size = offsetof(struct v4l2_params_buffer, data);
> > > + struct v4l2_params_buffer *buffer = vb2_plane_vaddr(vb, 0);
> > > + size_t payload_size = vb2_get_plane_payload(vb, 0);
> > > + size_t buffer_size;
> > > +
> > > + /* Payload size can't be greater than the destination buffer size */
> > > + if (payload_size > max_size) {
> > > + dev_dbg(dev, "Payload size is too large: %zu\n", payload_size);
> > > + return -EINVAL;
> > > + }
> > > +
> > > + /* Payload size can't be smaller than the header size */
> > > + if (payload_size < header_size) {
> > > + dev_dbg(dev, "Payload size is too small: %zu\n", payload_size);
> > > + return -EINVAL;
> > > + }
> > > +
> > > + /* Validate the size reported in the parameter buffer header */
> > > + buffer_size = header_size + buffer->data_size;
> > > + if (buffer_size != payload_size) {
> > > + dev_dbg(dev, "Data size %zu and payload size %zu are different\n",
> > > + buffer_size, payload_size);
> > > + return -EINVAL;
> > > + }
> >
> > This check needs to go to v4l2_params_blocks_validate() as it has to be
> > performed on the data after copying.
> >
I'm not sure. The aim of pre-validation (if we want to call it in this
way) is to check the correctness of the userspace provided buffer, and
the function as its main argument the vb2 buffer pointer for this
reason.
Isn't it important to check that the sizes are correct before doing a
mem copy ?
> > > +
> > > + return 0;
> > > +}
> > > +EXPORT_SYMBOL_GPL(v4l2_params_buffer_validate);
> > > +
> > > +int v4l2_params_blocks_validate(struct device *dev,
> > > + const struct v4l2_params_buffer *buffer,
> > > + const struct v4l2_params_handler *handlers,
> > > + size_t num_handlers)
While the actual "validation" checks the content of v4l2_params_buffer
after it has been copied to a kernel-only memory location. If I would
have to check its size I would have to receive here the vb2 buffer size
as argument (which the drivers should have just used as argument to
the memcpy). It feels a bit mixing two things (that's also why I liked
having a 'buffer validate' and a 'blocks validate' function, but I
won't argue)
> > > +{
> > > + size_t block_offset = 0;
> > > + size_t buffer_size;
> > > +
> > > + /* Walk the list of parameter blocks and validate them. */
> > > + buffer_size = buffer->data_size;
> > > + while (buffer_size >= sizeof(struct v4l2_params_block_header)) {
> > > + const struct v4l2_params_handler *handler;
> > > + const struct v4l2_params_block_header *block;
> > > +
> > > + /* Validate block sizes and types against the handlers. */
> > > + block = (const struct v4l2_params_block_header *)
> > > + (buffer->data + block_offset);
> > > +
> > > + if (block->type >= num_handlers) {
> > > + dev_dbg(dev, "Invalid parameters block type\n");
> >
> > I'd print the type and offset in the message to ease debugging.
> >
> > > + return -EINVAL;
> > > + }
> > > +
> > > + if (block->size > buffer_size) {
> > > + dev_dbg(dev, "Premature end of parameters data\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + /* It's invalid to specify both ENABLE and DISABLE. */
> > > + if ((block->flags & (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > > + V4L2_PARAMS_FL_BLOCK_DISABLE)) ==
> > > + (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > > + V4L2_PARAMS_FL_BLOCK_DISABLE)) {
> > > + dev_dbg(dev, "Invalid parameters block flags\n");
> >
> > Same here (print the flags and offset).
> >
> > > + return -EINVAL;
> > > + }
> > > +
> > > + /*
> > > + * Match the block reported size against the handler's expected
> > > + * one, but allow the block to only contain the header in
> > > + * case it is going to be disabled.
> > > + */
> > > + handler = &handlers[block->type];
> > > + if (block->size != handler->size &&
> > > + (!(block->flags & V4L2_PARAMS_FL_BLOCK_DISABLE) ||
> > > + block->size != sizeof(*block))) {
> > > + dev_dbg(dev, "Invalid parameters block size\n");
> >
> > And here too (print the size and offset).
> >
> > > + return -EINVAL;
> > > + }
> > > +
> > > + block_offset += block->size;
> > > + buffer_size -= block->size;
> > > + }
> > > +
> > > + if (buffer_size) {
> > > + dev_dbg(dev, "Unexpected data after the parameters buffer end\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +EXPORT_SYMBOL_GPL(v4l2_params_blocks_validate);
> > > diff --git a/include/media/v4l2-isp.h b/include/media/v4l2-isp.h
> > > new file mode 100644
> > > index 0000000000000000000000000000000000000000..2ad62c6169eef3d0fb8d245de56cc6bd7e6227e4
> > > --- /dev/null
> > > +++ b/include/media/v4l2-isp.h
> > > @@ -0,0 +1,100 @@
> > > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > > +/*
> > > + * Video4Linux2 generic ISP parameters and statistics support
> > > + *
> > > + * Copyright (C) 2025 Ideas On Board Oy
> > > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > + */
> > > +
> > > +#ifndef V4L2_PARAMS_H_
> > > +#define V4L2_PARAMS_H_
> >
> > V4L2_ISP_H_
> >
> > > +
> > > +#include <linux/media/v4l2-isp.h>
> > > +
> > > +struct device;
> > > +struct vb2_buffer;
> > > +
> > > +/**
> > > + * typedef v4l2_params_block_handler - V4L2 extensible format block handler
> >
> > As commented on 1/8, let's use the v4l2_isp_ prefix.
> >
> > > + * @arg: pointer the driver-specific argument
> > > + * @block: the ISP configuration block to handle
> > > + *
> > > + * Defines the function signature of the functions that handle an ISP block
> > > + * configuration.
> > > + */
> > > +typedef void (*v4l2_params_block_handler)(void *arg,
> > > + const struct v4l2_params_block_header *block);
> > > +
> > > +/**
> > > + * struct v4l2_params_handler - V4L2 extensible format handler
> > > + * @size: the block expected size
> > > + * @handler: the block handler function
> > > + *
> > > + * The v4l2_params_handler defines the type that driver making use of the
> > > + * V4L2 extensible parameters shall use to define their own ISP block
> > > + * handlers.
> > > + *
> > > + * Drivers shall prepare a list of handlers, one for each supported ISP block
> > > + * and correctly populate the structure's field with the expected block @size
> > > + * (used for validation) and a pointer to each block @handler function.
> > > + */
> > > +struct v4l2_params_handler {
> > > + size_t size;
> > > + v4l2_params_block_handler handler;
> > > +};
> > > +
> > > +/**
> > > + * v4l2_params_buffer_validate - Validate a V4L2 extensible parameters buffer
> >
> > As this is the pre-copy validation, what would you think of calling the
> > function v4l2_isp_params_pre_validate_buffer() ? The next function would
> > be called v4l2_isp_params_validate_buffer(), as they're both about
> > buffer validation. I'm also OK to keep the current names (with a
> > v4l2_isp_ prefix).
> >
> > I'm also thinking that the copy could be moved to the helper, but it can
> > be done later.
> >
> > > + * @dev: the driver's device pointer
> > > + * @vb: the videobuf2 buffer
> > > + * @max_size: the maximum allowed buffer size
> > > + * @buffer_validate: callback to the driver-specific buffer validation
> >
> > You forgot to drop the documentation for this argument.
> >
> > > + *
> > > + * Helper function that performs validation of an extensible parameters buffer.
> > > + *
> > > + * The helper is meant to be used by drivers to perform validation of the
> > > + * extensible parameters buffer size correctness.
> > > + *
> > > + * The @vb buffer as received from the vb2 .buf_prepare() operation is checked
> > > + * against @max_size and its validated to be large enough to accommodate at
> > > + * least one ISP configuration block. The effective buffer size is compared
> > > + * with the reported data size to make sure they match.
> > > + *
> > > + * Drivers should use this function to validate the buffer size correctness
> > > + * before performing a copy of the user-provided videobuf2 buffer content into a
> > > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > > + * content after it has been submitted to the driver.
> > > + */
> > > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > > + size_t max_size);
> > > +
> > > +/**
> > > + * v4l2_params_blocks_validate - Validate V4L2 extensible parameters ISP
> > > + * configuration blocks
> > > + * @dev: the driver's device pointer
> > > + * @buffer: the extensible parameters configuration buffer
> > > + * @handlers: the list of block handlers
> >
> > array of block handlers
> >
> > > + * @num_handlers: the number of block handlers
> > > + *
> > > + * Helper function that performs validation of the ISP configuration blocks in
> > > + * an extensible parameters buffer.
> > > + *
> > > + * The helper is meant to be used by drivers to perform validation of the
> > > + * ISP configuration data blocks. For each block in the extensible parameters
> > > + * buffer, its size and correctness are validated against its associated handler
> > > + * in the @handlers list.
> >
> > You need to explain somewhere that the handlers array is indexed by
> > block type.
> >
> > > + *
> > > + * Drivers should use this function to validate the ISP configuration blocks
> > > + * after having validated the correctness of the vb2 buffer sizes by using the
> > > + * v4l2_params_buffer_validate() helper first. Once the buffer size has been
> > > + * validated, drivers should perform a copy of the user-provided buffer into a
> > > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > > + * content after it has been submitted to the driver, and then call this
> > > + * function to perform per-block validation.
> >
> > There's room for improvement in the documentation. I think it would be
> > clearer if you explained the big picture in
> > Documentation/userspace-api/media/v4l/extensible-parameters.rst
>
> My bad, that should be Documentation/driver-api/media/v4l2-isp.rst.
>
> > (pre-validation, copy and post-validation), and only focussed on what
> > those two functions do in their kerneldoc. That can be done later,
> > nothing that you say here is incorrect.
> >
> > With the other comments addressed,
> >
> > Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> >
> > > + */
> > > +int v4l2_params_blocks_validate(struct device *dev,
> > > + const struct v4l2_params_buffer *buffer,
> > > + const struct v4l2_params_handler *handlers,
> > > + size_t num_handlers);
> > > +
> > > +#endif /* V4L2_PARAMS_H_ */
>
> --
> Regards,
>
> Laurent Pinchart
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types
2025-10-06 10:26 ` Dan Scally
@ 2025-10-06 14:47 ` Laurent Pinchart
0 siblings, 0 replies; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 14:47 UTC (permalink / raw)
To: Dan Scally
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On Mon, Oct 06, 2025 at 11:26:22AM +0100, Daniel Scally wrote:
> On 06/10/2025 10:58, Laurent Pinchart wrote:
> > On Mon, Oct 06, 2025 at 10:51:33AM +0100, Daniel Scally wrote:
> >> On 06/10/2025 10:06, Laurent Pinchart wrote:
> >>> On Mon, Oct 06, 2025 at 09:46:26AM +0100, Daniel Scally wrote:
> >>>> On 06/10/2025 09:27, Laurent Pinchart wrote:
> >>>>> On Mon, Oct 06, 2025 at 09:15:47AM +0100, Daniel Scally wrote:
> >>>>>> On 05/10/2025 01:06, Laurent Pinchart wrote:
> >>>>>>> On Mon, Sep 15, 2025 at 07:18:10PM +0200, Jacopo Mondi wrote:
> >>>>>>>> Introduce v4l2-isp.h in the Linux kernel uAPI.
> >>>>>>>>
> >>>>>>>> The header includes types for generic ISP configuration parameters
> >>>>>>>> and will be extended in future with support for generic ISP statistics
> >>>>>>>
> >>>>>>> s/in future/in the future/
> >>>>>>>
> >>>>>>> (and you can reflow the commit message)
> >>>>>>>
> >>>>>>>> formats.
> >>>>>>>>
> >>>>>>>> Generic ISP parameters support is provided by introducing two new
> >>>>>>>> types that represent an extensible and versioned buffer of ISP
> >>>>>>>> configuration parameters.
> >>>>>>>>
> >>>>>>>> The v4l2_params_block_header structure represents the header to be
> >>>>>>>> prepend to each ISP configuration block and the v4l2_params_buffer type
> >>>>>>>> represents the base type for the configuration parameters buffer.
> >>>>>>>
> >>>>>>> The second part of the sentence describes the same structure as the next
> >>>>>>> paragraph.
> >>>>>>>
> >>>>>>>> The v4l2_params_buffer represents the container for the ISP
> >>>>>>>> configuration data block. The generic type is defined with a 0-sized
> >>>>>>>> data member that the ISP driver implementations shall properly size
> >>>>>>>> according to their capabilities.
> >>>>>>>
> >>>>>>> This will be easier to understand if you describe v4l2_params_buffer
> >>>>>>> first.
> >>>>>>>
> >>>>>>> The commit message would benefit from being rewritten.
> >>>>>>>
> >>>>>>>> [Add v4l2_params_buffer_size()]
> >>>>>>>> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> >>>>>>>> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> >>>>>>>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >>>>>>>> ---
> >>>>>>>> MAINTAINERS | 6 +++
> >>>>>>>> include/uapi/linux/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++++
> >>>>>>>> 2 files changed, 106 insertions(+)
> >>>>>>>>
> >>>>>>>> diff --git a/MAINTAINERS b/MAINTAINERS
> >>>>>>>> index ee8cb2db483f6a5e96b62b6f2edd05b1427b69f5..e82c3d0758d6033fe8fcd56ffde2c03c4319fd11 100644
> >>>>>>>> --- a/MAINTAINERS
> >>>>>>>> +++ b/MAINTAINERS
> >>>>>>>> @@ -26410,6 +26410,12 @@ F: drivers/media/i2c/vd55g1.c
> >>>>>>>> F: drivers/media/i2c/vd56g3.c
> >>>>>>>> F: drivers/media/i2c/vgxy61.c
> >>>>>>>>
> >>>>>>>> +V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
> >>>>>>>> +M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >>>>>>>> +L: linux-media@vger.kernel.org
> >>>>>>>> +S: Maintained
> >>>>>>>> +F: include/uapi/linux/media/v4l2-isp.h
> >>>>>>>> +
> >>>>>>>> VF610 NAND DRIVER
> >>>>>>>> M: Stefan Agner <stefan@agner.ch>
> >>>>>>>> L: linux-mtd@lists.infradead.org
> >>>>>>>> diff --git a/include/uapi/linux/media/v4l2-isp.h b/include/uapi/linux/media/v4l2-isp.h
> >>>>>>>> new file mode 100644
> >>>>>>>> index 0000000000000000000000000000000000000000..b838555dce2b290a14136ab09ea4d2dfdc95b26b
> >>>>>>>> --- /dev/null
> >>>>>>>> +++ b/include/uapi/linux/media/v4l2-isp.h
> >>>>>>>> @@ -0,0 +1,100 @@
> >>>>>>>> +/* 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 <jacopo.mondi@ideasonboard.com>
> >>>>>>>> + */
> >>>>>>>> +
> >>>>>>>> +#ifndef _UAPI_V4L2_ISP_H_
> >>>>>>>> +#define _UAPI_V4L2_ISP_H_
> >>>>>>>> +
> >>>>>>>> +#include <linux/stddef.h>
> >>>>>>>> +#include <linux/types.h>
> >>>>>>>> +
> >>>>>>>> +#define V4L2_PARAMS_FL_BLOCK_DISABLE (1U << 0)
> >>>>>>>> +#define V4L2_PARAMS_FL_BLOCK_ENABLE (1U << 1)
> >>>>>>>> +
> >>>>>>>> +/*
> >>>>>>>> + * Reserve the first 8 bits for V4L2_PARAMS_FL_* flag.
> >>>>>>>> + *
> >>>>>>>> + * Driver-specific flags should be defined as:
> >>>>>>>> + * #define PLATFORM_SPECIFIC_FLAG0 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(0))
> >>>>>>>
> >>>>>>> s/PLATFORM/DRIVER/
> >>>>>>>
> >>>>>>>> + * #define PLATFORM_SPECIFIC_FLAG1 ((1U << V4L2_PARAMS_FL_DRIVER_FLAGS(1))
> >>>>>>>> + */
> >>>>>>>> +#define V4L2_PARAMS_FL_DRIVER_FLAGS(n) ((n) + 8)
> >>>>>>>> +
> >>>>>>>> +/**
> >>>>>>>> + * struct v4l2_params_block_header - V4L2 extensible parameters block 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
> >>>>>>>> + * driver inspects this common header to discern the block type and its size and
> >>>>>>>> + * properly handle the block content.
> >>>>>>>
> >>>>>>> The last sentence is not relevant for the UAPI.
> >>>>>>>
> >>>>>>>> + *
> >>>>>>>> + * 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_FL_* and
> >>>>>>>> + * driver-specific flags specified by the driver 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
> >>>>>>>
> >>>>>>> I think the fields usually go right after the structure name, followed
> >>>>>>> by the rest of the documentation.
> >>>>>>>
> >>>>>>>> + */
> >>>>>>>> +struct v4l2_params_block_header {
> >>>>>>>> + __u16 type;
> >>>>>>>> + __u16 flags;
> >>>>>>>> + __u32 size;
> >>>>>>>> +} __attribute__((aligned(8)));
> >>>>>>>> +
> >>>>>>>> +/**
> >>>>>>>> + * v4l2_params_buffer_size - Calculate size of v4l2_params_buffer for a platform
> >>>>>>>> + *
> >>>>>>>> + * Users of the v4l2 extensible parameters will have differing sized data arrays
> >>>>>>>> + * depending on their specific parameter buffers. Drivers and userspace will
> >>>>>>>> + * need to be able to calculate the appropriate size of the struct to
> >>>>>>>> + * accommodate all ISP configuration blocks provided by the platform.
> >>>>>>>> + * This macro provides a convenient tool for the calculation.
> >>>>>>>> + *
> >>>>>>>> + * @max_params_size: The total size of the ISP configuration blocks
> >>>>>>>> + */
> >>>>>>>> +#define v4l2_params_buffer_size(max_params_size) \
> >>>>>>>> + (offsetof(struct v4l2_params_buffer, data) + (max_params_size))
> >>>>>>>
> >>>>>>> This isn't used in this series as far as I can tell, and neither is it
> >>>>>>> used in your libcamera implementation. I'd drop the macro (as well as
> >>>>>>> the mention in the commit message).
> >>>>>>
> >>>>>> This is because the rkisp1 and c3 ISP implementations are already merged with a custom parameters
> >>>>>> buffer struct defined at [1] and [2]. There the array size is set to the max size macro. This series
> >>>>>> just asserts that the header part is a size match for struct v4l2_params_buffer to guarantee
> >>>>>> compatibility, so throughout those drivers they can use sizeof(struct c3_isp_params_cfg) or the
> >>>>>> rkisp equivalent and it's fine.
> >>>>>>
> >>>>>> For new users that don't have a custom struct in their uAPI and are relying on struct
> >>>>>> v4l2_params_buffer we can't just do sizeof(), so the idea was for this to provide a canonical way
> >>>>>> for the size calculation to be done across both the kernel and userspace.
> >>>>>>
> >>>>>> If we decide that it's worth keeping but want a user in this series to justify its inclusion, it
> >>>>>> could be used in patches 2 and 3 - I'll reply to patch 2 in a second to indicate where.
> >>>>>
> >>>>> Will it be used by userspace too for the Mali C55, or only by the kernel
> >>>>
> >>>> I have used it in userspace too.
> >>>
> >>> Any pointer to the code ?
> >>
> >> I didn't post my commits to adapt the mali-c55 IPA to the extensible parameters, but it's basically
> >> the same as Jacopo's patch here:
> >> https://lists.libcamera.org/pipermail/libcamera-devel/2025-October/053567.html
> >>
> >> And the change I made using the macro was in IPAMaliC55::fillParams():
>
> Just for context, that function currently is:
>
> void IPAMaliC55::fillParams(unsigned int request,
> [[maybe_unused]] uint32_t bufferId)
> {
> struct mali_c55_params_buffer *params;
> IPAFrameContext &frameContext = context_.frameContexts.get(request);
>
> params = reinterpret_cast<mali_c55_params_buffer *>(
> buffers_.at(bufferId).planes()[0].data());
> memset(params, 0, sizeof(mali_c55_params_buffer));
>
> 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);
> }
>
> size_t bytesused = offsetof(struct mali_c55_params_buffer, data) + params->total_size;
> paramsComputed.emit(request, bytesused);
> }
>
> >>
> >> - memset(params, 0, sizeof(mali_c55_params_buffer));
> >> + memset(params, 0, v4l2_params_buffer_size(MALI_C55_PARAMS_MAX_SIZE));
> >
> > Given that the buffer should be sized for the worst case, wouldn't it be
> > better to memset .planes()[0].data().size() ?
>
> Won't buffers_.at(bufferId).planes()[0].size() be the same as
> v4l2_params_buffer_size(MALI_C55_PARAMS_MAX_SIZE)? I am under the impression that that size will
> come ultimately from .queue_setup() which will be setting the sizes with:
>
> sizes[0] = v4l2_params_buffer_size(MALI_C55_PARAMS_MAX_SIZE);
>
> In that sense I suppose that that would remove the need for v4l2_params_buffer_size() to be used in
> userspace and we could just fallback to struct_size_t() within the kernel though.
You're reading my mind :-)
> >>>>> driver ?
> >>>>>
> >>>>>> [1] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/rkisp1-config.h#L1675
> >>>>>> [2] https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/media/amlogic/c3-isp-config.h#L558>
> >>>>>>
> >>>>>>>> +
> >>>>>>>> +/**
> >>>>>>>> + * struct v4l2_params_buffer - V4L2 extensible parameters configuration
> >>>>>>>> + *
> >>>>>>>> + * This struct contains the configuration parameters of the ISP algorithms,
> >>>>>>>
> >>>>>>> s/struct/structure/
> >>>>>>>
> >>>>>>>> + * serialized by userspace into a data buffer. Each configuration parameter
> >>>>>>>> + * block is represented by a block-specific structure which contains a
> >>>>>>>> + * :c:type:`v4l2_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 nor overlaps. Userspace shall populate the @data_size field with
> >>>>>>>
> >>>>>>> I think you can drop "nor overlaps", nobody in their right mind should
> >>>>>>> think the blocks could be overlayed :-)
> >>>>>>>
> >>>>>>>> + * the effective size, in bytes, of the @data buffer.
> >>>>>>>> + *
> >>>>>>>> + * @version: The parameters buffer version (driver-specific)
> >>>>>>>> + * @data_size: The configuration data effective size, excluding this header
> >>>>>>>> + * @data: The configuration data
> >>>>>>>
> >>>>>>> Move the fields up just after the structure name.
> >>>>>>>
> >>>>>>> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> >>>>>>>
> >>>>>>>> + */
> >>>>>>>> +struct v4l2_params_buffer {
> >>>>>>>> + __u32 version;
> >>>>>>>> + __u32 data_size;
> >>>>>>>> + __u8 data[] __counted_by(data_size);
> >>>>>>>> +};
> >>>>>>>> +
> >>>>>>>> +#endif /* _UAPI_V4L2_ISP_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c
2025-10-06 10:28 ` Jacopo Mondi
@ 2025-10-06 14:51 ` Laurent Pinchart
2025-10-06 15:00 ` Jacopo Mondi
0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 14:51 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On Mon, Oct 06, 2025 at 12:28:01PM +0200, Jacopo Mondi wrote:
> On Mon, Oct 06, 2025 at 04:08:06AM +0300, Laurent Pinchart wrote:
> > On Mon, Oct 06, 2025 at 03:47:43AM +0300, Laurent Pinchart wrote:
> > > On Mon, Sep 15, 2025 at 07:18:14PM +0200, Jacopo Mondi wrote:
> > > > Add to the v4l2 framework helper functions to support drivers
> > >
> > > s/v4l2/V4L2/
> > >
> > > > when validating a buffer of extensible ISP parameters.
> > > >
> > > > Introduce new types in include/media/v4l2-isp.h that drivers shall use
> > > > in order to comply with the generic ISP parameters validation procedure,
> > > > and add helper functionss to v4l2-isp.c to perform blocks and buffer
> > > > validation.
> > > >
> > > > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > ---
> > > > MAINTAINERS | 2 +
> > > > drivers/media/v4l2-core/Kconfig | 4 ++
> > > > drivers/media/v4l2-core/Makefile | 1 +
> > > > drivers/media/v4l2-core/v4l2-isp.c | 108 +++++++++++++++++++++++++++++++++++++
> > > > include/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++
> > > > 5 files changed, 215 insertions(+)
> > > >
> > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > index abba872cb63f1430a49a2afbace4b9f9958c3991..5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1 100644
> > > > --- a/MAINTAINERS
> > > > +++ b/MAINTAINERS
> > > > @@ -26415,6 +26415,8 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > L: linux-media@vger.kernel.org
> > > > S: Maintained
> > > > F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
> > > > +F: drivers/media/v4l2-core/v4l2-isp.c
> > > > +F: include/media/v4l2-isp.h
> > > > F: include/uapi/linux/media/v4l2-isp.h
> > > >
> > > > VF610 NAND DRIVER
> > > > diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
> > > > index 331b8e535e5bbf33f22638b2ae8bc764ad5fc407..d50ccac9733cc39a43426ae7e7996dd0b5b45186 100644
> > > > --- a/drivers/media/v4l2-core/Kconfig
> > > > +++ b/drivers/media/v4l2-core/Kconfig
> > > > @@ -82,3 +82,7 @@ config V4L2_CCI_I2C
> > > > depends on I2C
> > > > select REGMAP_I2C
> > > > select V4L2_CCI
> > > > +
> > > > +config V4L2_ISP
> > > > + tristate
> > > > + depends on VIDEOBUF2_CORE
> > > > diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> > > > index 2177b9d63a8ffc1127c5a70118249a2ff63cd759..329f0eadce994cc1c8580beb435f68fa7e2a7aeb 100644
> > > > --- a/drivers/media/v4l2-core/Makefile
> > > > +++ b/drivers/media/v4l2-core/Makefile
> > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o
> > > > obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
> > > > obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
> > > > obj-$(CONFIG_V4L2_H264) += v4l2-h264.o
> > > > +obj-$(CONFIG_V4L2_ISP) += v4l2-isp.o
> > > > obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o
> > > > obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
> > > > obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o
> > > > diff --git a/drivers/media/v4l2-core/v4l2-isp.c b/drivers/media/v4l2-core/v4l2-isp.c
> > > > new file mode 100644
> > > > index 0000000000000000000000000000000000000000..e350bdaf53b5502e1ec2a4989c20df1100ab2d2a
> > > > --- /dev/null
> > > > +++ b/drivers/media/v4l2-core/v4l2-isp.c
> > > > @@ -0,0 +1,108 @@
> > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > +/*
> > > > + * Video4Linux2 generic ISP parameters and statistics support
> > > > + *
> > > > + * Copyright (C) 2025 Ideas On Board Oy
> > > > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > + */
> > > > +
> > > > +#include <linux/bitops.h>
> > > > +#include <linux/device.h>
> > > > +
> > > > +#include <media/videobuf2-core.h>
> > > > +#include <media/v4l2-isp.h>
> > >
> > > v4l2-isp goes first.
> > >
> > > > +
> > > > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > > > + size_t max_size)
> > > > +{
> > > > + size_t header_size = offsetof(struct v4l2_params_buffer, data);
> > > > + struct v4l2_params_buffer *buffer = vb2_plane_vaddr(vb, 0);
> > > > + size_t payload_size = vb2_get_plane_payload(vb, 0);
> > > > + size_t buffer_size;
> > > > +
> > > > + /* Payload size can't be greater than the destination buffer size */
> > > > + if (payload_size > max_size) {
> > > > + dev_dbg(dev, "Payload size is too large: %zu\n", payload_size);
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + /* Payload size can't be smaller than the header size */
> > > > + if (payload_size < header_size) {
> > > > + dev_dbg(dev, "Payload size is too small: %zu\n", payload_size);
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + /* Validate the size reported in the parameter buffer header */
> > > > + buffer_size = header_size + buffer->data_size;
> > > > + if (buffer_size != payload_size) {
> > > > + dev_dbg(dev, "Data size %zu and payload size %zu are different\n",
> > > > + buffer_size, payload_size);
> > > > + return -EINVAL;
> > > > + }
> > >
> > > This check needs to go to v4l2_params_blocks_validate() as it has to be
> > > performed on the data after copying.
> > >
>
> I'm not sure. The aim of pre-validation (if we want to call it in this
> way) is to check the correctness of the userspace provided buffer, and
> the function as its main argument the vb2 buffer pointer for this
> reason.
>
> Isn't it important to check that the sizes are correct before doing a
> mem copy ?
This check reads buffer->data_size. It can be modified by userspace
after the check and before doing the copy, which will lead to an invalid
value being used in v4l2_params_blocks_validate(). Pre-copy validation
can't use anything from within the buffer.
> > > > +
> > > > + return 0;
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(v4l2_params_buffer_validate);
> > > > +
> > > > +int v4l2_params_blocks_validate(struct device *dev,
> > > > + const struct v4l2_params_buffer *buffer,
> > > > + const struct v4l2_params_handler *handlers,
> > > > + size_t num_handlers)
>
> While the actual "validation" checks the content of v4l2_params_buffer
> after it has been copied to a kernel-only memory location. If I would
> have to check its size I would have to receive here the vb2 buffer size
> as argument (which the drivers should have just used as argument to
> the memcpy). It feels a bit mixing two things (that's also why I liked
> having a 'buffer validate' and a 'blocks validate' function, but I
> won't argue)
>
> > > > +{
> > > > + size_t block_offset = 0;
> > > > + size_t buffer_size;
> > > > +
> > > > + /* Walk the list of parameter blocks and validate them. */
> > > > + buffer_size = buffer->data_size;
> > > > + while (buffer_size >= sizeof(struct v4l2_params_block_header)) {
> > > > + const struct v4l2_params_handler *handler;
> > > > + const struct v4l2_params_block_header *block;
> > > > +
> > > > + /* Validate block sizes and types against the handlers. */
> > > > + block = (const struct v4l2_params_block_header *)
> > > > + (buffer->data + block_offset);
> > > > +
> > > > + if (block->type >= num_handlers) {
> > > > + dev_dbg(dev, "Invalid parameters block type\n");
> > >
> > > I'd print the type and offset in the message to ease debugging.
> > >
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + if (block->size > buffer_size) {
> > > > + dev_dbg(dev, "Premature end of parameters data\n");
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + /* It's invalid to specify both ENABLE and DISABLE. */
> > > > + if ((block->flags & (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > > > + V4L2_PARAMS_FL_BLOCK_DISABLE)) ==
> > > > + (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > > > + V4L2_PARAMS_FL_BLOCK_DISABLE)) {
> > > > + dev_dbg(dev, "Invalid parameters block flags\n");
> > >
> > > Same here (print the flags and offset).
> > >
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + /*
> > > > + * Match the block reported size against the handler's expected
> > > > + * one, but allow the block to only contain the header in
> > > > + * case it is going to be disabled.
> > > > + */
> > > > + handler = &handlers[block->type];
> > > > + if (block->size != handler->size &&
> > > > + (!(block->flags & V4L2_PARAMS_FL_BLOCK_DISABLE) ||
> > > > + block->size != sizeof(*block))) {
> > > > + dev_dbg(dev, "Invalid parameters block size\n");
> > >
> > > And here too (print the size and offset).
> > >
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + block_offset += block->size;
> > > > + buffer_size -= block->size;
> > > > + }
> > > > +
> > > > + if (buffer_size) {
> > > > + dev_dbg(dev, "Unexpected data after the parameters buffer end\n");
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(v4l2_params_blocks_validate);
> > > > diff --git a/include/media/v4l2-isp.h b/include/media/v4l2-isp.h
> > > > new file mode 100644
> > > > index 0000000000000000000000000000000000000000..2ad62c6169eef3d0fb8d245de56cc6bd7e6227e4
> > > > --- /dev/null
> > > > +++ b/include/media/v4l2-isp.h
> > > > @@ -0,0 +1,100 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > > > +/*
> > > > + * Video4Linux2 generic ISP parameters and statistics support
> > > > + *
> > > > + * Copyright (C) 2025 Ideas On Board Oy
> > > > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > + */
> > > > +
> > > > +#ifndef V4L2_PARAMS_H_
> > > > +#define V4L2_PARAMS_H_
> > >
> > > V4L2_ISP_H_
> > >
> > > > +
> > > > +#include <linux/media/v4l2-isp.h>
> > > > +
> > > > +struct device;
> > > > +struct vb2_buffer;
> > > > +
> > > > +/**
> > > > + * typedef v4l2_params_block_handler - V4L2 extensible format block handler
> > >
> > > As commented on 1/8, let's use the v4l2_isp_ prefix.
> > >
> > > > + * @arg: pointer the driver-specific argument
> > > > + * @block: the ISP configuration block to handle
> > > > + *
> > > > + * Defines the function signature of the functions that handle an ISP block
> > > > + * configuration.
> > > > + */
> > > > +typedef void (*v4l2_params_block_handler)(void *arg,
> > > > + const struct v4l2_params_block_header *block);
> > > > +
> > > > +/**
> > > > + * struct v4l2_params_handler - V4L2 extensible format handler
> > > > + * @size: the block expected size
> > > > + * @handler: the block handler function
> > > > + *
> > > > + * The v4l2_params_handler defines the type that driver making use of the
> > > > + * V4L2 extensible parameters shall use to define their own ISP block
> > > > + * handlers.
> > > > + *
> > > > + * Drivers shall prepare a list of handlers, one for each supported ISP block
> > > > + * and correctly populate the structure's field with the expected block @size
> > > > + * (used for validation) and a pointer to each block @handler function.
> > > > + */
> > > > +struct v4l2_params_handler {
> > > > + size_t size;
> > > > + v4l2_params_block_handler handler;
> > > > +};
> > > > +
> > > > +/**
> > > > + * v4l2_params_buffer_validate - Validate a V4L2 extensible parameters buffer
> > >
> > > As this is the pre-copy validation, what would you think of calling the
> > > function v4l2_isp_params_pre_validate_buffer() ? The next function would
> > > be called v4l2_isp_params_validate_buffer(), as they're both about
> > > buffer validation. I'm also OK to keep the current names (with a
> > > v4l2_isp_ prefix).
> > >
> > > I'm also thinking that the copy could be moved to the helper, but it can
> > > be done later.
> > >
> > > > + * @dev: the driver's device pointer
> > > > + * @vb: the videobuf2 buffer
> > > > + * @max_size: the maximum allowed buffer size
> > > > + * @buffer_validate: callback to the driver-specific buffer validation
> > >
> > > You forgot to drop the documentation for this argument.
> > >
> > > > + *
> > > > + * Helper function that performs validation of an extensible parameters buffer.
> > > > + *
> > > > + * The helper is meant to be used by drivers to perform validation of the
> > > > + * extensible parameters buffer size correctness.
> > > > + *
> > > > + * The @vb buffer as received from the vb2 .buf_prepare() operation is checked
> > > > + * against @max_size and its validated to be large enough to accommodate at
> > > > + * least one ISP configuration block. The effective buffer size is compared
> > > > + * with the reported data size to make sure they match.
> > > > + *
> > > > + * Drivers should use this function to validate the buffer size correctness
> > > > + * before performing a copy of the user-provided videobuf2 buffer content into a
> > > > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > > > + * content after it has been submitted to the driver.
> > > > + */
> > > > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > > > + size_t max_size);
> > > > +
> > > > +/**
> > > > + * v4l2_params_blocks_validate - Validate V4L2 extensible parameters ISP
> > > > + * configuration blocks
> > > > + * @dev: the driver's device pointer
> > > > + * @buffer: the extensible parameters configuration buffer
> > > > + * @handlers: the list of block handlers
> > >
> > > array of block handlers
> > >
> > > > + * @num_handlers: the number of block handlers
> > > > + *
> > > > + * Helper function that performs validation of the ISP configuration blocks in
> > > > + * an extensible parameters buffer.
> > > > + *
> > > > + * The helper is meant to be used by drivers to perform validation of the
> > > > + * ISP configuration data blocks. For each block in the extensible parameters
> > > > + * buffer, its size and correctness are validated against its associated handler
> > > > + * in the @handlers list.
> > >
> > > You need to explain somewhere that the handlers array is indexed by
> > > block type.
> > >
> > > > + *
> > > > + * Drivers should use this function to validate the ISP configuration blocks
> > > > + * after having validated the correctness of the vb2 buffer sizes by using the
> > > > + * v4l2_params_buffer_validate() helper first. Once the buffer size has been
> > > > + * validated, drivers should perform a copy of the user-provided buffer into a
> > > > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > > > + * content after it has been submitted to the driver, and then call this
> > > > + * function to perform per-block validation.
> > >
> > > There's room for improvement in the documentation. I think it would be
> > > clearer if you explained the big picture in
> > > Documentation/userspace-api/media/v4l/extensible-parameters.rst
> >
> > My bad, that should be Documentation/driver-api/media/v4l2-isp.rst.
> >
> > > (pre-validation, copy and post-validation), and only focussed on what
> > > those two functions do in their kerneldoc. That can be done later,
> > > nothing that you say here is incorrect.
> > >
> > > With the other comments addressed,
> > >
> > > Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> > >
> > > > + */
> > > > +int v4l2_params_blocks_validate(struct device *dev,
> > > > + const struct v4l2_params_buffer *buffer,
> > > > + const struct v4l2_params_handler *handlers,
> > > > + size_t num_handlers);
> > > > +
> > > > +#endif /* V4L2_PARAMS_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c
2025-10-06 14:51 ` Laurent Pinchart
@ 2025-10-06 15:00 ` Jacopo Mondi
2025-10-06 15:41 ` Laurent Pinchart
0 siblings, 1 reply; 32+ messages in thread
From: Jacopo Mondi @ 2025-10-06 15:00 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Jacopo Mondi, Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab,
Heiko Stuebner, Dan Scally, Sakari Ailus, Antoine Bouyer,
linux-kernel, linux-media, linux-rockchip, linux-arm-kernel
On Mon, Oct 06, 2025 at 05:51:46PM +0300, Laurent Pinchart wrote:
> On Mon, Oct 06, 2025 at 12:28:01PM +0200, Jacopo Mondi wrote:
> > On Mon, Oct 06, 2025 at 04:08:06AM +0300, Laurent Pinchart wrote:
> > > On Mon, Oct 06, 2025 at 03:47:43AM +0300, Laurent Pinchart wrote:
> > > > On Mon, Sep 15, 2025 at 07:18:14PM +0200, Jacopo Mondi wrote:
> > > > > Add to the v4l2 framework helper functions to support drivers
> > > >
> > > > s/v4l2/V4L2/
> > > >
> > > > > when validating a buffer of extensible ISP parameters.
> > > > >
> > > > > Introduce new types in include/media/v4l2-isp.h that drivers shall use
> > > > > in order to comply with the generic ISP parameters validation procedure,
> > > > > and add helper functionss to v4l2-isp.c to perform blocks and buffer
> > > > > validation.
> > > > >
> > > > > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > > ---
> > > > > MAINTAINERS | 2 +
> > > > > drivers/media/v4l2-core/Kconfig | 4 ++
> > > > > drivers/media/v4l2-core/Makefile | 1 +
> > > > > drivers/media/v4l2-core/v4l2-isp.c | 108 +++++++++++++++++++++++++++++++++++++
> > > > > include/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++
> > > > > 5 files changed, 215 insertions(+)
> > > > >
> > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > index abba872cb63f1430a49a2afbace4b9f9958c3991..5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1 100644
> > > > > --- a/MAINTAINERS
> > > > > +++ b/MAINTAINERS
> > > > > @@ -26415,6 +26415,8 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > > L: linux-media@vger.kernel.org
> > > > > S: Maintained
> > > > > F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
> > > > > +F: drivers/media/v4l2-core/v4l2-isp.c
> > > > > +F: include/media/v4l2-isp.h
> > > > > F: include/uapi/linux/media/v4l2-isp.h
> > > > >
> > > > > VF610 NAND DRIVER
> > > > > diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
> > > > > index 331b8e535e5bbf33f22638b2ae8bc764ad5fc407..d50ccac9733cc39a43426ae7e7996dd0b5b45186 100644
> > > > > --- a/drivers/media/v4l2-core/Kconfig
> > > > > +++ b/drivers/media/v4l2-core/Kconfig
> > > > > @@ -82,3 +82,7 @@ config V4L2_CCI_I2C
> > > > > depends on I2C
> > > > > select REGMAP_I2C
> > > > > select V4L2_CCI
> > > > > +
> > > > > +config V4L2_ISP
> > > > > + tristate
> > > > > + depends on VIDEOBUF2_CORE
> > > > > diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> > > > > index 2177b9d63a8ffc1127c5a70118249a2ff63cd759..329f0eadce994cc1c8580beb435f68fa7e2a7aeb 100644
> > > > > --- a/drivers/media/v4l2-core/Makefile
> > > > > +++ b/drivers/media/v4l2-core/Makefile
> > > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o
> > > > > obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
> > > > > obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
> > > > > obj-$(CONFIG_V4L2_H264) += v4l2-h264.o
> > > > > +obj-$(CONFIG_V4L2_ISP) += v4l2-isp.o
> > > > > obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o
> > > > > obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
> > > > > obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o
> > > > > diff --git a/drivers/media/v4l2-core/v4l2-isp.c b/drivers/media/v4l2-core/v4l2-isp.c
> > > > > new file mode 100644
> > > > > index 0000000000000000000000000000000000000000..e350bdaf53b5502e1ec2a4989c20df1100ab2d2a
> > > > > --- /dev/null
> > > > > +++ b/drivers/media/v4l2-core/v4l2-isp.c
> > > > > @@ -0,0 +1,108 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > +/*
> > > > > + * Video4Linux2 generic ISP parameters and statistics support
> > > > > + *
> > > > > + * Copyright (C) 2025 Ideas On Board Oy
> > > > > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > > + */
> > > > > +
> > > > > +#include <linux/bitops.h>
> > > > > +#include <linux/device.h>
> > > > > +
> > > > > +#include <media/videobuf2-core.h>
> > > > > +#include <media/v4l2-isp.h>
> > > >
> > > > v4l2-isp goes first.
> > > >
> > > > > +
> > > > > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > > > > + size_t max_size)
> > > > > +{
> > > > > + size_t header_size = offsetof(struct v4l2_params_buffer, data);
> > > > > + struct v4l2_params_buffer *buffer = vb2_plane_vaddr(vb, 0);
> > > > > + size_t payload_size = vb2_get_plane_payload(vb, 0);
> > > > > + size_t buffer_size;
> > > > > +
> > > > > + /* Payload size can't be greater than the destination buffer size */
> > > > > + if (payload_size > max_size) {
> > > > > + dev_dbg(dev, "Payload size is too large: %zu\n", payload_size);
> > > > > + return -EINVAL;
> > > > > + }
> > > > > +
> > > > > + /* Payload size can't be smaller than the header size */
> > > > > + if (payload_size < header_size) {
> > > > > + dev_dbg(dev, "Payload size is too small: %zu\n", payload_size);
> > > > > + return -EINVAL;
> > > > > + }
> > > > > +
> > > > > + /* Validate the size reported in the parameter buffer header */
> > > > > + buffer_size = header_size + buffer->data_size;
> > > > > + if (buffer_size != payload_size) {
> > > > > + dev_dbg(dev, "Data size %zu and payload size %zu are different\n",
> > > > > + buffer_size, payload_size);
> > > > > + return -EINVAL;
> > > > > + }
> > > >
> > > > This check needs to go to v4l2_params_blocks_validate() as it has to be
> > > > performed on the data after copying.
> > > >
> >
> > I'm not sure. The aim of pre-validation (if we want to call it in this
> > way) is to check the correctness of the userspace provided buffer, and
> > the function as its main argument the vb2 buffer pointer for this
> > reason.
> >
> > Isn't it important to check that the sizes are correct before doing a
> > mem copy ?
>
> This check reads buffer->data_size. It can be modified by userspace
> after the check and before doing the copy, which will lead to an invalid
> value being used in v4l2_params_blocks_validate(). Pre-copy validation
> can't use anything from within the buffer.
The helper is intended to be called in the .buf_prepare callback,
which is in the QBUF ioctl call path. Is there a window where
userspace could modify the buffer during the ioctl call ?
>
> > > > > +
> > > > > + return 0;
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(v4l2_params_buffer_validate);
> > > > > +
> > > > > +int v4l2_params_blocks_validate(struct device *dev,
> > > > > + const struct v4l2_params_buffer *buffer,
> > > > > + const struct v4l2_params_handler *handlers,
> > > > > + size_t num_handlers)
> >
> > While the actual "validation" checks the content of v4l2_params_buffer
> > after it has been copied to a kernel-only memory location. If I would
> > have to check its size I would have to receive here the vb2 buffer size
> > as argument (which the drivers should have just used as argument to
> > the memcpy). It feels a bit mixing two things (that's also why I liked
> > having a 'buffer validate' and a 'blocks validate' function, but I
> > won't argue)
> >
Could you provide then the design for a nice interface where the vb2
buffer size can be passed to this function if validation of the vb2
buffer size should be moved here ?
> > > > > +{
> > > > > + size_t block_offset = 0;
> > > > > + size_t buffer_size;
> > > > > +
> > > > > + /* Walk the list of parameter blocks and validate them. */
> > > > > + buffer_size = buffer->data_size;
> > > > > + while (buffer_size >= sizeof(struct v4l2_params_block_header)) {
> > > > > + const struct v4l2_params_handler *handler;
> > > > > + const struct v4l2_params_block_header *block;
> > > > > +
> > > > > + /* Validate block sizes and types against the handlers. */
> > > > > + block = (const struct v4l2_params_block_header *)
> > > > > + (buffer->data + block_offset);
> > > > > +
> > > > > + if (block->type >= num_handlers) {
> > > > > + dev_dbg(dev, "Invalid parameters block type\n");
> > > >
> > > > I'd print the type and offset in the message to ease debugging.
> > > >
> > > > > + return -EINVAL;
> > > > > + }
> > > > > +
> > > > > + if (block->size > buffer_size) {
> > > > > + dev_dbg(dev, "Premature end of parameters data\n");
> > > > > + return -EINVAL;
> > > > > + }
> > > > > +
> > > > > + /* It's invalid to specify both ENABLE and DISABLE. */
> > > > > + if ((block->flags & (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > > > > + V4L2_PARAMS_FL_BLOCK_DISABLE)) ==
> > > > > + (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > > > > + V4L2_PARAMS_FL_BLOCK_DISABLE)) {
> > > > > + dev_dbg(dev, "Invalid parameters block flags\n");
> > > >
> > > > Same here (print the flags and offset).
> > > >
> > > > > + return -EINVAL;
> > > > > + }
> > > > > +
> > > > > + /*
> > > > > + * Match the block reported size against the handler's expected
> > > > > + * one, but allow the block to only contain the header in
> > > > > + * case it is going to be disabled.
> > > > > + */
> > > > > + handler = &handlers[block->type];
> > > > > + if (block->size != handler->size &&
> > > > > + (!(block->flags & V4L2_PARAMS_FL_BLOCK_DISABLE) ||
> > > > > + block->size != sizeof(*block))) {
> > > > > + dev_dbg(dev, "Invalid parameters block size\n");
> > > >
> > > > And here too (print the size and offset).
> > > >
> > > > > + return -EINVAL;
> > > > > + }
> > > > > +
> > > > > + block_offset += block->size;
> > > > > + buffer_size -= block->size;
> > > > > + }
> > > > > +
> > > > > + if (buffer_size) {
> > > > > + dev_dbg(dev, "Unexpected data after the parameters buffer end\n");
> > > > > + return -EINVAL;
> > > > > + }
> > > > > +
> > > > > + return 0;
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(v4l2_params_blocks_validate);
> > > > > diff --git a/include/media/v4l2-isp.h b/include/media/v4l2-isp.h
> > > > > new file mode 100644
> > > > > index 0000000000000000000000000000000000000000..2ad62c6169eef3d0fb8d245de56cc6bd7e6227e4
> > > > > --- /dev/null
> > > > > +++ b/include/media/v4l2-isp.h
> > > > > @@ -0,0 +1,100 @@
> > > > > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > > > > +/*
> > > > > + * Video4Linux2 generic ISP parameters and statistics support
> > > > > + *
> > > > > + * Copyright (C) 2025 Ideas On Board Oy
> > > > > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > > + */
> > > > > +
> > > > > +#ifndef V4L2_PARAMS_H_
> > > > > +#define V4L2_PARAMS_H_
> > > >
> > > > V4L2_ISP_H_
> > > >
> > > > > +
> > > > > +#include <linux/media/v4l2-isp.h>
> > > > > +
> > > > > +struct device;
> > > > > +struct vb2_buffer;
> > > > > +
> > > > > +/**
> > > > > + * typedef v4l2_params_block_handler - V4L2 extensible format block handler
> > > >
> > > > As commented on 1/8, let's use the v4l2_isp_ prefix.
> > > >
> > > > > + * @arg: pointer the driver-specific argument
> > > > > + * @block: the ISP configuration block to handle
> > > > > + *
> > > > > + * Defines the function signature of the functions that handle an ISP block
> > > > > + * configuration.
> > > > > + */
> > > > > +typedef void (*v4l2_params_block_handler)(void *arg,
> > > > > + const struct v4l2_params_block_header *block);
> > > > > +
> > > > > +/**
> > > > > + * struct v4l2_params_handler - V4L2 extensible format handler
> > > > > + * @size: the block expected size
> > > > > + * @handler: the block handler function
> > > > > + *
> > > > > + * The v4l2_params_handler defines the type that driver making use of the
> > > > > + * V4L2 extensible parameters shall use to define their own ISP block
> > > > > + * handlers.
> > > > > + *
> > > > > + * Drivers shall prepare a list of handlers, one for each supported ISP block
> > > > > + * and correctly populate the structure's field with the expected block @size
> > > > > + * (used for validation) and a pointer to each block @handler function.
> > > > > + */
> > > > > +struct v4l2_params_handler {
> > > > > + size_t size;
> > > > > + v4l2_params_block_handler handler;
> > > > > +};
> > > > > +
> > > > > +/**
> > > > > + * v4l2_params_buffer_validate - Validate a V4L2 extensible parameters buffer
> > > >
> > > > As this is the pre-copy validation, what would you think of calling the
> > > > function v4l2_isp_params_pre_validate_buffer() ? The next function would
> > > > be called v4l2_isp_params_validate_buffer(), as they're both about
> > > > buffer validation. I'm also OK to keep the current names (with a
> > > > v4l2_isp_ prefix).
> > > >
> > > > I'm also thinking that the copy could be moved to the helper, but it can
> > > > be done later.
> > > >
> > > > > + * @dev: the driver's device pointer
> > > > > + * @vb: the videobuf2 buffer
> > > > > + * @max_size: the maximum allowed buffer size
> > > > > + * @buffer_validate: callback to the driver-specific buffer validation
> > > >
> > > > You forgot to drop the documentation for this argument.
> > > >
> > > > > + *
> > > > > + * Helper function that performs validation of an extensible parameters buffer.
> > > > > + *
> > > > > + * The helper is meant to be used by drivers to perform validation of the
> > > > > + * extensible parameters buffer size correctness.
> > > > > + *
> > > > > + * The @vb buffer as received from the vb2 .buf_prepare() operation is checked
> > > > > + * against @max_size and its validated to be large enough to accommodate at
> > > > > + * least one ISP configuration block. The effective buffer size is compared
> > > > > + * with the reported data size to make sure they match.
> > > > > + *
> > > > > + * Drivers should use this function to validate the buffer size correctness
> > > > > + * before performing a copy of the user-provided videobuf2 buffer content into a
> > > > > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > > > > + * content after it has been submitted to the driver.
> > > > > + */
> > > > > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > > > > + size_t max_size);
> > > > > +
> > > > > +/**
> > > > > + * v4l2_params_blocks_validate - Validate V4L2 extensible parameters ISP
> > > > > + * configuration blocks
> > > > > + * @dev: the driver's device pointer
> > > > > + * @buffer: the extensible parameters configuration buffer
> > > > > + * @handlers: the list of block handlers
> > > >
> > > > array of block handlers
> > > >
> > > > > + * @num_handlers: the number of block handlers
> > > > > + *
> > > > > + * Helper function that performs validation of the ISP configuration blocks in
> > > > > + * an extensible parameters buffer.
> > > > > + *
> > > > > + * The helper is meant to be used by drivers to perform validation of the
> > > > > + * ISP configuration data blocks. For each block in the extensible parameters
> > > > > + * buffer, its size and correctness are validated against its associated handler
> > > > > + * in the @handlers list.
> > > >
> > > > You need to explain somewhere that the handlers array is indexed by
> > > > block type.
> > > >
> > > > > + *
> > > > > + * Drivers should use this function to validate the ISP configuration blocks
> > > > > + * after having validated the correctness of the vb2 buffer sizes by using the
> > > > > + * v4l2_params_buffer_validate() helper first. Once the buffer size has been
> > > > > + * validated, drivers should perform a copy of the user-provided buffer into a
> > > > > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > > > > + * content after it has been submitted to the driver, and then call this
> > > > > + * function to perform per-block validation.
> > > >
> > > > There's room for improvement in the documentation. I think it would be
> > > > clearer if you explained the big picture in
> > > > Documentation/userspace-api/media/v4l/extensible-parameters.rst
> > >
> > > My bad, that should be Documentation/driver-api/media/v4l2-isp.rst.
> > >
> > > > (pre-validation, copy and post-validation), and only focussed on what
> > > > those two functions do in their kerneldoc. That can be done later,
> > > > nothing that you say here is incorrect.
> > > >
> > > > With the other comments addressed,
> > > >
> > > > Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> > > >
> > > > > + */
> > > > > +int v4l2_params_blocks_validate(struct device *dev,
> > > > > + const struct v4l2_params_buffer *buffer,
> > > > > + const struct v4l2_params_handler *handlers,
> > > > > + size_t num_handlers);
> > > > > +
> > > > > +#endif /* V4L2_PARAMS_H_ */
>
> --
> Regards,
>
> Laurent Pinchart
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c
2025-10-06 15:00 ` Jacopo Mondi
@ 2025-10-06 15:41 ` Laurent Pinchart
0 siblings, 0 replies; 32+ messages in thread
From: Laurent Pinchart @ 2025-10-06 15:41 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Dafna Hirschfeld, Keke Li, Mauro Carvalho Chehab, Heiko Stuebner,
Dan Scally, Sakari Ailus, Antoine Bouyer, linux-kernel,
linux-media, linux-rockchip, linux-arm-kernel
On Mon, Oct 06, 2025 at 05:00:02PM +0200, Jacopo Mondi wrote:
> On Mon, Oct 06, 2025 at 05:51:46PM +0300, Laurent Pinchart wrote:
> > On Mon, Oct 06, 2025 at 12:28:01PM +0200, Jacopo Mondi wrote:
> > > On Mon, Oct 06, 2025 at 04:08:06AM +0300, Laurent Pinchart wrote:
> > > > On Mon, Oct 06, 2025 at 03:47:43AM +0300, Laurent Pinchart wrote:
> > > > > On Mon, Sep 15, 2025 at 07:18:14PM +0200, Jacopo Mondi wrote:
> > > > > > Add to the v4l2 framework helper functions to support drivers
> > > > >
> > > > > s/v4l2/V4L2/
> > > > >
> > > > > > when validating a buffer of extensible ISP parameters.
> > > > > >
> > > > > > Introduce new types in include/media/v4l2-isp.h that drivers shall use
> > > > > > in order to comply with the generic ISP parameters validation procedure,
> > > > > > and add helper functionss to v4l2-isp.c to perform blocks and buffer
> > > > > > validation.
> > > > > >
> > > > > > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> > > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > > > ---
> > > > > > MAINTAINERS | 2 +
> > > > > > drivers/media/v4l2-core/Kconfig | 4 ++
> > > > > > drivers/media/v4l2-core/Makefile | 1 +
> > > > > > drivers/media/v4l2-core/v4l2-isp.c | 108 +++++++++++++++++++++++++++++++++++++
> > > > > > include/media/v4l2-isp.h | 100 ++++++++++++++++++++++++++++++++++
> > > > > > 5 files changed, 215 insertions(+)
> > > > > >
> > > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > > index abba872cb63f1430a49a2afbace4b9f9958c3991..5e0e4208ebe6c58a9ea0834e1ebb36abd2de06e1 100644
> > > > > > --- a/MAINTAINERS
> > > > > > +++ b/MAINTAINERS
> > > > > > @@ -26415,6 +26415,8 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > > > L: linux-media@vger.kernel.org
> > > > > > S: Maintained
> > > > > > F: Documentation/userspace-api/media/v4l/extensible-parameters.rst
> > > > > > +F: drivers/media/v4l2-core/v4l2-isp.c
> > > > > > +F: include/media/v4l2-isp.h
> > > > > > F: include/uapi/linux/media/v4l2-isp.h
> > > > > >
> > > > > > VF610 NAND DRIVER
> > > > > > diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
> > > > > > index 331b8e535e5bbf33f22638b2ae8bc764ad5fc407..d50ccac9733cc39a43426ae7e7996dd0b5b45186 100644
> > > > > > --- a/drivers/media/v4l2-core/Kconfig
> > > > > > +++ b/drivers/media/v4l2-core/Kconfig
> > > > > > @@ -82,3 +82,7 @@ config V4L2_CCI_I2C
> > > > > > depends on I2C
> > > > > > select REGMAP_I2C
> > > > > > select V4L2_CCI
> > > > > > +
> > > > > > +config V4L2_ISP
> > > > > > + tristate
> > > > > > + depends on VIDEOBUF2_CORE
> > > > > > diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> > > > > > index 2177b9d63a8ffc1127c5a70118249a2ff63cd759..329f0eadce994cc1c8580beb435f68fa7e2a7aeb 100644
> > > > > > --- a/drivers/media/v4l2-core/Makefile
> > > > > > +++ b/drivers/media/v4l2-core/Makefile
> > > > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o
> > > > > > obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
> > > > > > obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
> > > > > > obj-$(CONFIG_V4L2_H264) += v4l2-h264.o
> > > > > > +obj-$(CONFIG_V4L2_ISP) += v4l2-isp.o
> > > > > > obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o
> > > > > > obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
> > > > > > obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o
> > > > > > diff --git a/drivers/media/v4l2-core/v4l2-isp.c b/drivers/media/v4l2-core/v4l2-isp.c
> > > > > > new file mode 100644
> > > > > > index 0000000000000000000000000000000000000000..e350bdaf53b5502e1ec2a4989c20df1100ab2d2a
> > > > > > --- /dev/null
> > > > > > +++ b/drivers/media/v4l2-core/v4l2-isp.c
> > > > > > @@ -0,0 +1,108 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > > +/*
> > > > > > + * Video4Linux2 generic ISP parameters and statistics support
> > > > > > + *
> > > > > > + * Copyright (C) 2025 Ideas On Board Oy
> > > > > > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > > > + */
> > > > > > +
> > > > > > +#include <linux/bitops.h>
> > > > > > +#include <linux/device.h>
> > > > > > +
> > > > > > +#include <media/videobuf2-core.h>
> > > > > > +#include <media/v4l2-isp.h>
> > > > >
> > > > > v4l2-isp goes first.
> > > > >
> > > > > > +
> > > > > > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > > > > > + size_t max_size)
> > > > > > +{
> > > > > > + size_t header_size = offsetof(struct v4l2_params_buffer, data);
> > > > > > + struct v4l2_params_buffer *buffer = vb2_plane_vaddr(vb, 0);
> > > > > > + size_t payload_size = vb2_get_plane_payload(vb, 0);
> > > > > > + size_t buffer_size;
> > > > > > +
> > > > > > + /* Payload size can't be greater than the destination buffer size */
> > > > > > + if (payload_size > max_size) {
> > > > > > + dev_dbg(dev, "Payload size is too large: %zu\n", payload_size);
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + /* Payload size can't be smaller than the header size */
> > > > > > + if (payload_size < header_size) {
> > > > > > + dev_dbg(dev, "Payload size is too small: %zu\n", payload_size);
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + /* Validate the size reported in the parameter buffer header */
> > > > > > + buffer_size = header_size + buffer->data_size;
> > > > > > + if (buffer_size != payload_size) {
> > > > > > + dev_dbg(dev, "Data size %zu and payload size %zu are different\n",
> > > > > > + buffer_size, payload_size);
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > >
> > > > > This check needs to go to v4l2_params_blocks_validate() as it has to be
> > > > > performed on the data after copying.
> > > > >
> > >
> > > I'm not sure. The aim of pre-validation (if we want to call it in this
> > > way) is to check the correctness of the userspace provided buffer, and
> > > the function as its main argument the vb2 buffer pointer for this
> > > reason.
> > >
> > > Isn't it important to check that the sizes are correct before doing a
> > > mem copy ?
> >
> > This check reads buffer->data_size. It can be modified by userspace
> > after the check and before doing the copy, which will lead to an invalid
> > value being used in v4l2_params_blocks_validate(). Pre-copy validation
> > can't use anything from within the buffer.
>
> The helper is intended to be called in the .buf_prepare callback,
> which is in the QBUF ioctl call path. Is there a window where
> userspace could modify the buffer during the ioctl call ?
Yes, you can have a multi-threaded process in userspace. This is why
validation of buffer->data_size is performed on the copied data today in
the rkisp1 and amlogic-c3 drivers, I think this needs to be preserved.
> > > > > > +
> > > > > > + return 0;
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(v4l2_params_buffer_validate);
> > > > > > +
> > > > > > +int v4l2_params_blocks_validate(struct device *dev,
> > > > > > + const struct v4l2_params_buffer *buffer,
> > > > > > + const struct v4l2_params_handler *handlers,
> > > > > > + size_t num_handlers)
> > >
> > > While the actual "validation" checks the content of v4l2_params_buffer
> > > after it has been copied to a kernel-only memory location. If I would
> > > have to check its size I would have to receive here the vb2 buffer size
> > > as argument (which the drivers should have just used as argument to
> > > the memcpy). It feels a bit mixing two things (that's also why I liked
> > > having a 'buffer validate' and a 'blocks validate' function, but I
> > > won't argue)
>
> Could you provide then the design for a nice interface where the vb2
> buffer size can be passed to this function if validation of the vb2
> buffer size should be moved here ?
I may be missing the problem. Both helpers are called from
.buf_prepare(), where the video buffer is available. In the rkisp1
driver for instance, they are both called from
rkisp1_params_prepare_ext_params(). You can pass the video buffer
pointer to this function.
Another option would be to move the memcpy to the helpers. There would
then be a single call to a helper (but the helper would still be
structured in the same way internally, the contents of the buffer would
need to be validated after the copy). I haven't checked if that would
lead to a too restrictive architecture though, it may not accommodate
the needs of all drivers.
> > > > > > +{
> > > > > > + size_t block_offset = 0;
> > > > > > + size_t buffer_size;
> > > > > > +
> > > > > > + /* Walk the list of parameter blocks and validate them. */
> > > > > > + buffer_size = buffer->data_size;
> > > > > > + while (buffer_size >= sizeof(struct v4l2_params_block_header)) {
> > > > > > + const struct v4l2_params_handler *handler;
> > > > > > + const struct v4l2_params_block_header *block;
> > > > > > +
> > > > > > + /* Validate block sizes and types against the handlers. */
> > > > > > + block = (const struct v4l2_params_block_header *)
> > > > > > + (buffer->data + block_offset);
> > > > > > +
> > > > > > + if (block->type >= num_handlers) {
> > > > > > + dev_dbg(dev, "Invalid parameters block type\n");
> > > > >
> > > > > I'd print the type and offset in the message to ease debugging.
> > > > >
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + if (block->size > buffer_size) {
> > > > > > + dev_dbg(dev, "Premature end of parameters data\n");
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + /* It's invalid to specify both ENABLE and DISABLE. */
> > > > > > + if ((block->flags & (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > > > > > + V4L2_PARAMS_FL_BLOCK_DISABLE)) ==
> > > > > > + (V4L2_PARAMS_FL_BLOCK_ENABLE |
> > > > > > + V4L2_PARAMS_FL_BLOCK_DISABLE)) {
> > > > > > + dev_dbg(dev, "Invalid parameters block flags\n");
> > > > >
> > > > > Same here (print the flags and offset).
> > > > >
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + /*
> > > > > > + * Match the block reported size against the handler's expected
> > > > > > + * one, but allow the block to only contain the header in
> > > > > > + * case it is going to be disabled.
> > > > > > + */
> > > > > > + handler = &handlers[block->type];
> > > > > > + if (block->size != handler->size &&
> > > > > > + (!(block->flags & V4L2_PARAMS_FL_BLOCK_DISABLE) ||
> > > > > > + block->size != sizeof(*block))) {
> > > > > > + dev_dbg(dev, "Invalid parameters block size\n");
> > > > >
> > > > > And here too (print the size and offset).
> > > > >
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + block_offset += block->size;
> > > > > > + buffer_size -= block->size;
> > > > > > + }
> > > > > > +
> > > > > > + if (buffer_size) {
> > > > > > + dev_dbg(dev, "Unexpected data after the parameters buffer end\n");
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + return 0;
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(v4l2_params_blocks_validate);
> > > > > > diff --git a/include/media/v4l2-isp.h b/include/media/v4l2-isp.h
> > > > > > new file mode 100644
> > > > > > index 0000000000000000000000000000000000000000..2ad62c6169eef3d0fb8d245de56cc6bd7e6227e4
> > > > > > --- /dev/null
> > > > > > +++ b/include/media/v4l2-isp.h
> > > > > > @@ -0,0 +1,100 @@
> > > > > > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > > > > > +/*
> > > > > > + * Video4Linux2 generic ISP parameters and statistics support
> > > > > > + *
> > > > > > + * Copyright (C) 2025 Ideas On Board Oy
> > > > > > + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > > > > > + */
> > > > > > +
> > > > > > +#ifndef V4L2_PARAMS_H_
> > > > > > +#define V4L2_PARAMS_H_
> > > > >
> > > > > V4L2_ISP_H_
> > > > >
> > > > > > +
> > > > > > +#include <linux/media/v4l2-isp.h>
> > > > > > +
> > > > > > +struct device;
> > > > > > +struct vb2_buffer;
> > > > > > +
> > > > > > +/**
> > > > > > + * typedef v4l2_params_block_handler - V4L2 extensible format block handler
> > > > >
> > > > > As commented on 1/8, let's use the v4l2_isp_ prefix.
> > > > >
> > > > > > + * @arg: pointer the driver-specific argument
> > > > > > + * @block: the ISP configuration block to handle
> > > > > > + *
> > > > > > + * Defines the function signature of the functions that handle an ISP block
> > > > > > + * configuration.
> > > > > > + */
> > > > > > +typedef void (*v4l2_params_block_handler)(void *arg,
> > > > > > + const struct v4l2_params_block_header *block);
> > > > > > +
> > > > > > +/**
> > > > > > + * struct v4l2_params_handler - V4L2 extensible format handler
> > > > > > + * @size: the block expected size
> > > > > > + * @handler: the block handler function
> > > > > > + *
> > > > > > + * The v4l2_params_handler defines the type that driver making use of the
> > > > > > + * V4L2 extensible parameters shall use to define their own ISP block
> > > > > > + * handlers.
> > > > > > + *
> > > > > > + * Drivers shall prepare a list of handlers, one for each supported ISP block
> > > > > > + * and correctly populate the structure's field with the expected block @size
> > > > > > + * (used for validation) and a pointer to each block @handler function.
> > > > > > + */
> > > > > > +struct v4l2_params_handler {
> > > > > > + size_t size;
> > > > > > + v4l2_params_block_handler handler;
> > > > > > +};
> > > > > > +
> > > > > > +/**
> > > > > > + * v4l2_params_buffer_validate - Validate a V4L2 extensible parameters buffer
> > > > >
> > > > > As this is the pre-copy validation, what would you think of calling the
> > > > > function v4l2_isp_params_pre_validate_buffer() ? The next function would
> > > > > be called v4l2_isp_params_validate_buffer(), as they're both about
> > > > > buffer validation. I'm also OK to keep the current names (with a
> > > > > v4l2_isp_ prefix).
> > > > >
> > > > > I'm also thinking that the copy could be moved to the helper, but it can
> > > > > be done later.
> > > > >
> > > > > > + * @dev: the driver's device pointer
> > > > > > + * @vb: the videobuf2 buffer
> > > > > > + * @max_size: the maximum allowed buffer size
> > > > > > + * @buffer_validate: callback to the driver-specific buffer validation
> > > > >
> > > > > You forgot to drop the documentation for this argument.
> > > > >
> > > > > > + *
> > > > > > + * Helper function that performs validation of an extensible parameters buffer.
> > > > > > + *
> > > > > > + * The helper is meant to be used by drivers to perform validation of the
> > > > > > + * extensible parameters buffer size correctness.
> > > > > > + *
> > > > > > + * The @vb buffer as received from the vb2 .buf_prepare() operation is checked
> > > > > > + * against @max_size and its validated to be large enough to accommodate at
> > > > > > + * least one ISP configuration block. The effective buffer size is compared
> > > > > > + * with the reported data size to make sure they match.
> > > > > > + *
> > > > > > + * Drivers should use this function to validate the buffer size correctness
> > > > > > + * before performing a copy of the user-provided videobuf2 buffer content into a
> > > > > > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > > > > > + * content after it has been submitted to the driver.
> > > > > > + */
> > > > > > +int v4l2_params_buffer_validate(struct device *dev, struct vb2_buffer *vb,
> > > > > > + size_t max_size);
> > > > > > +
> > > > > > +/**
> > > > > > + * v4l2_params_blocks_validate - Validate V4L2 extensible parameters ISP
> > > > > > + * configuration blocks
> > > > > > + * @dev: the driver's device pointer
> > > > > > + * @buffer: the extensible parameters configuration buffer
> > > > > > + * @handlers: the list of block handlers
> > > > >
> > > > > array of block handlers
> > > > >
> > > > > > + * @num_handlers: the number of block handlers
> > > > > > + *
> > > > > > + * Helper function that performs validation of the ISP configuration blocks in
> > > > > > + * an extensible parameters buffer.
> > > > > > + *
> > > > > > + * The helper is meant to be used by drivers to perform validation of the
> > > > > > + * ISP configuration data blocks. For each block in the extensible parameters
> > > > > > + * buffer, its size and correctness are validated against its associated handler
> > > > > > + * in the @handlers list.
> > > > >
> > > > > You need to explain somewhere that the handlers array is indexed by
> > > > > block type.
> > > > >
> > > > > > + *
> > > > > > + * Drivers should use this function to validate the ISP configuration blocks
> > > > > > + * after having validated the correctness of the vb2 buffer sizes by using the
> > > > > > + * v4l2_params_buffer_validate() helper first. Once the buffer size has been
> > > > > > + * validated, drivers should perform a copy of the user-provided buffer into a
> > > > > > + * kernel-only memory buffer to prevent userspace from modifying the buffer
> > > > > > + * content after it has been submitted to the driver, and then call this
> > > > > > + * function to perform per-block validation.
> > > > >
> > > > > There's room for improvement in the documentation. I think it would be
> > > > > clearer if you explained the big picture in
> > > > > Documentation/userspace-api/media/v4l/extensible-parameters.rst
> > > >
> > > > My bad, that should be Documentation/driver-api/media/v4l2-isp.rst.
> > > >
> > > > > (pre-validation, copy and post-validation), and only focussed on what
> > > > > those two functions do in their kerneldoc. That can be done later,
> > > > > nothing that you say here is incorrect.
> > > > >
> > > > > With the other comments addressed,
> > > > >
> > > > > Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> > > > >
> > > > > > + */
> > > > > > +int v4l2_params_blocks_validate(struct device *dev,
> > > > > > + const struct v4l2_params_buffer *buffer,
> > > > > > + const struct v4l2_params_handler *handlers,
> > > > > > + size_t num_handlers);
> > > > > > +
> > > > > > +#endif /* V4L2_PARAMS_H_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2025-10-06 15:41 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-15 17:18 [PATCH v5 0/8] media: Introduce V4L2 generic ISP support Jacopo Mondi
2025-09-15 17:18 ` [PATCH v5 1/8] media: uapi: Introduce V4L2 generic ISP types Jacopo Mondi
2025-10-05 0:06 ` Laurent Pinchart
2025-10-06 0:07 ` Laurent Pinchart
2025-10-06 8:15 ` Dan Scally
2025-10-06 8:27 ` Laurent Pinchart
2025-10-06 8:46 ` Dan Scally
2025-10-06 9:06 ` Laurent Pinchart
2025-10-06 9:51 ` Dan Scally
2025-10-06 9:58 ` Laurent Pinchart
2025-10-06 10:26 ` Dan Scally
2025-10-06 14:47 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 2/8] media: uapi: Convert RkISP1 to V4L2 extensible params Jacopo Mondi
2025-10-05 0:18 ` Laurent Pinchart
2025-10-06 8:17 ` Dan Scally
2025-09-15 17:18 ` [PATCH v5 3/8] media: uapi: Convert Amlogic C3 " Jacopo Mondi
2025-10-05 0:24 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 4/8] media: Documentation: uapi: Add V4L2 extensible parameters Jacopo Mondi
2025-10-06 1:17 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 5/8] media: v4l2-core: Introduce v4l2-isp.c Jacopo Mondi
2025-10-06 0:47 ` Laurent Pinchart
2025-10-06 1:08 ` Laurent Pinchart
2025-10-06 10:28 ` Jacopo Mondi
2025-10-06 14:51 ` Laurent Pinchart
2025-10-06 15:00 ` Jacopo Mondi
2025-10-06 15:41 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 6/8] media: rkisp1: Use v4l2-isp for validation Jacopo Mondi
2025-10-06 1:06 ` Laurent Pinchart
2025-09-15 17:18 ` [PATCH v5 7/8] media: amlogic-c3: " Jacopo Mondi
2025-09-15 17:18 ` [PATCH v5 8/8] media: Documentation: kapi: Add v4l2 generic ISP support Jacopo Mondi
2025-10-06 1:18 ` Laurent Pinchart
2025-10-02 8:17 ` [PATCH v5 0/8] media: Introduce V4L2 " Sakari Ailus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).