* [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters
@ 2024-07-03 16:10 Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 1/7] uapi: rkisp1-config: Add extensible parameters format Jacopo Mondi
` (6 more replies)
0 siblings, 7 replies; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-03 16:10 UTC (permalink / raw)
To: Linux Media Mailing List
Cc: Jacopo Mondi, Laurent Pinchart, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
v4->v5:
- Refine validation of the ext params buffer following Laurent's suggestion
- perform memcpy of the parameters buffer after sizes validation
v3->v4:
- Introduce 'union rkisp1_ext_params_config' to avoid casts in the block
handlers
v2->v3:
- Address Laurent's comments on the uAPI:
- rename $block_config with just 'config'
- reduce header size
- rename a few fields/blocks
- Address Laurent's comment on the params node:
- Use the plane payload for memcpy() and buffer validation
- drop buf_out_validate() and use buf_prepare() only
- validate the total buffer size against the buffer payload
- use const pointers where possible
v1->v2:
- re-order patches to introduce parameters buffer caching for the existing
"fixed" format before introducing the "extensible" format
- align all structures to 64-bit boundaries in the uAPI
- remove NO_CHANGE enablement state and cache a bitmask of enabled blocks
- address review comments in documentation
The VeriSilicon ISP8000 IP, supported through the rkisp1 driver in the Linux
kernel, is integrated in several SoCs from different vendors. Different
revisions of the IP differ in the number of supported features and in the
register space location assigned to specific ISP blocks.
The current configuration parameters format, defined in
include/uapi/linux/rkisp1-config.h is realized by a C structure (struct
rkisp1_params_cfg) which wraps other structures that allows to configure
specific ISP blocks. The layout of the parameters buffer is part of the Linux
kernel uAPI and can hardly be extended or modified to adapt it to different
revisions of the same IP.
This series proposes the introduction of a new parameters format for the RkISP1
(without dropping support for the existing one) which is designed with the goals
of being:
1) versioned: can be changed without breaking existing applications
2) extensible: new blocks and parameters can be added without breaking the uABI
To do so, a new 'struct rkisp1_ext_params_cfg' type is introduced. It wraps an
header and a data buffer, which userspace fills with configuration blocks
for each ISP block it intends to configure. The parameters buffer is thus of
different effective sizes, depending on the number of blocks userspace intends
to configure.
The kernel driver parses the data block and decides, based on the versioning
number and the platform it operates on, how to handle each block.
The parameters format is very similar to the parameters format implemented
in the in-review Mali C55 ISP driver [1]
CI pipeline [2]
[1] https://lore.kernel.org/linux-media/20240529152858.183799-15-dan.scally@ideasonboard.com/
[2] https://gitlab.freedesktop.org/linux-media/users/jmondi/-/pipelines/1216396
Jacopo Mondi (7):
uapi: rkisp1-config: Add extensible parameters format
uapi: videodev2: Add V4L2_META_FMT_RK_ISP1_EXT_PARAMS
media: rkisp1: Add struct rkisp1_params_buffer
media: rkisp1: Copy the parameters buffer
media: rkisp1: Cache the currently active format
media: rkisp1: Implement extensible params support
media: rkisp1: Implement s_fmt/try_fmt
Documentation/admin-guide/media/rkisp1.rst | 11 +-
.../media/v4l/metafmt-rkisp1.rst | 57 +-
.../platform/rockchip/rkisp1/rkisp1-common.h | 31 +-
.../platform/rockchip/rkisp1/rkisp1-params.c | 764 ++++++++++++++++--
drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
include/uapi/linux/rkisp1-config.h | 489 +++++++++++
include/uapi/linux/videodev2.h | 1 +
7 files changed, 1284 insertions(+), 70 deletions(-)
--
2.45.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v5 1/7] uapi: rkisp1-config: Add extensible parameters format
2024-07-03 16:10 [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters Jacopo Mondi
@ 2024-07-03 16:10 ` Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 2/7] uapi: videodev2: Add V4L2_META_FMT_RK_ISP1_EXT_PARAMS Jacopo Mondi
` (5 subsequent siblings)
6 siblings, 0 replies; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-03 16:10 UTC (permalink / raw)
To: Linux Media Mailing List
Cc: Jacopo Mondi, Laurent Pinchart, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
Add to the rkisp1-config.h header data types and documentation of
the extensible parameters format.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
---
include/uapi/linux/rkisp1-config.h | 489 +++++++++++++++++++++++++++++
1 file changed, 489 insertions(+)
diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
index 6eeaf8bf2362..00b09c92cca7 100644
--- a/include/uapi/linux/rkisp1-config.h
+++ b/include/uapi/linux/rkisp1-config.h
@@ -996,4 +996,493 @@ struct rkisp1_stat_buffer {
struct rkisp1_cif_isp_stat params;
};
+/*---------- PART3: Extensible Configuration Parameters ------------*/
+
+/**
+ * enum rkisp1_ext_params_block_type - RkISP1 extensible params block type
+ *
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS: Black level subtraction
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC: Defect pixel cluster correction
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG: Sensor de-gamma
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN: Auto white balance gains
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT: ISP filtering
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM: Bayer de-mosaic
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK: Cross-talk correction
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC: Gamma out correction
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF: De-noise pre-filter
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH: De-noise pre-filter strength
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC: Color processing
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_IE: Image effects
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC: Lens shading correction
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS: Auto white balance statistics
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS: Histogram statistics
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS: Auto exposure statistics
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS: Auto-focus statistics
+ */
+enum rkisp1_ext_params_block_type {
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_IE,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS,
+};
+
+/**
+ * enum rkisp1_ext_params_block_enable - RkISP1 extensible parameter block
+ * enable flags
+ *
+ * @RKISP1_EXT_PARAMS_BLOCK_DISABLE: Disable the HW block
+ * @RKISP1_EXT_PARAMS_BLOCK_ENABLE: Enable the HW block
+ */
+enum rkisp1_ext_params_block_enable {
+ RKISP1_EXT_PARAMS_BLOCK_DISABLE,
+ RKISP1_EXT_PARAMS_BLOCK_ENABLE,
+};
+
+/**
+ * struct rkisp1_ext_params_block_header - RkISP1 extensible 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:`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 @enable field specifies the ISP block enablement state. The possible
+ * enablement states are enumerated by :c:type:`rkisp1_ext_params_block_enable`.
+ * When userspace needs to configure and enable an ISP block it shall fully
+ * populate the block configuration and the @enable flag shall be set to
+ * RKISP1_EXT_PARAMS_BLOCK_ENABLE. When userspace simply wants to disable the
+ * ISP block the @enable flag shall be set to RKISP1_EXT_PARAMS_BLOCK_DISABLE.
+ * 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 set the @enable flag to
+ * RKISP1_EXT_PARAMS_BLOCK_ENABLE.
+ *
+ * Userspace is responsible for correctly populating the parameters block header
+ * fields (@type, @enable and @size) and the block-specific parameters.
+ *
+ * For example:
+ *
+ * .. 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.enable = RKISP1_EXT_PARAMS_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`
+ * @enable: The block enable flag, see
+ * :c:type:`rkisp1_ext_params_block_enable`
+ * @size: Size (in bytes) of the parameters block, including this header
+ */
+struct rkisp1_ext_params_block_header {
+ __u16 type;
+ __u16 enable;
+ __u16 size;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_bls_config - RkISP1 extensible params BLS config
+ *
+ * RkISP1 extensible parameters Black Level Subtraction configuration block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Black Level Subtraction configuration, see
+ * :c:type:`rkisp1_cif_isp_bls_config`
+ */
+struct rkisp1_ext_params_bls_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_bls_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_dpcc_config - RkISP1 extensible params DPCC config
+ *
+ * RkISP1 extensible parameters Defective Pixel Cluster Correction configuration
+ * block. Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Defective Pixel Cluster Correction configuration, see
+ * :c:type:`rkisp1_cif_isp_dpcc_config`
+ */
+struct rkisp1_ext_params_dpcc_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_dpcc_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_sdg_config - RkISP1 extensible params SDG config
+ *
+ * RkISP1 extensible parameters Sensor Degamma configuration block. Identified
+ * by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Sensor Degamma configuration, see
+ * :c:type:`rkisp1_cif_isp_sdg_config`
+ */
+struct rkisp1_ext_params_sdg_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_sdg_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_lsc_config - RkISP1 extensible params LSC config
+ *
+ * RkISP1 extensible parameters Lens Shading Correction configuration block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Lens Shading Correction configuration, see
+ * :c:type:`rkisp1_cif_isp_lsc_config`
+ */
+struct rkisp1_ext_params_lsc_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_lsc_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_awb_gain_config - RkISP1 extensible params AWB
+ * gain config
+ *
+ * RkISP1 extensible parameters Auto-White Balance Gains configuration block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Auto-White Balance Gains configuration, see
+ * :c:type:`rkisp1_cif_isp_awb_gain_config`
+ */
+struct rkisp1_ext_params_awb_gain_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_awb_gain_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_flt_config - RkISP1 extensible params FLT config
+ *
+ * RkISP1 extensible parameters Filter configuration block. Identified by
+ * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Filter configuration, see :c:type:`rkisp1_cif_isp_flt_config`
+ */
+struct rkisp1_ext_params_flt_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_flt_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_bdm_config - RkISP1 extensible params BDM config
+ *
+ * RkISP1 extensible parameters Demosaicing configuration block. Identified by
+ * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Demosaicing configuration, see :c:type:`rkisp1_cif_isp_bdm_config`
+ */
+struct rkisp1_ext_params_bdm_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_bdm_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_ctk_config - RkISP1 extensible params CTK config
+ *
+ * RkISP1 extensible parameters Cross-Talk configuration block. Identified by
+ * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Cross-Talk configuration, see :c:type:`rkisp1_cif_isp_ctk_config`
+ */
+struct rkisp1_ext_params_ctk_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_ctk_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_goc_config - RkISP1 extensible params GOC config
+ *
+ * RkISP1 extensible parameters Gamma-Out configuration block. Identified by
+ * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Gamma-Out configuration, see :c:type:`rkisp1_cif_isp_goc_config`
+ */
+struct rkisp1_ext_params_goc_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_goc_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_dpf_config - RkISP1 extensible params DPF config
+ *
+ * RkISP1 extensible parameters De-noise Pre-Filter configuration block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: De-noise Pre-Filter configuration, see
+ * :c:type:`rkisp1_cif_isp_dpf_config`
+ */
+struct rkisp1_ext_params_dpf_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_dpf_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_dpf_strength_config - RkISP1 extensible params DPF
+ * strength config
+ *
+ * RkISP1 extensible parameters De-noise Pre-Filter strength configuration
+ * block. Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: De-noise Pre-Filter strength configuration, see
+ * :c:type:`rkisp1_cif_isp_dpf_strength_config`
+ */
+struct rkisp1_ext_params_dpf_strength_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_dpf_strength_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_cproc_config - RkISP1 extensible params CPROC config
+ *
+ * RkISP1 extensible parameters Color Processing configuration block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Color processing configuration, see
+ * :c:type:`rkisp1_cif_isp_cproc_config`
+ */
+struct rkisp1_ext_params_cproc_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_cproc_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_ie_config - RkISP1 extensible params IE config
+ *
+ * RkISP1 extensible parameters Image Effect configuration block. Identified by
+ * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_IE`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Image Effect configuration, see :c:type:`rkisp1_cif_isp_ie_config`
+ */
+struct rkisp1_ext_params_ie_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_ie_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_awb_meas_config - RkISP1 extensible params AWB
+ * Meas config
+ *
+ * RkISP1 extensible parameters Auto-White Balance Measurement configuration
+ * block. Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Auto-White Balance measure configuration, see
+ * :c:type:`rkisp1_cif_isp_awb_meas_config`
+ */
+struct rkisp1_ext_params_awb_meas_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_awb_meas_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_hst_config - RkISP1 extensible params Histogram config
+ *
+ * RkISP1 extensible parameters Histogram statistics configuration block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Histogram statistics configuration, see
+ * :c:type:`rkisp1_cif_isp_hst_config`
+ */
+struct rkisp1_ext_params_hst_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_hst_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_aec_config - RkISP1 extensible params AEC config
+ *
+ * RkISP1 extensible parameters Auto-Exposure statistics configuration block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Auto-Exposure statistics configuration, see
+ * :c:type:`rkisp1_cif_isp_aec_config`
+ */
+struct rkisp1_ext_params_aec_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_aec_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_afc_config - RkISP1 extensible params AFC config
+ *
+ * RkISP1 extensible parameters Auto-Focus statistics configuration block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Auto-Focus statistics configuration, see
+ * :c:type:`rkisp1_cif_isp_afc_config`
+ */
+struct rkisp1_ext_params_afc_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_afc_config config;
+} __attribute__((aligned(8)));
+
+#define RKISP1_EXT_PARAMS_MAX_SIZE \
+ (sizeof(struct rkisp1_ext_params_bls_config) +\
+ sizeof(struct rkisp1_ext_params_dpcc_config) +\
+ sizeof(struct rkisp1_ext_params_sdg_config) +\
+ sizeof(struct rkisp1_ext_params_lsc_config) +\
+ sizeof(struct rkisp1_ext_params_awb_gain_config) +\
+ sizeof(struct rkisp1_ext_params_flt_config) +\
+ sizeof(struct rkisp1_ext_params_bdm_config) +\
+ sizeof(struct rkisp1_ext_params_ctk_config) +\
+ sizeof(struct rkisp1_ext_params_goc_config) +\
+ sizeof(struct rkisp1_ext_params_dpf_config) +\
+ sizeof(struct rkisp1_ext_params_dpf_strength_config) +\
+ sizeof(struct rkisp1_ext_params_cproc_config) +\
+ sizeof(struct rkisp1_ext_params_ie_config) +\
+ sizeof(struct rkisp1_ext_params_awb_meas_config) +\
+ sizeof(struct rkisp1_ext_params_hst_config) +\
+ sizeof(struct rkisp1_ext_params_aec_config) +\
+ sizeof(struct rkisp1_ext_params_afc_config))
+
+/**
+ * enum rksip1_ext_param_buffer_version - RkISP1 extensible parameters version
+ *
+ * @RKISP1_EXT_PARAM_BUFFER_V1: First version of RkISP1 extensible parameters
+ */
+enum rksip1_ext_param_buffer_version {
+ RKISP1_EXT_PARAM_BUFFER_V1 = 1,
+};
+
+/**
+ * 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.
+ *
+ * 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 -------------------+
+ * | version = RKISP_EXT_PARAMS_BUFFER_V1; |
+ * | data_size = sizeof(struct rkisp1_ext_params_bls_config) |
+ * | + sizeof(struct rkisp1_ext_params_dpcc_config); |
+ * | +------------------------- data ---------------------------------+ |
+ * | | +------------- struct rkisp1_ext_params_bls_config -----------+ | |
+ * | | | +-------- struct rkisp1_ext_params_block_header ---------+ | | |
+ * | | | | type = RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS; | | | |
+ * | | | | enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; | | | |
+ * | | | | size = sizeof(struct rkisp1_ext_params_bls_config); | | | |
+ * | | | +---------------------------------------------------------+ | | |
+ * | | | +---------- struct rkisp1_cif_isp_bls_config -------------+ | | |
+ * | | | | enable_auto = 0; | | | |
+ * | | | | fixed_val.r = 256; | | | |
+ * | | | | fixed_val.gr = 256; | | | |
+ * | | | | fixed_val.gb = 256; | | | |
+ * | | | | fixed_val.b = 256; | | | |
+ * | | | +---------------------------------------------------------+ | | |
+ * | | +------------ struct rkisp1_ext_params_dpcc_config -----------+ | |
+ * | | | +-------- struct rkisp1_ext_params_block_header ---------+ | | |
+ * | | | | type = RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC; | | | |
+ * | | | | enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; | | | |
+ * | | | | size = sizeof(struct rkisp1_ext_params_dpcc_config); | | | |
+ * | | | +---------------------------------------------------------+ | | |
+ * | | | +---------- struct rkisp1_cif_isp_dpcc_config ------------+ | | |
+ * | | | | mode = RKISP1_CIF_ISP_DPCC_MODE_STAGE1_ENABLE; | | | |
+ * | | | | output_mode = | | | |
+ * | | | | RKISP1_CIF_ISP_DPCC_OUTPUT_MODE_STAGE1_INCL_G_CENTER; | | | |
+ * | | | | set_use = ... ; | | | |
+ * | | | | ... = ... ; | | | |
+ * | | | +---------------------------------------------------------+ | | |
+ * | | +-------------------------------------------------------------+ | |
+ * | +-----------------------------------------------------------------+ |
+ * +---------------------------------------------------------------------+
+ *
+ * @version: The RkISP1 extensible parameters buffer version, see
+ * :c:type:`rksip1_ext_param_buffer_version`
+ * @data_size: The RkISP1 configuration data effective size, excluding this
+ * header
+ * @data: The RkISP1 extensible configuration data blocks
+ */
+struct rkisp1_ext_params_cfg {
+ __u32 version;
+ __u32 data_size;
+ __u8 data[RKISP1_EXT_PARAMS_MAX_SIZE];
+};
+
#endif /* _UAPI_RKISP1_CONFIG_H */
--
2.45.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v5 2/7] uapi: videodev2: Add V4L2_META_FMT_RK_ISP1_EXT_PARAMS
2024-07-03 16:10 [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 1/7] uapi: rkisp1-config: Add extensible parameters format Jacopo Mondi
@ 2024-07-03 16:10 ` Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 3/7] media: rkisp1: Add struct rkisp1_params_buffer Jacopo Mondi
` (4 subsequent siblings)
6 siblings, 0 replies; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-03 16:10 UTC (permalink / raw)
To: Linux Media Mailing List
Cc: Jacopo Mondi, Laurent Pinchart, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
The rkisp1 driver stores ISP configuration parameters in the fixed
rkisp1_params_cfg structure. As the members of the structure are part of
the userspace API, the structure layout is immutable and cannot be
extended further. Introducing new parameters or modifying the existing
ones would change the buffer layout and cause breakages in existing
applications.
The allow for future extensions to the ISP parameters, introduce a new
extensible parameters format, with a new format 4CC. Document usage of
the new format in the rkisp1 admin guide.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Documentation/admin-guide/media/rkisp1.rst | 11 +++-
.../media/v4l/metafmt-rkisp1.rst | 57 ++++++++++++++++---
drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
include/uapi/linux/videodev2.h | 1 +
4 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/Documentation/admin-guide/media/rkisp1.rst b/Documentation/admin-guide/media/rkisp1.rst
index 6f14d9561fa5..6c878c71442f 100644
--- a/Documentation/admin-guide/media/rkisp1.rst
+++ b/Documentation/admin-guide/media/rkisp1.rst
@@ -114,11 +114,18 @@ to be applied to the hardware during a video stream, allowing userspace
to dynamically modify values such as black level, cross talk corrections
and others.
-The buffer format is defined by struct :c:type:`rkisp1_params_cfg`, and
-userspace should set
+The ISP driver supports two different parameters configuration methods, the
+`fixed parameters format` or the `extensible parameters format`.
+
+When using the `fixed parameters` method the buffer format is defined by struct
+:c:type:`rkisp1_params_cfg`, and userspace should set
:ref:`V4L2_META_FMT_RK_ISP1_PARAMS <v4l2-meta-fmt-rk-isp1-params>` as the
dataformat.
+When using the `extensible parameters` method the buffer format is defined by
+struct :c:type:`rkisp1_ext_params_cfg`, and userspace should set
+:ref:`V4L2_META_FMT_RK_ISP1_EXT_PARAMS <v4l2-meta-fmt-rk-isp1-ext-params>` as
+the dataformat.
Capturing Video Frames Example
==============================
diff --git a/Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst b/Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst
index fa04f00bcd2e..4e3f4ea9e1c8 100644
--- a/Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst
+++ b/Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst
@@ -1,28 +1,67 @@
.. SPDX-License-Identifier: GPL-2.0
-.. _v4l2-meta-fmt-rk-isp1-params:
-
.. _v4l2-meta-fmt-rk-isp1-stat-3a:
-*****************************************************************************
-V4L2_META_FMT_RK_ISP1_PARAMS ('rk1p'), V4L2_META_FMT_RK_ISP1_STAT_3A ('rk1s')
-*****************************************************************************
+************************************************************************************************************************
+V4L2_META_FMT_RK_ISP1_PARAMS ('rk1p'), V4L2_META_FMT_RK_ISP1_STAT_3A ('rk1s'), V4L2_META_FMT_RK_ISP1_EXT_PARAMS ('rk1e')
+************************************************************************************************************************
+========================
Configuration parameters
========================
-The configuration parameters are passed to the
+The configuration of the RkISP1 ISP is performed by userspace by providing
+parameters for the ISP to the driver using the :c:type:`v4l2_meta_format`
+interface.
+
+There are two methods that allow to configure the ISP, the `fixed parameters`
+configuration format and the `extensible parameters` configuration
+format.
+
+.. _v4l2-meta-fmt-rk-isp1-params:
+
+Fixed parameters configuration format
+=====================================
+
+When using the fixed configuration format, parameters are passed to the
:ref:`rkisp1_params <rkisp1_params>` metadata output video node, using
-the :c:type:`v4l2_meta_format` interface. The buffer contains
-a single instance of the C structure :c:type:`rkisp1_params_cfg` defined in
-``rkisp1-config.h``. So the structure can be obtained from the buffer by:
+the `V4L2_META_FMT_RK_ISP1_PARAMS` meta format.
+
+The buffer contains a single instance of the C structure
+:c:type:`rkisp1_params_cfg` defined in ``rkisp1-config.h``. So the structure can
+be obtained from the buffer by:
.. code-block:: c
struct rkisp1_params_cfg *params = (struct rkisp1_params_cfg*) buffer;
+This method supports a subset of the ISP features only, new applications should
+use the extensible parameters method.
+
+.. _v4l2-meta-fmt-rk-isp1-ext-params:
+
+Extensible parameters configuration format
+==========================================
+
+When using the extensible configuration format, parameters are passed to the
+:ref:`rkisp1_params <rkisp1_params>` metadata output video node, using
+the `V4L2_META_FMT_RK_ISP1_EXT_PARAMS` meta format.
+
+The buffer contains a single instance of the C structure
+:c:type:`rkisp1_ext_params_cfg` defined in ``rkisp1-config.h``. The
+:c:type:`rkisp1_ext_params_cfg` structure is designed to allow userspace to
+populate the data buffer with only the configuration data for the ISP blocks it
+intends to configure. The extensible parameters format design allows developers
+to define new block types to support new configuration parameters, and defines a
+versioning scheme so that it can be extended and versioned without breaking
+compatibility with existing applications.
+
+For these reasons, this configuration method if preferred over the `fixed
+parameters` format alternative.
+
.. rkisp1_stat_buffer
+===========================
3A and histogram statistics
===========================
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 5eb4d797d259..257d69341953 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1458,6 +1458,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_META_FMT_VIVID: descr = "Vivid Metadata"; break;
case V4L2_META_FMT_RK_ISP1_PARAMS: descr = "Rockchip ISP1 3A Parameters"; break;
case V4L2_META_FMT_RK_ISP1_STAT_3A: descr = "Rockchip ISP1 3A Statistics"; break;
+ case V4L2_META_FMT_RK_ISP1_EXT_PARAMS: descr = "Rockchip ISP1 Ext 3A Params"; break;
case V4L2_PIX_FMT_NV12_8L128: descr = "NV12 (8x128 Linear)"; break;
case V4L2_PIX_FMT_NV12M_8L128: descr = "NV12M (8x128 Linear)"; break;
case V4L2_PIX_FMT_NV12_10BE_8L128: descr = "10-bit NV12 (8x128 Linear, BE)"; break;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 4e91362da6da..725e86c4bbbd 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -854,6 +854,7 @@ struct v4l2_pix_format {
/* Vendor specific - used for RK_ISP1 camera sub-system */
#define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P') /* Rockchip ISP1 3A Parameters */
#define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A Statistics */
+#define V4L2_META_FMT_RK_ISP1_EXT_PARAMS v4l2_fourcc('R', 'K', '1', 'E') /* Rockchip ISP1 3a Extensible Parameters */
/* Vendor specific - used for RaspberryPi PiSP */
#define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') /* PiSP BE configuration */
--
2.45.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v5 3/7] media: rkisp1: Add struct rkisp1_params_buffer
2024-07-03 16:10 [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 1/7] uapi: rkisp1-config: Add extensible parameters format Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 2/7] uapi: videodev2: Add V4L2_META_FMT_RK_ISP1_EXT_PARAMS Jacopo Mondi
@ 2024-07-03 16:10 ` Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 4/7] media: rkisp1: Copy the parameters buffer Jacopo Mondi
` (3 subsequent siblings)
6 siblings, 0 replies; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-03 16:10 UTC (permalink / raw)
To: Linux Media Mailing List
Cc: Jacopo Mondi, Laurent Pinchart, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
Create the 'struct rkisp1_params_buffer' type that wraps a
vb2_v4l2_buffer to prepare to hold a copy of the parameters buffer that
will be used to cache the user-provided configuration buffer in the
following patches.
Replace usage of 'struct rkisp1_buffer' with 'struct
rkisp1_params_buffer' in rkisp1-params.c to prepare for that.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
---
.../platform/rockchip/rkisp1/rkisp1-common.h | 14 ++++++++++++-
.../platform/rockchip/rkisp1/rkisp1-params.c | 21 ++++++++++---------
2 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index 26573f6ae575..a615bbb0255e 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -232,7 +232,7 @@ struct rkisp1_vdev_node {
/*
* struct rkisp1_buffer - A container for the vb2 buffers used by the video devices:
- * params, stats, mainpath, selfpath
+ * stats, mainpath, selfpath
*
* @vb: vb2 buffer
* @queue: entry of the buffer in the queue
@@ -244,6 +244,18 @@ struct rkisp1_buffer {
dma_addr_t buff_addr[VIDEO_MAX_PLANES];
};
+/*
+ * struct rkisp1_params_buffer - A container for the vb2 buffers used by the
+ * params video device
+ *
+ * @vb: vb2 buffer
+ * @queue: entry of the buffer in the queue
+ */
+struct rkisp1_params_buffer {
+ struct vb2_v4l2_buffer vb;
+ struct list_head queue;
+};
+
/*
* struct rkisp1_dummy_buffer - A buffer to write the next frame to in case
* there are no vb2 buffers available.
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 173d1ea41874..2844e55bc4f2 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -1502,20 +1502,21 @@ static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params,
}
static bool rkisp1_params_get_buffer(struct rkisp1_params *params,
- struct rkisp1_buffer **buf,
+ struct rkisp1_params_buffer **buf,
struct rkisp1_params_cfg **cfg)
{
if (list_empty(¶ms->params))
return false;
- *buf = list_first_entry(¶ms->params, struct rkisp1_buffer, queue);
+ *buf = list_first_entry(¶ms->params, struct rkisp1_params_buffer,
+ queue);
*cfg = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0);
return true;
}
static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
- struct rkisp1_buffer *buf,
+ struct rkisp1_params_buffer *buf,
unsigned int frame_sequence)
{
list_del(&buf->queue);
@@ -1528,7 +1529,7 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
{
struct rkisp1_params *params = &rkisp1->params;
struct rkisp1_params_cfg *new_params;
- struct rkisp1_buffer *cur_buf;
+ struct rkisp1_params_buffer *cur_buf;
spin_lock(¶ms->config_lock);
@@ -1604,7 +1605,7 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
{
struct rkisp1_cif_isp_hst_config hst = rkisp1_hst_params_default_config;
struct rkisp1_params_cfg *new_params;
- struct rkisp1_buffer *cur_buf;
+ struct rkisp1_params_buffer *cur_buf;
params->quantization = quantization;
params->ycbcr_encoding = ycbcr_encoding;
@@ -1650,7 +1651,7 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
void rkisp1_params_post_configure(struct rkisp1_params *params)
{
struct rkisp1_params_cfg *new_params;
- struct rkisp1_buffer *cur_buf;
+ struct rkisp1_params_buffer *cur_buf;
spin_lock_irq(¶ms->config_lock);
@@ -1821,8 +1822,8 @@ static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct rkisp1_buffer *params_buf =
- container_of(vbuf, struct rkisp1_buffer, vb);
+ struct rkisp1_params_buffer *params_buf =
+ container_of(vbuf, struct rkisp1_params_buffer, vb);
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_params *params = vq->drv_priv;
@@ -1844,7 +1845,7 @@ static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
{
struct rkisp1_params *params = vq->drv_priv;
- struct rkisp1_buffer *buf;
+ struct rkisp1_params_buffer *buf;
LIST_HEAD(tmp_list);
/*
@@ -1890,7 +1891,7 @@ static int rkisp1_params_init_vb2_queue(struct vb2_queue *q,
q->drv_priv = params;
q->ops = &rkisp1_params_vb2_ops;
q->mem_ops = &vb2_vmalloc_memops;
- q->buf_struct_size = sizeof(struct rkisp1_buffer);
+ q->buf_struct_size = sizeof(struct rkisp1_params_buffer);
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &node->vlock;
--
2.45.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v5 4/7] media: rkisp1: Copy the parameters buffer
2024-07-03 16:10 [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters Jacopo Mondi
` (2 preceding siblings ...)
2024-07-03 16:10 ` [PATCH v5 3/7] media: rkisp1: Add struct rkisp1_params_buffer Jacopo Mondi
@ 2024-07-03 16:10 ` Jacopo Mondi
2024-07-05 10:52 ` Paul Elder
2024-07-03 16:10 ` [PATCH v5 5/7] media: rkisp1: Cache the currently active format Jacopo Mondi
` (2 subsequent siblings)
6 siblings, 1 reply; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-03 16:10 UTC (permalink / raw)
To: Linux Media Mailing List
Cc: Jacopo Mondi, Laurent Pinchart, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
The ISP parameters buffers are queued by userspace to the params video
device and appended by the driver to the list of available buffers for
later consumption.
As the parameters buffer is mapped in the userspace process memory,
applications have access to the buffer content after the buffer has
been queued.
To prevent userspace from modifying the contents of the parameters buffer
after it has been queued to the video device, add to 'struct
rkisp1_params_buffer' a scratch buffer where to copy the parameters.
Allocate the scratch buffer in the vb2 buf_init() operation and copy the
buffer content in the buf_prepare() operation. Free the scratch
buffer in the newly introduced buf_cleanup() operation handler.
Modify the ISP configuration function to access the ISP configuration
from the cached copy of the parameters buffer instead of using the
userspace-mapped one.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../platform/rockchip/rkisp1/rkisp1-common.h | 8 ++
.../platform/rockchip/rkisp1/rkisp1-params.c | 83 ++++++++++++-------
2 files changed, 60 insertions(+), 31 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index a615bbb0255e..8d520c5c71c3 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -250,12 +250,20 @@ struct rkisp1_buffer {
*
* @vb: vb2 buffer
* @queue: entry of the buffer in the queue
+ * @cfg: scratch buffer used for caching the ISP configuration parameters
*/
struct rkisp1_params_buffer {
struct vb2_v4l2_buffer vb;
struct list_head queue;
+ struct rkisp1_params_cfg *cfg;
};
+static inline struct rkisp1_params_buffer *
+to_rkisp1_params_buffer(struct vb2_v4l2_buffer *vbuf)
+{
+ return container_of(vbuf, struct rkisp1_params_buffer, vb);
+}
+
/*
* struct rkisp1_dummy_buffer - A buffer to write the next frame to in case
* there are no vb2 buffers available.
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 2844e55bc4f2..e333cda21fdd 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -5,6 +5,8 @@
* Copyright (C) 2017 Rockchip Electronics Co., Ltd.
*/
+#include <linux/string.h>
+
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
@@ -1501,20 +1503,6 @@ static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params,
}
}
-static bool rkisp1_params_get_buffer(struct rkisp1_params *params,
- struct rkisp1_params_buffer **buf,
- struct rkisp1_params_cfg **cfg)
-{
- if (list_empty(¶ms->params))
- return false;
-
- *buf = list_first_entry(¶ms->params, struct rkisp1_params_buffer,
- queue);
- *cfg = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0);
-
- return true;
-}
-
static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
struct rkisp1_params_buffer *buf,
unsigned int frame_sequence)
@@ -1528,17 +1516,18 @@ static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
void rkisp1_params_isr(struct rkisp1_device *rkisp1)
{
struct rkisp1_params *params = &rkisp1->params;
- struct rkisp1_params_cfg *new_params;
struct rkisp1_params_buffer *cur_buf;
spin_lock(¶ms->config_lock);
- if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params))
+ cur_buf = list_first_entry_or_null(¶ms->params,
+ struct rkisp1_params_buffer, queue);
+ if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_other_config(params, new_params);
- rkisp1_isp_isr_lsc_config(params, new_params);
- rkisp1_isp_isr_meas_config(params, new_params);
+ rkisp1_isp_isr_other_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1604,7 +1593,6 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
enum v4l2_ycbcr_encoding ycbcr_encoding)
{
struct rkisp1_cif_isp_hst_config hst = rkisp1_hst_params_default_config;
- struct rkisp1_params_cfg *new_params;
struct rkisp1_params_buffer *cur_buf;
params->quantization = quantization;
@@ -1634,11 +1622,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
/* apply the first buffer if there is one already */
- if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params))
+ cur_buf = list_first_entry_or_null(¶ms->params,
+ struct rkisp1_params_buffer, queue);
+ if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_other_config(params, new_params);
- rkisp1_isp_isr_meas_config(params, new_params);
+ rkisp1_isp_isr_other_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1650,7 +1640,6 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
void rkisp1_params_post_configure(struct rkisp1_params *params)
{
- struct rkisp1_params_cfg *new_params;
struct rkisp1_params_buffer *cur_buf;
spin_lock_irq(¶ms->config_lock);
@@ -1663,11 +1652,12 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
* ordering doesn't affect other ISP versions negatively, do so
* unconditionally.
*/
-
- if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params))
+ cur_buf = list_first_entry_or_null(¶ms->params,
+ struct rkisp1_params_buffer, queue);
+ if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_lsc_config(params, new_params);
+ rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1819,11 +1809,31 @@ static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
return 0;
}
+static int rkisp1_params_vb2_buf_init(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
+
+ params_buf->cfg = kvmalloc(sizeof(*params_buf->cfg), GFP_KERNEL);
+ if (!params_buf->cfg)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void rkisp1_params_vb2_buf_cleanup(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
+
+ kvfree(params_buf->cfg);
+ params_buf->cfg = NULL;
+}
+
static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct rkisp1_params_buffer *params_buf =
- container_of(vbuf, struct rkisp1_params_buffer, vb);
+ struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_params *params = vq->drv_priv;
@@ -1834,10 +1844,19 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
{
- if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_params_cfg))
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
+ struct rkisp1_params_cfg *cfg =
+ vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
+
+ if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
return -EINVAL;
- vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_params_cfg));
+ /*
+ * Copy the parameters buffer to the internal scratch buffer to avoid
+ * userspace modifying the buffer content while the driver processes it.
+ */
+ memcpy(params_buf->cfg, cfg, sizeof(*cfg));
return 0;
}
@@ -1863,6 +1882,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
static const struct vb2_ops rkisp1_params_vb2_ops = {
.queue_setup = rkisp1_params_vb2_queue_setup,
+ .buf_init = rkisp1_params_vb2_buf_init,
+ .buf_cleanup = rkisp1_params_vb2_buf_cleanup,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
.buf_queue = rkisp1_params_vb2_buf_queue,
--
2.45.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v5 5/7] media: rkisp1: Cache the currently active format
2024-07-03 16:10 [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters Jacopo Mondi
` (3 preceding siblings ...)
2024-07-03 16:10 ` [PATCH v5 4/7] media: rkisp1: Copy the parameters buffer Jacopo Mondi
@ 2024-07-03 16:10 ` Jacopo Mondi
2024-07-05 10:56 ` Paul Elder
2024-07-03 16:10 ` [PATCH v5 6/7] media: rkisp1: Implement extensible params support Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 7/7] media: rkisp1: Implement s_fmt/try_fmt Jacopo Mondi
6 siblings, 1 reply; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-03 16:10 UTC (permalink / raw)
To: Linux Media Mailing List
Cc: Jacopo Mondi, Laurent Pinchart, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
The rkisp1-params driver assumes the data buffer format is the only
currently supported "fixed" one. The usage of the "fixed" format is
assumed when allocating memory for the scratch buffers and when
initializing the vb2 queue.
In order to prepare to support the "extensible" format beside the
existing "fixed" one, add support in the driver for both formats by
caching a pointer to the active one in the driver structure and use it
in the vb2 queue operations and subdev pad operations implementations.
Do not yet allow userspace to select between the two formats as the
support for the "extensible" format parsing will be introduced in a later
patch in the series.
While at it, document the un-documented ycbcr_encoding field of
struct rkisp1_params_ops.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../platform/rockchip/rkisp1/rkisp1-common.h | 8 +--
.../platform/rockchip/rkisp1/rkisp1-params.c | 52 ++++++++++++-------
2 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index 8d520c5c71c3..43cc727a628d 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -255,7 +255,7 @@ struct rkisp1_buffer {
struct rkisp1_params_buffer {
struct vb2_v4l2_buffer vb;
struct list_head queue;
- struct rkisp1_params_cfg *cfg;
+ void *cfg;
};
static inline struct rkisp1_params_buffer *
@@ -392,8 +392,9 @@ struct rkisp1_params_ops {
* @ops: pointer to the variant-specific operations
* @config_lock: locks the buffer list 'params'
* @params: queue of rkisp1_buffer
- * @vdev_fmt: v4l2_format of the metadata format
+ * @metafmt the currently enabled metadata format
* @quantization: the quantization configured on the isp's src pad
+ * @ycbcr_encoding the YCbCr encoding
* @raw_type: the bayer pattern on the isp video sink pad
*/
struct rkisp1_params {
@@ -403,7 +404,8 @@ struct rkisp1_params {
spinlock_t config_lock; /* locks the buffers list 'params' */
struct list_head params;
- struct v4l2_format vdev_fmt;
+
+ const struct v4l2_meta_format *metafmt;
enum v4l2_quantization quantization;
enum v4l2_ycbcr_encoding ycbcr_encoding;
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index e333cda21fdd..45c4b1bcee63 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -35,6 +35,22 @@
#define RKISP1_ISP_CC_COEFF(n) \
(RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
+enum rkisp1_params_formats {
+ RKISP1_PARAMS_FIXED,
+ RKISP1_PARAMS_EXTENSIBLE,
+};
+
+static const struct v4l2_meta_format rkisp1_params_formats[] = {
+ [RKISP1_PARAMS_FIXED] = {
+ .dataformat = V4L2_META_FMT_RK_ISP1_PARAMS,
+ .buffersize = sizeof(struct rkisp1_params_cfg),
+ },
+ [RKISP1_PARAMS_EXTENSIBLE] = {
+ .dataformat = V4L2_META_FMT_RK_ISP1_EXT_PARAMS,
+ .buffersize = sizeof(struct rkisp1_ext_params_cfg),
+ },
+};
+
static inline void
rkisp1_param_set_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask)
{
@@ -1738,7 +1754,7 @@ static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv,
if (f->index > 0 || f->type != video->queue->type)
return -EINVAL;
- f->pixelformat = params->vdev_fmt.fmt.meta.dataformat;
+ f->pixelformat = params->metafmt->dataformat;
return 0;
}
@@ -1754,8 +1770,8 @@ static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh,
return -EINVAL;
memset(meta, 0, sizeof(*meta));
- meta->dataformat = params->vdev_fmt.fmt.meta.dataformat;
- meta->buffersize = params->vdev_fmt.fmt.meta.buffersize;
+ meta->dataformat = params->metafmt->dataformat;
+ meta->buffersize = params->metafmt->buffersize;
return 0;
}
@@ -1798,13 +1814,15 @@ static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
unsigned int sizes[],
struct device *alloc_devs[])
{
+ struct rkisp1_params *params = vq->drv_priv;
+
*num_buffers = clamp_t(u32, *num_buffers,
RKISP1_ISP_PARAMS_REQ_BUFS_MIN,
RKISP1_ISP_PARAMS_REQ_BUFS_MAX);
*num_planes = 1;
- sizes[0] = sizeof(struct rkisp1_params_cfg);
+ sizes[0] = params->metafmt->buffersize;
return 0;
}
@@ -1813,8 +1831,10 @@ static int rkisp1_params_vb2_buf_init(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
+ struct rkisp1_params *params = vb->vb2_queue->drv_priv;
- params_buf->cfg = kvmalloc(sizeof(*params_buf->cfg), GFP_KERNEL);
+ params_buf->cfg = kvmalloc(params->metafmt->buffersize,
+ GFP_KERNEL);
if (!params_buf->cfg)
return -ENOMEM;
@@ -1919,19 +1939,6 @@ static int rkisp1_params_init_vb2_queue(struct vb2_queue *q,
return vb2_queue_init(q);
}
-static void rkisp1_init_params(struct rkisp1_params *params)
-{
- params->vdev_fmt.fmt.meta.dataformat =
- V4L2_META_FMT_RK_ISP1_PARAMS;
- params->vdev_fmt.fmt.meta.buffersize =
- sizeof(struct rkisp1_params_cfg);
-
- if (params->rkisp1->info->isp_ver == RKISP1_V12)
- params->ops = &rkisp1_v12_params_ops;
- else
- params->ops = &rkisp1_v10_params_ops;
-}
-
int rkisp1_params_register(struct rkisp1_device *rkisp1)
{
struct rkisp1_params *params = &rkisp1->params;
@@ -1960,7 +1967,14 @@ int rkisp1_params_register(struct rkisp1_device *rkisp1)
vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT;
vdev->vfl_dir = VFL_DIR_TX;
rkisp1_params_init_vb2_queue(vdev->queue, params);
- rkisp1_init_params(params);
+
+ params->metafmt = &rkisp1_params_formats[RKISP1_PARAMS_FIXED];
+
+ if (params->rkisp1->info->isp_ver == RKISP1_V12)
+ params->ops = &rkisp1_v12_params_ops;
+ else
+ params->ops = &rkisp1_v10_params_ops;
+
video_set_drvdata(vdev, params);
node->pad.flags = MEDIA_PAD_FL_SOURCE;
--
2.45.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v5 6/7] media: rkisp1: Implement extensible params support
2024-07-03 16:10 [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters Jacopo Mondi
` (4 preceding siblings ...)
2024-07-03 16:10 ` [PATCH v5 5/7] media: rkisp1: Cache the currently active format Jacopo Mondi
@ 2024-07-03 16:10 ` Jacopo Mondi
2024-07-03 20:56 ` Laurent Pinchart
` (3 more replies)
2024-07-03 16:10 ` [PATCH v5 7/7] media: rkisp1: Implement s_fmt/try_fmt Jacopo Mondi
6 siblings, 4 replies; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-03 16:10 UTC (permalink / raw)
To: Linux Media Mailing List
Cc: Jacopo Mondi, Laurent Pinchart, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
Implement support in rkisp1-params for the extensible configuration
parameters format.
Create a list of handlers for each ISP block that wraps the existing
configuration functions and handles the ISP block enablement.
Parse the configuration parameters buffer in rkisp1_ext_params_config
and filter the enable blocks by group, to allow setting the 'other'
groups separately from the 'lsc' group to support the pre/post-configure
operations.
Implement parameter buffer validation for the extensible format at
.buf_prepare() time.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
.../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
.../platform/rockchip/rkisp1/rkisp1-params.c | 602 +++++++++++++++++-
2 files changed, 591 insertions(+), 14 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index 43cc727a628d..2f4bf7e97927 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -396,6 +396,7 @@ struct rkisp1_params_ops {
* @quantization: the quantization configured on the isp's src pad
* @ycbcr_encoding the YCbCr encoding
* @raw_type: the bayer pattern on the isp video sink pad
+ * @enabled_blocks: bitmask of enabled ISP blocks
*/
struct rkisp1_params {
struct rkisp1_vdev_node vnode;
@@ -410,6 +411,8 @@ struct rkisp1_params {
enum v4l2_quantization quantization;
enum v4l2_ycbcr_encoding ycbcr_encoding;
enum rkisp1_fmt_raw_pat_type raw_type;
+
+ u32 enabled_blocks;
};
/*
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 45c4b1bcee63..3ef410337aa2 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -35,6 +35,30 @@
#define RKISP1_ISP_CC_COEFF(n) \
(RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
+#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;
+};
+
enum rkisp1_params_formats {
RKISP1_PARAMS_FIXED,
RKISP1_PARAMS_EXTENSIBLE,
@@ -1519,6 +1543,451 @@ 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)
+{
+ const struct rkisp1_ext_params_bls_config *bls = &block->bls;
+
+ if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
+ RKISP1_CIF_ISP_BLS_ENA);
+ return;
+ }
+
+ rkisp1_bls_config(params, &bls->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
+ RKISP1_CIF_ISP_BLS_ENA);
+}
+
+static void
+rkisp1_ext_params_dpcc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
+
+ if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
+ RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
+ return;
+ }
+
+ rkisp1_dpcc_config(params, &dpcc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
+ RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
+}
+
+static void
+rkisp1_ext_params_sdg(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
+ return;
+ }
+
+ rkisp1_sdg_config(params, &sdg->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ 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)
+{
+ const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
+ RKISP1_CIF_ISP_LSC_CTRL_ENA);
+ return;
+ }
+
+ rkisp1_lsc_config(params, &lsc->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
+ RKISP1_CIF_ISP_LSC_CTRL_ENA);
+}
+
+static void
+rkisp1_ext_params_awbg(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
+ return;
+ }
+
+ params->ops->awb_gain_config(params, &awbg->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
+}
+
+static void
+rkisp1_ext_params_flt(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_flt_config *flt = &block->flt;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
+ RKISP1_CIF_ISP_FLT_ENA);
+ return;
+ }
+
+ rkisp1_flt_config(params, &flt->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
+ RKISP1_CIF_ISP_FLT_ENA);
+}
+
+static void
+rkisp1_ext_params_bdm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
+ RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
+ return;
+ }
+
+ rkisp1_bdm_config(params, &bdm->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
+ RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
+}
+
+static void
+rkisp1_ext_params_ctk(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_ctk_enable(params, false);
+ return;
+ }
+
+ rkisp1_ctk_config(params, &ctk->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
+ rkisp1_ctk_enable(params, true);
+}
+
+static void
+rkisp1_ext_params_goc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_goc_config *goc = &block->goc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
+ return;
+ }
+
+ params->ops->goc_config(params, &goc->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ 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)
+{
+ const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
+ RKISP1_CIF_ISP_DPF_MODE_EN);
+ return;
+ }
+
+ rkisp1_dpf_config(params, &dpf->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
+ RKISP1_CIF_ISP_DPF_MODE_EN);
+}
+
+static void
+rkisp1_ext_params_dpfs(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
+
+ rkisp1_dpf_strength_config(params, &dpfs->config);
+}
+
+static void
+rkisp1_ext_params_cproc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
+ RKISP1_CIF_C_PROC_CTR_ENABLE);
+ return;
+ }
+
+ rkisp1_cproc_config(params, &cproc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
+ RKISP1_CIF_C_PROC_CTR_ENABLE);
+}
+
+static void
+rkisp1_ext_params_ie(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_ie_config *ie = &block->ie;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_ie_enable(params, false);
+ return;
+ }
+
+ rkisp1_ie_config(params, &ie->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
+ rkisp1_ie_enable(params, true);
+}
+
+static void
+rkisp1_ext_params_awbm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ params->ops->awb_meas_enable(params, &awbm->config,
+ false);
+ return;
+ }
+
+ params->ops->awb_meas_config(params, &awbm->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
+ params->ops->awb_meas_enable(params, &awbm->config,
+ true);
+}
+
+static void
+rkisp1_ext_params_hstm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_hst_config *hst = &block->hst;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ params->ops->hst_enable(params, &hst->config, false);
+ return;
+ }
+
+ params->ops->hst_config(params, &hst->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
+ 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)
+{
+ const struct rkisp1_ext_params_aec_config *aec = &block->aec;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
+ RKISP1_CIF_ISP_EXP_ENA);
+ return;
+ }
+
+ params->ops->aec_config(params, &aec->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
+ RKISP1_CIF_ISP_EXP_ENA);
+}
+
+static void
+rkisp1_ext_params_afcm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_afc_config *afc = &block->afc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
+ RKISP1_CIF_ISP_AFM_ENA);
+ return;
+ }
+
+ params->ops->afm_config(params, &afc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
+ RKISP1_CIF_ISP_AFM_ENA);
+}
+
+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;
+ unsigned int group;
+} rkisp1_ext_params_handlers[] = {
+ [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,
+ },
+ [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,
+ },
+};
+
+static void rkisp1_ext_params_config(struct rkisp1_params *params,
+ struct rkisp1_ext_params_cfg *cfg,
+ u32 block_group_mask)
+{
+ size_t block_offset = 0;
+
+ if (WARN_ON(!cfg))
+ return;
+
+ /* 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;
+
+ block = (const union rkisp1_ext_params_config *)
+ &cfg->data[block_offset];
+ block_offset += block->header.size;
+
+ /* Make sure the block is in the list of groups to configure. */
+ block_handler = &rkisp1_ext_params_handlers[block->header.type];
+ if (!(block_handler->group & block_group_mask))
+ continue;
+
+ block_handler->handler(params, block);
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
+ params->enabled_blocks &= ~BIT(block->header.type);
+ else
+ params->enabled_blocks |= BIT(block->header.type);
+ }
+}
+
static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
struct rkisp1_params_buffer *buf,
unsigned int frame_sequence)
@@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_other_config(params, cur_buf->cfg);
- rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
- rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
+ rkisp1_isp_isr_other_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ } else {
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
+ }
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_other_config(params, cur_buf->cfg);
- rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
+ rkisp1_isp_isr_other_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ } else {
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
+ }
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
+ rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ else
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1862,25 +2346,114 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
spin_unlock_irq(¶ms->config_lock);
}
-static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
+static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
+ struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
- struct rkisp1_params_cfg *cfg =
- vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
+ 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;
- if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
+ /*
+ * 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) {
+ dev_dbg(params->rkisp1->dev,
+ "Too large buffer payload size %lu\n", payload_size);
return -EINVAL;
+ }
+
+ if (payload_size < header_size) {
+ dev_dbg(params->rkisp1->dev,
+ "Buffer payload %lu smaller than header size %lu\n",
+ payload_size, header_size);
+ return -EINVAL;
+ }
/*
- * Copy the parameters buffer to the internal scratch buffer to avoid
- * userspace modifying the buffer content while the driver processes it.
+ * Copy the parameters buffer to the internal scratch buffer to
+ * avoid userspace modifying the buffer content while the driver
+ * processes it.
*/
- memcpy(params_buf->cfg, cfg, sizeof(*cfg));
+ memcpy(cfg, usr_cfg, payload_size);
+
+ /* 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 %lu larger than buffer payload size %lu\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;
+ }
+
+ 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;
+ }
return 0;
}
+static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
+ struct rkisp1_ext_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
+ struct rkisp1_params *params = vb->vb2_queue->drv_priv;
+ size_t payload = vb2_get_plane_payload(vb, 0);
+
+ /* Only validate the plane payload size for fixed parameters format. */
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
+ if (payload != sizeof(struct rkisp1_params_cfg))
+ return -EINVAL;
+
+ /*
+ * Copy the parameters buffer to the internal scratch buffer to
+ * avoid userspace modifying the buffer content while the driver
+ * processes it.
+ */
+ memcpy(params_buf->cfg, cfg, payload);
+
+ return 0;
+ }
+
+ return rkisp1_params_prepare_ext_params(params, vb);
+}
+
static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
{
struct rkisp1_params *params = vq->drv_priv;
@@ -1898,6 +2471,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
list_for_each_entry(buf, &tmp_list, queue)
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+
+ params->enabled_blocks = 0;
}
static const struct vb2_ops rkisp1_params_vb2_ops = {
@@ -1909,7 +2484,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
.buf_queue = rkisp1_params_vb2_buf_queue,
.buf_prepare = rkisp1_params_vb2_buf_prepare,
.stop_streaming = rkisp1_params_vb2_stop_streaming,
-
};
static const struct v4l2_file_operations rkisp1_params_fops = {
--
2.45.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v5 7/7] media: rkisp1: Implement s_fmt/try_fmt
2024-07-03 16:10 [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters Jacopo Mondi
` (5 preceding siblings ...)
2024-07-03 16:10 ` [PATCH v5 6/7] media: rkisp1: Implement extensible params support Jacopo Mondi
@ 2024-07-03 16:10 ` Jacopo Mondi
2024-07-05 11:23 ` Paul Elder
6 siblings, 1 reply; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-03 16:10 UTC (permalink / raw)
To: Linux Media Mailing List
Cc: Jacopo Mondi, Laurent Pinchart, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
Implement in the rkisp1 driver support for the s_fmt and try_fmt
operation to allow userspace to select between the extensible
and the fixed parameters formats.
Implement enum_mbus_code to enumerate the fixed and the extensible
formats and disallow changing the data format while the queue is busy.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../platform/rockchip/rkisp1/rkisp1-params.c | 58 ++++++++++++++++---
1 file changed, 50 insertions(+), 8 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 3ef410337aa2..ea1ad92d2b21 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -75,6 +75,17 @@ static const struct v4l2_meta_format rkisp1_params_formats[] = {
},
};
+static const struct v4l2_meta_format *
+rkisp1_params_get_format_info(u32 dataformat)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(rkisp1_params_formats); i++) {
+ if (rkisp1_params_formats[i].dataformat == dataformat)
+ return &rkisp1_params_formats[i];
+ }
+
+ return &rkisp1_params_formats[RKISP1_PARAMS_FIXED];
+}
+
static inline void
rkisp1_param_set_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask)
{
@@ -2233,12 +2244,12 @@ static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
struct video_device *video = video_devdata(file);
- struct rkisp1_params *params = video_get_drvdata(video);
- if (f->index > 0 || f->type != video->queue->type)
+ if (f->index >= ARRAY_SIZE(rkisp1_params_formats) ||
+ f->type != video->queue->type)
return -EINVAL;
- f->pixelformat = params->metafmt->dataformat;
+ f->pixelformat = rkisp1_params_formats[f->index].dataformat;
return 0;
}
@@ -2253,9 +2264,40 @@ static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh,
if (f->type != video->queue->type)
return -EINVAL;
- memset(meta, 0, sizeof(*meta));
- meta->dataformat = params->metafmt->dataformat;
- meta->buffersize = params->metafmt->buffersize;
+ *meta = *params->metafmt;
+
+ return 0;
+}
+
+static int rkisp1_params_try_fmt_meta_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct video_device *video = video_devdata(file);
+ struct v4l2_meta_format *meta = &f->fmt.meta;
+
+ if (f->type != video->queue->type)
+ return -EINVAL;
+
+ *meta = *rkisp1_params_get_format_info(meta->dataformat);
+
+ return 0;
+}
+
+static int rkisp1_params_s_fmt_meta_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct video_device *video = video_devdata(file);
+ struct rkisp1_params *params = video_get_drvdata(video);
+ struct v4l2_meta_format *meta = &f->fmt.meta;
+
+ if (f->type != video->queue->type)
+ return -EINVAL;
+
+ if (vb2_is_busy(video->queue))
+ return -EBUSY;
+
+ params->metafmt = rkisp1_params_get_format_info(meta->dataformat);
+ *meta = *params->metafmt;
return 0;
}
@@ -2285,8 +2327,8 @@ static const struct v4l2_ioctl_ops rkisp1_params_ioctl = {
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out,
.vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
- .vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
- .vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
+ .vidioc_s_fmt_meta_out = rkisp1_params_s_fmt_meta_out,
+ .vidioc_try_fmt_meta_out = rkisp1_params_try_fmt_meta_out,
.vidioc_querycap = rkisp1_params_querycap,
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
--
2.45.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v5 6/7] media: rkisp1: Implement extensible params support
2024-07-03 16:10 ` [PATCH v5 6/7] media: rkisp1: Implement extensible params support Jacopo Mondi
@ 2024-07-03 20:56 ` Laurent Pinchart
2024-07-03 21:17 ` [PATCH v5.1 " Laurent Pinchart
` (2 subsequent siblings)
3 siblings, 0 replies; 21+ messages in thread
From: Laurent Pinchart @ 2024-07-03 20:56 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Linux Media Mailing List, Sakari Ailus, Hans Verkuil, Stefan Klug,
Paul Elder, Daniel Scally, Kieran Bingham, Umang Jain,
Dafna Hirschfeld, Mauro Carvalho Chehab, Heiko Stuebner
On Wed, Jul 03, 2024 at 06:10:45PM +0200, Jacopo Mondi wrote:
> Implement support in rkisp1-params for the extensible configuration
> parameters format.
>
> Create a list of handlers for each ISP block that wraps the existing
> configuration functions and handles the ISP block enablement.
>
> Parse the configuration parameters buffer in rkisp1_ext_params_config
> and filter the enable blocks by group, to allow setting the 'other'
> groups separately from the 'lsc' group to support the pre/post-configure
> operations.
>
> Implement parameter buffer validation for the extensible format at
> .buf_prepare() time.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> .../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
> .../platform/rockchip/rkisp1/rkisp1-params.c | 602 +++++++++++++++++-
> 2 files changed, 591 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> index 43cc727a628d..2f4bf7e97927 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> @@ -396,6 +396,7 @@ struct rkisp1_params_ops {
> * @quantization: the quantization configured on the isp's src pad
> * @ycbcr_encoding the YCbCr encoding
> * @raw_type: the bayer pattern on the isp video sink pad
> + * @enabled_blocks: bitmask of enabled ISP blocks
> */
> struct rkisp1_params {
> struct rkisp1_vdev_node vnode;
> @@ -410,6 +411,8 @@ struct rkisp1_params {
> enum v4l2_quantization quantization;
> enum v4l2_ycbcr_encoding ycbcr_encoding;
> enum rkisp1_fmt_raw_pat_type raw_type;
> +
> + u32 enabled_blocks;
> };
>
> /*
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 45c4b1bcee63..3ef410337aa2 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -35,6 +35,30 @@
> #define RKISP1_ISP_CC_COEFF(n) \
> (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
>
> +#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;
> +};
> +
> enum rkisp1_params_formats {
> RKISP1_PARAMS_FIXED,
> RKISP1_PARAMS_EXTENSIBLE,
> @@ -1519,6 +1543,451 @@ 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)
> +{
> + const struct rkisp1_ext_params_bls_config *bls = &block->bls;
> +
> + if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> + RKISP1_CIF_ISP_BLS_ENA);
> + return;
> + }
> +
> + rkisp1_bls_config(params, &bls->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> + RKISP1_CIF_ISP_BLS_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
> +
> + if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> + return;
> + }
> +
> + rkisp1_dpcc_config(params, &dpcc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> +}
> +
> +static void
> +rkisp1_ext_params_sdg(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> + return;
> + }
> +
> + rkisp1_sdg_config(params, &sdg->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + 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)
> +{
> + const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> + return;
> + }
> +
> + rkisp1_lsc_config(params, &lsc->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_awbg(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> + return;
> + }
> +
> + params->ops->awb_gain_config(params, &awbg->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_flt(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_flt_config *flt = &block->flt;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> + RKISP1_CIF_ISP_FLT_ENA);
> + return;
> + }
> +
> + rkisp1_flt_config(params, &flt->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> + RKISP1_CIF_ISP_FLT_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_bdm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> + return;
> + }
> +
> + rkisp1_bdm_config(params, &bdm->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> +}
> +
> +static void
> +rkisp1_ext_params_ctk(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_ctk_enable(params, false);
> + return;
> + }
> +
> + rkisp1_ctk_config(params, &ctk->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
> + rkisp1_ctk_enable(params, true);
> +}
> +
> +static void
> +rkisp1_ext_params_goc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_goc_config *goc = &block->goc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> + return;
> + }
> +
> + params->ops->goc_config(params, &goc->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + 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)
> +{
> + const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> + RKISP1_CIF_ISP_DPF_MODE_EN);
> + return;
> + }
> +
> + rkisp1_dpf_config(params, &dpf->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> + RKISP1_CIF_ISP_DPF_MODE_EN);
> +}
> +
> +static void
> +rkisp1_ext_params_dpfs(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
> +
> + rkisp1_dpf_strength_config(params, &dpfs->config);
> +}
> +
> +static void
> +rkisp1_ext_params_cproc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
> + RKISP1_CIF_C_PROC_CTR_ENABLE);
> + return;
> + }
> +
> + rkisp1_cproc_config(params, &cproc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
> + RKISP1_CIF_C_PROC_CTR_ENABLE);
> +}
> +
> +static void
> +rkisp1_ext_params_ie(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_ie_config *ie = &block->ie;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_ie_enable(params, false);
> + return;
> + }
> +
> + rkisp1_ie_config(params, &ie->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
> + rkisp1_ie_enable(params, true);
> +}
> +
> +static void
> +rkisp1_ext_params_awbm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + params->ops->awb_meas_enable(params, &awbm->config,
> + false);
> + return;
> + }
> +
> + params->ops->awb_meas_config(params, &awbm->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
> + params->ops->awb_meas_enable(params, &awbm->config,
> + true);
> +}
> +
> +static void
> +rkisp1_ext_params_hstm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_hst_config *hst = &block->hst;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + params->ops->hst_enable(params, &hst->config, false);
> + return;
> + }
> +
> + params->ops->hst_config(params, &hst->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
> + 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)
> +{
> + const struct rkisp1_ext_params_aec_config *aec = &block->aec;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> + RKISP1_CIF_ISP_EXP_ENA);
> + return;
> + }
> +
> + params->ops->aec_config(params, &aec->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> + RKISP1_CIF_ISP_EXP_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_afcm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_afc_config *afc = &block->afc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> + RKISP1_CIF_ISP_AFM_ENA);
> + return;
> + }
> +
> + params->ops->afm_config(params, &afc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> + RKISP1_CIF_ISP_AFM_ENA);
> +}
> +
> +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;
> + unsigned int group;
> +} rkisp1_ext_params_handlers[] = {
> + [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,
> + },
> + [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,
> + },
> +};
> +
> +static void rkisp1_ext_params_config(struct rkisp1_params *params,
> + struct rkisp1_ext_params_cfg *cfg,
> + u32 block_group_mask)
> +{
> + size_t block_offset = 0;
> +
> + if (WARN_ON(!cfg))
> + return;
> +
> + /* 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;
> +
> + block = (const union rkisp1_ext_params_config *)
> + &cfg->data[block_offset];
> + block_offset += block->header.size;
> +
> + /* Make sure the block is in the list of groups to configure. */
> + block_handler = &rkisp1_ext_params_handlers[block->header.type];
> + if (!(block_handler->group & block_group_mask))
> + continue;
> +
> + block_handler->handler(params, block);
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
> + params->enabled_blocks &= ~BIT(block->header.type);
> + else
> + params->enabled_blocks |= BIT(block->header.type);
> + }
> +}
> +
> static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> struct rkisp1_params_buffer *buf,
> unsigned int frame_sequence)
> @@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + } else {
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> + }
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + } else {
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
> + }
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + else
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1862,25 +2346,114 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> spin_unlock_irq(¶ms->config_lock);
> }
>
> -static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> + struct vb2_buffer *vb)
> {
> struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> - struct rkisp1_params_cfg *cfg =
> - vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
> + 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;
>
> - if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
> + /*
> + * 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) {
> + dev_dbg(params->rkisp1->dev,
> + "Too large buffer payload size %lu\n", payload_size);
> return -EINVAL;
> + }
> +
> + if (payload_size < header_size) {
> + dev_dbg(params->rkisp1->dev,
> + "Buffer payload %lu smaller than header size %lu\n",
> + payload_size, header_size);
> + return -EINVAL;
> + }
>
> /*
> - * Copy the parameters buffer to the internal scratch buffer to avoid
> - * userspace modifying the buffer content while the driver processes it.
> + * Copy the parameters buffer to the internal scratch buffer to
> + * avoid userspace modifying the buffer content while the driver
> + * processes it.
> */
> - memcpy(params_buf->cfg, cfg, sizeof(*cfg));
> + memcpy(cfg, usr_cfg, payload_size);
> +
> + /* 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 %lu larger than buffer payload size %lu\n",
s/larger/different/
> + 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;
> + }
> +
> + 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;
> + }
>
> return 0;
> }
>
> +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +{
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> + struct rkisp1_ext_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
> + struct rkisp1_params *params = vb->vb2_queue->drv_priv;
> + size_t payload = vb2_get_plane_payload(vb, 0);
> +
> + /* Only validate the plane payload size for fixed parameters format. */
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + if (payload != sizeof(struct rkisp1_params_cfg))
sizeof(*cfg)
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
I can fix those when applying, no need for a v6.
> + return -EINVAL;
> +
> + /*
> + * Copy the parameters buffer to the internal scratch buffer to
> + * avoid userspace modifying the buffer content while the driver
> + * processes it.
> + */
> + memcpy(params_buf->cfg, cfg, payload);
> +
> + return 0;
> + }
> +
> + return rkisp1_params_prepare_ext_params(params, vb);
> +}
> +
> static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
> {
> struct rkisp1_params *params = vq->drv_priv;
> @@ -1898,6 +2471,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
>
> list_for_each_entry(buf, &tmp_list, queue)
> vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> +
> + params->enabled_blocks = 0;
> }
>
> static const struct vb2_ops rkisp1_params_vb2_ops = {
> @@ -1909,7 +2484,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
> .buf_queue = rkisp1_params_vb2_buf_queue,
> .buf_prepare = rkisp1_params_vb2_buf_prepare,
> .stop_streaming = rkisp1_params_vb2_stop_streaming,
> -
> };
>
> static const struct v4l2_file_operations rkisp1_params_fops = {
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v5.1 6/7] media: rkisp1: Implement extensible params support
2024-07-03 16:10 ` [PATCH v5 6/7] media: rkisp1: Implement extensible params support Jacopo Mondi
2024-07-03 20:56 ` Laurent Pinchart
@ 2024-07-03 21:17 ` Laurent Pinchart
2024-07-04 7:36 ` Jacopo Mondi
2024-07-04 9:56 ` [PATCH v5.2 " Laurent Pinchart
2024-07-06 12:18 ` [PATCH v5 " Sakari Ailus
3 siblings, 1 reply; 21+ messages in thread
From: Laurent Pinchart @ 2024-07-03 21:17 UTC (permalink / raw)
To: linux-media
Cc: Jacopo Mondi, Sakari Ailus, Hans Verkuil, Stefan Klug, Paul Elder,
Daniel Scally, Kieran Bingham, Umang Jain, Dafna Hirschfeld,
Mauro Carvalho Chehab, Heiko Stuebner
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Implement support in rkisp1-params for the extensible configuration
parameters format.
Create a list of handlers for each ISP block that wraps the existing
configuration functions and handles the ISP block enablement.
Parse the configuration parameters buffer in rkisp1_ext_params_config
and filter the enable blocks by group, to allow setting the 'other'
groups separately from the 'lsc' group to support the pre/post-configure
operations.
Implement parameter buffer validation for the extensible format at
.buf_prepare() time.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v5:
- Use correct struct type for cfg in rkisp1_params_vb2_buf_prepare()
- Replace sizeof(type) with sizeof(var)
- Refactor rkisp1_params_vb2_buf_prepare() to reduce indentation
---
.../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
.../platform/rockchip/rkisp1/rkisp1-params.c | 604 +++++++++++++++++-
2 files changed, 593 insertions(+), 14 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index b4369bbccea3..c1689c0fa05a 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -401,6 +401,7 @@ struct rkisp1_params_ops {
* @quantization: the quantization configured on the isp's src pad
* @ycbcr_encoding the YCbCr encoding
* @raw_type: the bayer pattern on the isp video sink pad
+ * @enabled_blocks: bitmask of enabled ISP blocks
*/
struct rkisp1_params {
struct rkisp1_vdev_node vnode;
@@ -415,6 +416,8 @@ struct rkisp1_params {
enum v4l2_quantization quantization;
enum v4l2_ycbcr_encoding ycbcr_encoding;
enum rkisp1_fmt_raw_pat_type raw_type;
+
+ u32 enabled_blocks;
};
/*
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 45c4b1bcee63..5e83a2e9d818 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -35,6 +35,30 @@
#define RKISP1_ISP_CC_COEFF(n) \
(RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
+#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;
+};
+
enum rkisp1_params_formats {
RKISP1_PARAMS_FIXED,
RKISP1_PARAMS_EXTENSIBLE,
@@ -1519,6 +1543,451 @@ 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)
+{
+ const struct rkisp1_ext_params_bls_config *bls = &block->bls;
+
+ if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
+ RKISP1_CIF_ISP_BLS_ENA);
+ return;
+ }
+
+ rkisp1_bls_config(params, &bls->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
+ RKISP1_CIF_ISP_BLS_ENA);
+}
+
+static void
+rkisp1_ext_params_dpcc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
+
+ if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
+ RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
+ return;
+ }
+
+ rkisp1_dpcc_config(params, &dpcc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
+ RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
+}
+
+static void
+rkisp1_ext_params_sdg(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
+ return;
+ }
+
+ rkisp1_sdg_config(params, &sdg->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ 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)
+{
+ const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
+ RKISP1_CIF_ISP_LSC_CTRL_ENA);
+ return;
+ }
+
+ rkisp1_lsc_config(params, &lsc->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
+ RKISP1_CIF_ISP_LSC_CTRL_ENA);
+}
+
+static void
+rkisp1_ext_params_awbg(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
+ return;
+ }
+
+ params->ops->awb_gain_config(params, &awbg->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
+}
+
+static void
+rkisp1_ext_params_flt(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_flt_config *flt = &block->flt;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
+ RKISP1_CIF_ISP_FLT_ENA);
+ return;
+ }
+
+ rkisp1_flt_config(params, &flt->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
+ RKISP1_CIF_ISP_FLT_ENA);
+}
+
+static void
+rkisp1_ext_params_bdm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
+ RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
+ return;
+ }
+
+ rkisp1_bdm_config(params, &bdm->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
+ RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
+}
+
+static void
+rkisp1_ext_params_ctk(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_ctk_enable(params, false);
+ return;
+ }
+
+ rkisp1_ctk_config(params, &ctk->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
+ rkisp1_ctk_enable(params, true);
+}
+
+static void
+rkisp1_ext_params_goc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_goc_config *goc = &block->goc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
+ return;
+ }
+
+ params->ops->goc_config(params, &goc->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ 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)
+{
+ const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
+ RKISP1_CIF_ISP_DPF_MODE_EN);
+ return;
+ }
+
+ rkisp1_dpf_config(params, &dpf->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
+ RKISP1_CIF_ISP_DPF_MODE_EN);
+}
+
+static void
+rkisp1_ext_params_dpfs(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
+
+ rkisp1_dpf_strength_config(params, &dpfs->config);
+}
+
+static void
+rkisp1_ext_params_cproc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
+ RKISP1_CIF_C_PROC_CTR_ENABLE);
+ return;
+ }
+
+ rkisp1_cproc_config(params, &cproc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
+ RKISP1_CIF_C_PROC_CTR_ENABLE);
+}
+
+static void
+rkisp1_ext_params_ie(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_ie_config *ie = &block->ie;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_ie_enable(params, false);
+ return;
+ }
+
+ rkisp1_ie_config(params, &ie->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
+ rkisp1_ie_enable(params, true);
+}
+
+static void
+rkisp1_ext_params_awbm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ params->ops->awb_meas_enable(params, &awbm->config,
+ false);
+ return;
+ }
+
+ params->ops->awb_meas_config(params, &awbm->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
+ params->ops->awb_meas_enable(params, &awbm->config,
+ true);
+}
+
+static void
+rkisp1_ext_params_hstm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_hst_config *hst = &block->hst;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ params->ops->hst_enable(params, &hst->config, false);
+ return;
+ }
+
+ params->ops->hst_config(params, &hst->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
+ 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)
+{
+ const struct rkisp1_ext_params_aec_config *aec = &block->aec;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
+ RKISP1_CIF_ISP_EXP_ENA);
+ return;
+ }
+
+ params->ops->aec_config(params, &aec->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
+ RKISP1_CIF_ISP_EXP_ENA);
+}
+
+static void
+rkisp1_ext_params_afcm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_afc_config *afc = &block->afc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
+ RKISP1_CIF_ISP_AFM_ENA);
+ return;
+ }
+
+ params->ops->afm_config(params, &afc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
+ RKISP1_CIF_ISP_AFM_ENA);
+}
+
+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;
+ unsigned int group;
+} rkisp1_ext_params_handlers[] = {
+ [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,
+ },
+ [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,
+ },
+};
+
+static void rkisp1_ext_params_config(struct rkisp1_params *params,
+ struct rkisp1_ext_params_cfg *cfg,
+ u32 block_group_mask)
+{
+ size_t block_offset = 0;
+
+ if (WARN_ON(!cfg))
+ return;
+
+ /* 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;
+
+ block = (const union rkisp1_ext_params_config *)
+ &cfg->data[block_offset];
+ block_offset += block->header.size;
+
+ /* Make sure the block is in the list of groups to configure. */
+ block_handler = &rkisp1_ext_params_handlers[block->header.type];
+ if (!(block_handler->group & block_group_mask))
+ continue;
+
+ block_handler->handler(params, block);
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
+ params->enabled_blocks &= ~BIT(block->header.type);
+ else
+ params->enabled_blocks |= BIT(block->header.type);
+ }
+}
+
static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
struct rkisp1_params_buffer *buf,
unsigned int frame_sequence)
@@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_other_config(params, cur_buf->cfg);
- rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
- rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
+ rkisp1_isp_isr_other_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ } else {
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
+ }
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_other_config(params, cur_buf->cfg);
- rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
+ rkisp1_isp_isr_other_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ } else {
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
+ }
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
+ rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ else
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1862,21 +2346,112 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
spin_unlock_irq(¶ms->config_lock);
}
-static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
+static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
+ struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
- struct rkisp1_params_cfg *cfg =
- vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
+ 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;
- if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
+ /*
+ * 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) {
+ dev_dbg(params->rkisp1->dev,
+ "Too large buffer payload size %lu\n", payload_size);
+ return -EINVAL;
+ }
+
+ if (payload_size < header_size) {
+ dev_dbg(params->rkisp1->dev,
+ "Buffer payload %lu smaller than header size %lu\n",
+ payload_size, header_size);
+ return -EINVAL;
+ }
+
+ /*
+ * Copy the parameters buffer to the internal scratch buffer to
+ * avoid userspace modifying the buffer content while the driver
+ * processes it.
+ */
+ memcpy(cfg, usr_cfg, payload_size);
+
+ /* 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 %lu larger than buffer payload size %lu\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;
+ }
+
+ 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;
+ }
+
+ return 0;
+}
+
+static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
+{
+ struct rkisp1_params *params = vb->vb2_queue->drv_priv;
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
+ struct rkisp1_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
+ size_t payload = vb2_get_plane_payload(vb, 0);
+
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS)
+ return rkisp1_params_prepare_ext_params(params, vb);
+
+ /*
+ * For the fixed parameters format the payload size must be exactly the
+ * size of the parameters structure.
+ */
+ if (payload != sizeof(*cfg))
return -EINVAL;
/*
- * Copy the parameters buffer to the internal scratch buffer to avoid
- * userspace modifying the buffer content while the driver processes it.
+ * Copy the parameters buffer to the internal scratch buffer to
+ * avoid userspace modifying the buffer content while the driver
+ * processes it.
*/
- memcpy(params_buf->cfg, cfg, sizeof(*cfg));
+ memcpy(params_buf->cfg, cfg, payload);
return 0;
}
@@ -1898,6 +2473,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
list_for_each_entry(buf, &tmp_list, queue)
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+
+ params->enabled_blocks = 0;
}
static const struct vb2_ops rkisp1_params_vb2_ops = {
@@ -1909,7 +2486,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
.buf_queue = rkisp1_params_vb2_buf_queue,
.buf_prepare = rkisp1_params_vb2_buf_prepare,
.stop_streaming = rkisp1_params_vb2_stop_streaming,
-
};
static const struct v4l2_file_operations rkisp1_params_fops = {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v5.1 6/7] media: rkisp1: Implement extensible params support
2024-07-03 21:17 ` [PATCH v5.1 " Laurent Pinchart
@ 2024-07-04 7:36 ` Jacopo Mondi
2024-07-04 9:40 ` Laurent Pinchart
0 siblings, 1 reply; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-04 7:36 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Jacopo Mondi, Sakari Ailus, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
Hi Laurent,
thanks for handling v5.1
On Thu, Jul 04, 2024 at 12:17:27AM GMT, Laurent Pinchart wrote:
> From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>
> Implement support in rkisp1-params for the extensible configuration
> parameters format.
>
> Create a list of handlers for each ISP block that wraps the existing
> configuration functions and handles the ISP block enablement.
>
> Parse the configuration parameters buffer in rkisp1_ext_params_config
> and filter the enable blocks by group, to allow setting the 'other'
> groups separately from the 'lsc' group to support the pre/post-configure
> operations.
>
> Implement parameter buffer validation for the extensible format at
> .buf_prepare() time.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v5:
>
> - Use correct struct type for cfg in rkisp1_params_vb2_buf_prepare()
> - Replace sizeof(type) with sizeof(var)
> - Refactor rkisp1_params_vb2_buf_prepare() to reduce indentation
> ---
> .../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
> .../platform/rockchip/rkisp1/rkisp1-params.c | 604 +++++++++++++++++-
> 2 files changed, 593 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> index b4369bbccea3..c1689c0fa05a 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> @@ -401,6 +401,7 @@ struct rkisp1_params_ops {
> * @quantization: the quantization configured on the isp's src pad
> * @ycbcr_encoding the YCbCr encoding
> * @raw_type: the bayer pattern on the isp video sink pad
> + * @enabled_blocks: bitmask of enabled ISP blocks
> */
> struct rkisp1_params {
> struct rkisp1_vdev_node vnode;
> @@ -415,6 +416,8 @@ struct rkisp1_params {
> enum v4l2_quantization quantization;
> enum v4l2_ycbcr_encoding ycbcr_encoding;
> enum rkisp1_fmt_raw_pat_type raw_type;
> +
> + u32 enabled_blocks;
> };
>
> /*
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 45c4b1bcee63..5e83a2e9d818 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -35,6 +35,30 @@
> #define RKISP1_ISP_CC_COEFF(n) \
> (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
>
> +#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;
> +};
> +
> enum rkisp1_params_formats {
> RKISP1_PARAMS_FIXED,
> RKISP1_PARAMS_EXTENSIBLE,
> @@ -1519,6 +1543,451 @@ 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)
> +{
> + const struct rkisp1_ext_params_bls_config *bls = &block->bls;
> +
> + if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> + RKISP1_CIF_ISP_BLS_ENA);
> + return;
> + }
> +
> + rkisp1_bls_config(params, &bls->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> + RKISP1_CIF_ISP_BLS_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
> +
> + if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> + return;
> + }
> +
> + rkisp1_dpcc_config(params, &dpcc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> +}
> +
> +static void
> +rkisp1_ext_params_sdg(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> + return;
> + }
> +
> + rkisp1_sdg_config(params, &sdg->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + 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)
> +{
> + const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> + return;
> + }
> +
> + rkisp1_lsc_config(params, &lsc->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_awbg(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> + return;
> + }
> +
> + params->ops->awb_gain_config(params, &awbg->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_flt(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_flt_config *flt = &block->flt;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> + RKISP1_CIF_ISP_FLT_ENA);
> + return;
> + }
> +
> + rkisp1_flt_config(params, &flt->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> + RKISP1_CIF_ISP_FLT_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_bdm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> + return;
> + }
> +
> + rkisp1_bdm_config(params, &bdm->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> +}
> +
> +static void
> +rkisp1_ext_params_ctk(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_ctk_enable(params, false);
> + return;
> + }
> +
> + rkisp1_ctk_config(params, &ctk->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
> + rkisp1_ctk_enable(params, true);
> +}
> +
> +static void
> +rkisp1_ext_params_goc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_goc_config *goc = &block->goc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> + return;
> + }
> +
> + params->ops->goc_config(params, &goc->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + 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)
> +{
> + const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> + RKISP1_CIF_ISP_DPF_MODE_EN);
> + return;
> + }
> +
> + rkisp1_dpf_config(params, &dpf->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> + RKISP1_CIF_ISP_DPF_MODE_EN);
> +}
> +
> +static void
> +rkisp1_ext_params_dpfs(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
> +
> + rkisp1_dpf_strength_config(params, &dpfs->config);
> +}
> +
> +static void
> +rkisp1_ext_params_cproc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
> + RKISP1_CIF_C_PROC_CTR_ENABLE);
> + return;
> + }
> +
> + rkisp1_cproc_config(params, &cproc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
> + RKISP1_CIF_C_PROC_CTR_ENABLE);
> +}
> +
> +static void
> +rkisp1_ext_params_ie(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_ie_config *ie = &block->ie;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_ie_enable(params, false);
> + return;
> + }
> +
> + rkisp1_ie_config(params, &ie->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
> + rkisp1_ie_enable(params, true);
> +}
> +
> +static void
> +rkisp1_ext_params_awbm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + params->ops->awb_meas_enable(params, &awbm->config,
> + false);
> + return;
> + }
> +
> + params->ops->awb_meas_config(params, &awbm->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
> + params->ops->awb_meas_enable(params, &awbm->config,
> + true);
> +}
> +
> +static void
> +rkisp1_ext_params_hstm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_hst_config *hst = &block->hst;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + params->ops->hst_enable(params, &hst->config, false);
> + return;
> + }
> +
> + params->ops->hst_config(params, &hst->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
> + 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)
> +{
> + const struct rkisp1_ext_params_aec_config *aec = &block->aec;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> + RKISP1_CIF_ISP_EXP_ENA);
> + return;
> + }
> +
> + params->ops->aec_config(params, &aec->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> + RKISP1_CIF_ISP_EXP_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_afcm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_afc_config *afc = &block->afc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> + RKISP1_CIF_ISP_AFM_ENA);
> + return;
> + }
> +
> + params->ops->afm_config(params, &afc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> + RKISP1_CIF_ISP_AFM_ENA);
> +}
> +
> +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;
> + unsigned int group;
> +} rkisp1_ext_params_handlers[] = {
> + [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,
> + },
> + [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,
> + },
> +};
> +
> +static void rkisp1_ext_params_config(struct rkisp1_params *params,
> + struct rkisp1_ext_params_cfg *cfg,
> + u32 block_group_mask)
> +{
> + size_t block_offset = 0;
> +
> + if (WARN_ON(!cfg))
> + return;
> +
> + /* 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;
> +
> + block = (const union rkisp1_ext_params_config *)
> + &cfg->data[block_offset];
> + block_offset += block->header.size;
> +
> + /* Make sure the block is in the list of groups to configure. */
> + block_handler = &rkisp1_ext_params_handlers[block->header.type];
> + if (!(block_handler->group & block_group_mask))
> + continue;
> +
> + block_handler->handler(params, block);
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
> + params->enabled_blocks &= ~BIT(block->header.type);
> + else
> + params->enabled_blocks |= BIT(block->header.type);
> + }
> +}
> +
> static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> struct rkisp1_params_buffer *buf,
> unsigned int frame_sequence)
> @@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + } else {
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> + }
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + } else {
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
> + }
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + else
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1862,21 +2346,112 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> spin_unlock_irq(¶ms->config_lock);
> }
>
> -static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> + struct vb2_buffer *vb)
> {
> struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> - struct rkisp1_params_cfg *cfg =
> - vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
> + 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;
>
> - if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
> + /*
> + * 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) {
> + dev_dbg(params->rkisp1->dev,
> + "Too large buffer payload size %lu\n", payload_size);
> + return -EINVAL;
> + }
> +
> + if (payload_size < header_size) {
> + dev_dbg(params->rkisp1->dev,
> + "Buffer payload %lu smaller than header size %lu\n",
> + payload_size, header_size);
> + return -EINVAL;
> + }
> +
> + /*
> + * Copy the parameters buffer to the internal scratch buffer to
> + * avoid userspace modifying the buffer content while the driver
> + * processes it.
> + */
> + memcpy(cfg, usr_cfg, payload_size);
> +
> + /* 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 %lu larger than buffer payload size %lu\n",
'Data size %lu different...'
> + 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;
> + }
> +
> + 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;
> + }
> +
> + return 0;
> +}
> +
> +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +{
> + struct rkisp1_params *params = vb->vb2_queue->drv_priv;
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> + struct rkisp1_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
ack, this was ext_params in my version but this isa the correct
> + size_t payload = vb2_get_plane_payload(vb, 0);
> +
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS)
> + return rkisp1_params_prepare_ext_params(params, vb);
> +
> + /*
> + * For the fixed parameters format the payload size must be exactly the
> + * size of the parameters structure.
> + */
> + if (payload != sizeof(*cfg))
> return -EINVAL;
>
> /*
> - * Copy the parameters buffer to the internal scratch buffer to avoid
> - * userspace modifying the buffer content while the driver processes it.
> + * Copy the parameters buffer to the internal scratch buffer to
> + * avoid userspace modifying the buffer content while the driver
> + * processes it.
I might have missed what has changed here
Anyway
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Thanks
j
> */
> - memcpy(params_buf->cfg, cfg, sizeof(*cfg));
> + memcpy(params_buf->cfg, cfg, payload);
>
> return 0;
> }
> @@ -1898,6 +2473,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
>
> list_for_each_entry(buf, &tmp_list, queue)
> vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> +
> + params->enabled_blocks = 0;
> }
>
> static const struct vb2_ops rkisp1_params_vb2_ops = {
> @@ -1909,7 +2486,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
> .buf_queue = rkisp1_params_vb2_buf_queue,
> .buf_prepare = rkisp1_params_vb2_buf_prepare,
> .stop_streaming = rkisp1_params_vb2_stop_streaming,
> -
> };
>
> static const struct v4l2_file_operations rkisp1_params_fops = {
> --
> Regards,
>
> Laurent Pinchart
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v5.1 6/7] media: rkisp1: Implement extensible params support
2024-07-04 7:36 ` Jacopo Mondi
@ 2024-07-04 9:40 ` Laurent Pinchart
0 siblings, 0 replies; 21+ messages in thread
From: Laurent Pinchart @ 2024-07-04 9:40 UTC (permalink / raw)
To: Jacopo Mondi
Cc: linux-media, Sakari Ailus, Hans Verkuil, Stefan Klug, Paul Elder,
Daniel Scally, Kieran Bingham, Umang Jain, Dafna Hirschfeld,
Mauro Carvalho Chehab, Heiko Stuebner
On Thu, Jul 04, 2024 at 09:36:29AM +0200, Jacopo Mondi wrote:
> Hi Laurent,
> thanks for handling v5.1
>
> On Thu, Jul 04, 2024 at 12:17:27AM GMT, Laurent Pinchart wrote:
> > From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >
> > Implement support in rkisp1-params for the extensible configuration
> > parameters format.
> >
> > Create a list of handlers for each ISP block that wraps the existing
> > configuration functions and handles the ISP block enablement.
> >
> > Parse the configuration parameters buffer in rkisp1_ext_params_config
> > and filter the enable blocks by group, to allow setting the 'other'
> > groups separately from the 'lsc' group to support the pre/post-configure
> > operations.
> >
> > Implement parameter buffer validation for the extensible format at
> > .buf_prepare() time.
> >
> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > Changes since v5:
> >
> > - Use correct struct type for cfg in rkisp1_params_vb2_buf_prepare()
> > - Replace sizeof(type) with sizeof(var)
> > - Refactor rkisp1_params_vb2_buf_prepare() to reduce indentation
> > ---
> > .../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
> > .../platform/rockchip/rkisp1/rkisp1-params.c | 604 +++++++++++++++++-
> > 2 files changed, 593 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > index b4369bbccea3..c1689c0fa05a 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > @@ -401,6 +401,7 @@ struct rkisp1_params_ops {
> > * @quantization: the quantization configured on the isp's src pad
> > * @ycbcr_encoding the YCbCr encoding
> > * @raw_type: the bayer pattern on the isp video sink pad
> > + * @enabled_blocks: bitmask of enabled ISP blocks
> > */
> > struct rkisp1_params {
> > struct rkisp1_vdev_node vnode;
> > @@ -415,6 +416,8 @@ struct rkisp1_params {
> > enum v4l2_quantization quantization;
> > enum v4l2_ycbcr_encoding ycbcr_encoding;
> > enum rkisp1_fmt_raw_pat_type raw_type;
> > +
> > + u32 enabled_blocks;
> > };
> >
> > /*
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > index 45c4b1bcee63..5e83a2e9d818 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > @@ -35,6 +35,30 @@
> > #define RKISP1_ISP_CC_COEFF(n) \
> > (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
> >
> > +#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;
> > +};
> > +
> > enum rkisp1_params_formats {
> > RKISP1_PARAMS_FIXED,
> > RKISP1_PARAMS_EXTENSIBLE,
> > @@ -1519,6 +1543,451 @@ 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)
> > +{
> > + const struct rkisp1_ext_params_bls_config *bls = &block->bls;
> > +
> > + if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> > + RKISP1_CIF_ISP_BLS_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_bls_config(params, &bls->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> > + RKISP1_CIF_ISP_BLS_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
> > +
> > + if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> > + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> > + return;
> > + }
> > +
> > + rkisp1_dpcc_config(params, &dpcc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> > + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_sdg(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_sdg_config(params, &sdg->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> > + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_lsc_config(params, &lsc->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> > + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_awbg(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> > + return;
> > + }
> > +
> > + params->ops->awb_gain_config(params, &awbg->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_flt(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_flt_config *flt = &block->flt;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> > + RKISP1_CIF_ISP_FLT_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_flt_config(params, &flt->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> > + RKISP1_CIF_ISP_FLT_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_bdm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> > + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> > + return;
> > + }
> > +
> > + rkisp1_bdm_config(params, &bdm->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> > + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_ctk(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_ctk_enable(params, false);
> > + return;
> > + }
> > +
> > + rkisp1_ctk_config(params, &ctk->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
> > + rkisp1_ctk_enable(params, true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_goc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_goc_config *goc = &block->goc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> > + return;
> > + }
> > +
> > + params->ops->goc_config(params, &goc->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> > + RKISP1_CIF_ISP_DPF_MODE_EN);
> > + return;
> > + }
> > +
> > + rkisp1_dpf_config(params, &dpf->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> > + RKISP1_CIF_ISP_DPF_MODE_EN);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_dpfs(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
> > +
> > + rkisp1_dpf_strength_config(params, &dpfs->config);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_cproc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
> > + RKISP1_CIF_C_PROC_CTR_ENABLE);
> > + return;
> > + }
> > +
> > + rkisp1_cproc_config(params, &cproc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
> > + RKISP1_CIF_C_PROC_CTR_ENABLE);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_ie(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_ie_config *ie = &block->ie;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_ie_enable(params, false);
> > + return;
> > + }
> > +
> > + rkisp1_ie_config(params, &ie->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
> > + rkisp1_ie_enable(params, true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_awbm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + params->ops->awb_meas_enable(params, &awbm->config,
> > + false);
> > + return;
> > + }
> > +
> > + params->ops->awb_meas_config(params, &awbm->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
> > + params->ops->awb_meas_enable(params, &awbm->config,
> > + true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_hstm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_hst_config *hst = &block->hst;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + params->ops->hst_enable(params, &hst->config, false);
> > + return;
> > + }
> > +
> > + params->ops->hst_config(params, &hst->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_aec_config *aec = &block->aec;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> > + RKISP1_CIF_ISP_EXP_ENA);
> > + return;
> > + }
> > +
> > + params->ops->aec_config(params, &aec->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> > + RKISP1_CIF_ISP_EXP_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_afcm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_afc_config *afc = &block->afc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> > + RKISP1_CIF_ISP_AFM_ENA);
> > + return;
> > + }
> > +
> > + params->ops->afm_config(params, &afc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> > + RKISP1_CIF_ISP_AFM_ENA);
> > +}
> > +
> > +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;
> > + unsigned int group;
> > +} rkisp1_ext_params_handlers[] = {
> > + [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,
> > + },
> > + [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,
> > + },
> > +};
> > +
> > +static void rkisp1_ext_params_config(struct rkisp1_params *params,
> > + struct rkisp1_ext_params_cfg *cfg,
> > + u32 block_group_mask)
> > +{
> > + size_t block_offset = 0;
> > +
> > + if (WARN_ON(!cfg))
> > + return;
> > +
> > + /* 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;
> > +
> > + block = (const union rkisp1_ext_params_config *)
> > + &cfg->data[block_offset];
> > + block_offset += block->header.size;
> > +
> > + /* Make sure the block is in the list of groups to configure. */
> > + block_handler = &rkisp1_ext_params_handlers[block->header.type];
> > + if (!(block_handler->group & block_group_mask))
> > + continue;
> > +
> > + block_handler->handler(params, block);
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
> > + params->enabled_blocks &= ~BIT(block->header.type);
> > + else
> > + params->enabled_blocks |= BIT(block->header.type);
> > + }
> > +}
> > +
> > static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> > struct rkisp1_params_buffer *buf,
> > unsigned int frame_sequence)
> > @@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> > + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + } else {
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> > + }
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> > + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + } else {
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
> > + }
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
> > + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + else
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1862,21 +2346,112 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> > spin_unlock_irq(¶ms->config_lock);
> > }
> >
> > -static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> > +static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> > + struct vb2_buffer *vb)
> > {
> > struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> > struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> > - struct rkisp1_params_cfg *cfg =
> > - vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
> > + 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;
> >
> > - if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
> > + /*
> > + * 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) {
> > + dev_dbg(params->rkisp1->dev,
> > + "Too large buffer payload size %lu\n", payload_size);
> > + return -EINVAL;
> > + }
> > +
> > + if (payload_size < header_size) {
> > + dev_dbg(params->rkisp1->dev,
> > + "Buffer payload %lu smaller than header size %lu\n",
> > + payload_size, header_size);
> > + return -EINVAL;
> > + }
> > +
> > + /*
> > + * Copy the parameters buffer to the internal scratch buffer to
> > + * avoid userspace modifying the buffer content while the driver
> > + * processes it.
> > + */
> > + memcpy(cfg, usr_cfg, payload_size);
> > +
> > + /* 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 %lu larger than buffer payload size %lu\n",
>
> 'Data size %lu different...'
Will fix.
> > + 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;
> > + }
> > +
> > + 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;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> > +{
> > + struct rkisp1_params *params = vb->vb2_queue->drv_priv;
> > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> > + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> > + struct rkisp1_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
>
> ack, this was ext_params in my version but this isa the correct
>
> > + size_t payload = vb2_get_plane_payload(vb, 0);
> > +
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS)
> > + return rkisp1_params_prepare_ext_params(params, vb);
> > +
> > + /*
> > + * For the fixed parameters format the payload size must be exactly the
> > + * size of the parameters structure.
> > + */
> > + if (payload != sizeof(*cfg))
> > return -EINVAL;
> >
> > /*
> > - * Copy the parameters buffer to the internal scratch buffer to avoid
> > - * userspace modifying the buffer content while the driver processes it.
> > + * Copy the parameters buffer to the internal scratch buffer to
> > + * avoid userspace modifying the buffer content while the driver
> > + * processes it.
>
> I might have missed what has changed here
Nothing that I'm aware of. This change comes from your v5 ;-) I'll drop
the modification.
> Anyway
> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>
> > */
> > - memcpy(params_buf->cfg, cfg, sizeof(*cfg));
> > + memcpy(params_buf->cfg, cfg, payload);
> >
> > return 0;
> > }
> > @@ -1898,6 +2473,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
> >
> > list_for_each_entry(buf, &tmp_list, queue)
> > vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> > +
> > + params->enabled_blocks = 0;
> > }
> >
> > static const struct vb2_ops rkisp1_params_vb2_ops = {
> > @@ -1909,7 +2486,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
> > .buf_queue = rkisp1_params_vb2_buf_queue,
> > .buf_prepare = rkisp1_params_vb2_buf_prepare,
> > .stop_streaming = rkisp1_params_vb2_stop_streaming,
> > -
> > };
> >
> > static const struct v4l2_file_operations rkisp1_params_fops = {
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v5.2 6/7] media: rkisp1: Implement extensible params support
2024-07-03 16:10 ` [PATCH v5 6/7] media: rkisp1: Implement extensible params support Jacopo Mondi
2024-07-03 20:56 ` Laurent Pinchart
2024-07-03 21:17 ` [PATCH v5.1 " Laurent Pinchart
@ 2024-07-04 9:56 ` Laurent Pinchart
2024-07-05 11:21 ` Paul Elder
2024-07-06 12:18 ` [PATCH v5 " Sakari Ailus
3 siblings, 1 reply; 21+ messages in thread
From: Laurent Pinchart @ 2024-07-04 9:56 UTC (permalink / raw)
To: linux-media
Cc: Jacopo Mondi, Sakari Ailus, Hans Verkuil, Stefan Klug, Paul Elder,
Daniel Scally, Kieran Bingham, Umang Jain, Dafna Hirschfeld,
Mauro Carvalho Chehab, Heiko Stuebner
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Implement support in rkisp1-params for the extensible configuration
parameters format.
Create a list of handlers for each ISP block that wraps the existing
configuration functions and handles the ISP block enablement.
Parse the configuration parameters buffer in rkisp1_ext_params_config
and filter the enable blocks by group, to allow setting the 'other'
groups separately from the 'lsc' group to support the pre/post-configure
operations.
Implement parameter buffer validation for the extensible format at
.buf_prepare() time.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
Changes since v5.1:
- Fix incorrect debug message
- Avoid rewrapping comments unnecessarily
Changes since v5:
- Use correct struct type for cfg in rkisp1_params_vb2_buf_prepare()
- Replace sizeof(type) with sizeof(var)
- Refactor rkisp1_params_vb2_buf_prepare() to reduce indentation
---
.../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
.../platform/rockchip/rkisp1/rkisp1-params.c | 598 +++++++++++++++++-
2 files changed, 589 insertions(+), 12 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index b4369bbccea3..c1689c0fa05a 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -401,6 +401,7 @@ struct rkisp1_params_ops {
* @quantization: the quantization configured on the isp's src pad
* @ycbcr_encoding the YCbCr encoding
* @raw_type: the bayer pattern on the isp video sink pad
+ * @enabled_blocks: bitmask of enabled ISP blocks
*/
struct rkisp1_params {
struct rkisp1_vdev_node vnode;
@@ -415,6 +416,8 @@ struct rkisp1_params {
enum v4l2_quantization quantization;
enum v4l2_ycbcr_encoding ycbcr_encoding;
enum rkisp1_fmt_raw_pat_type raw_type;
+
+ u32 enabled_blocks;
};
/*
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 45c4b1bcee63..c216aec4252f 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -35,6 +35,30 @@
#define RKISP1_ISP_CC_COEFF(n) \
(RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
+#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;
+};
+
enum rkisp1_params_formats {
RKISP1_PARAMS_FIXED,
RKISP1_PARAMS_EXTENSIBLE,
@@ -1519,6 +1543,451 @@ 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)
+{
+ const struct rkisp1_ext_params_bls_config *bls = &block->bls;
+
+ if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
+ RKISP1_CIF_ISP_BLS_ENA);
+ return;
+ }
+
+ rkisp1_bls_config(params, &bls->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
+ RKISP1_CIF_ISP_BLS_ENA);
+}
+
+static void
+rkisp1_ext_params_dpcc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
+
+ if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
+ RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
+ return;
+ }
+
+ rkisp1_dpcc_config(params, &dpcc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
+ RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
+}
+
+static void
+rkisp1_ext_params_sdg(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
+ return;
+ }
+
+ rkisp1_sdg_config(params, &sdg->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ 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)
+{
+ const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
+ RKISP1_CIF_ISP_LSC_CTRL_ENA);
+ return;
+ }
+
+ rkisp1_lsc_config(params, &lsc->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
+ RKISP1_CIF_ISP_LSC_CTRL_ENA);
+}
+
+static void
+rkisp1_ext_params_awbg(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
+ return;
+ }
+
+ params->ops->awb_gain_config(params, &awbg->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
+}
+
+static void
+rkisp1_ext_params_flt(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_flt_config *flt = &block->flt;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
+ RKISP1_CIF_ISP_FLT_ENA);
+ return;
+ }
+
+ rkisp1_flt_config(params, &flt->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
+ RKISP1_CIF_ISP_FLT_ENA);
+}
+
+static void
+rkisp1_ext_params_bdm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
+ RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
+ return;
+ }
+
+ rkisp1_bdm_config(params, &bdm->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
+ RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
+}
+
+static void
+rkisp1_ext_params_ctk(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_ctk_enable(params, false);
+ return;
+ }
+
+ rkisp1_ctk_config(params, &ctk->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
+ rkisp1_ctk_enable(params, true);
+}
+
+static void
+rkisp1_ext_params_goc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_goc_config *goc = &block->goc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
+ RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
+ return;
+ }
+
+ params->ops->goc_config(params, &goc->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
+ 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)
+{
+ const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
+ RKISP1_CIF_ISP_DPF_MODE_EN);
+ return;
+ }
+
+ rkisp1_dpf_config(params, &dpf->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
+ RKISP1_CIF_ISP_DPF_MODE_EN);
+}
+
+static void
+rkisp1_ext_params_dpfs(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
+
+ rkisp1_dpf_strength_config(params, &dpfs->config);
+}
+
+static void
+rkisp1_ext_params_cproc(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
+ RKISP1_CIF_C_PROC_CTR_ENABLE);
+ return;
+ }
+
+ rkisp1_cproc_config(params, &cproc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
+ RKISP1_CIF_C_PROC_CTR_ENABLE);
+}
+
+static void
+rkisp1_ext_params_ie(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_ie_config *ie = &block->ie;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_ie_enable(params, false);
+ return;
+ }
+
+ rkisp1_ie_config(params, &ie->config);
+
+ if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
+ rkisp1_ie_enable(params, true);
+}
+
+static void
+rkisp1_ext_params_awbm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ params->ops->awb_meas_enable(params, &awbm->config,
+ false);
+ return;
+ }
+
+ params->ops->awb_meas_config(params, &awbm->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
+ params->ops->awb_meas_enable(params, &awbm->config,
+ true);
+}
+
+static void
+rkisp1_ext_params_hstm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_hst_config *hst = &block->hst;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ params->ops->hst_enable(params, &hst->config, false);
+ return;
+ }
+
+ params->ops->hst_config(params, &hst->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
+ 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)
+{
+ const struct rkisp1_ext_params_aec_config *aec = &block->aec;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
+ RKISP1_CIF_ISP_EXP_ENA);
+ return;
+ }
+
+ params->ops->aec_config(params, &aec->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
+ RKISP1_CIF_ISP_EXP_ENA);
+}
+
+static void
+rkisp1_ext_params_afcm(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_afc_config *afc = &block->afc;
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
+ RKISP1_CIF_ISP_AFM_ENA);
+ return;
+ }
+
+ params->ops->afm_config(params, &afc->config);
+
+ if (!(params->enabled_blocks &
+ BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
+ RKISP1_CIF_ISP_AFM_ENA);
+}
+
+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;
+ unsigned int group;
+} rkisp1_ext_params_handlers[] = {
+ [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,
+ },
+ [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,
+ },
+};
+
+static void rkisp1_ext_params_config(struct rkisp1_params *params,
+ struct rkisp1_ext_params_cfg *cfg,
+ u32 block_group_mask)
+{
+ size_t block_offset = 0;
+
+ if (WARN_ON(!cfg))
+ return;
+
+ /* 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;
+
+ block = (const union rkisp1_ext_params_config *)
+ &cfg->data[block_offset];
+ block_offset += block->header.size;
+
+ /* Make sure the block is in the list of groups to configure. */
+ block_handler = &rkisp1_ext_params_handlers[block->header.type];
+ if (!(block_handler->group & block_group_mask))
+ continue;
+
+ block_handler->handler(params, block);
+
+ if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
+ params->enabled_blocks &= ~BIT(block->header.type);
+ else
+ params->enabled_blocks |= BIT(block->header.type);
+ }
+}
+
static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
struct rkisp1_params_buffer *buf,
unsigned int frame_sequence)
@@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_other_config(params, cur_buf->cfg);
- rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
- rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
+ rkisp1_isp_isr_other_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ } else {
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
+ }
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_other_config(params, cur_buf->cfg);
- rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
+ rkisp1_isp_isr_other_config(params, cur_buf->cfg);
+ rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
+ } else {
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
+ }
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
if (!cur_buf)
goto unlock;
- rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
+ rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
+ else
+ rkisp1_ext_params_config(params, cur_buf->cfg,
+ RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
/* update shadow register immediately */
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
@@ -1862,21 +2346,110 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
spin_unlock_irq(¶ms->config_lock);
}
-static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
+static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
+ struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
- struct rkisp1_params_cfg *cfg =
- vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
+ 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;
- if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
+ /*
+ * 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) {
+ dev_dbg(params->rkisp1->dev,
+ "Too large buffer payload size %lu\n", payload_size);
+ return -EINVAL;
+ }
+
+ if (payload_size < header_size) {
+ dev_dbg(params->rkisp1->dev,
+ "Buffer payload %lu smaller than header size %lu\n",
+ payload_size, header_size);
+ return -EINVAL;
+ }
+
+ /*
+ * Copy the parameters buffer to the internal scratch buffer to avoid
+ * userspace modifying the buffer content while the driver processes it.
+ */
+ memcpy(cfg, usr_cfg, payload_size);
+
+ /* 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 %lu different than buffer payload size %lu\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;
+ }
+
+ 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;
+ }
+
+ return 0;
+}
+
+static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
+{
+ struct rkisp1_params *params = vb->vb2_queue->drv_priv;
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
+ struct rkisp1_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
+ size_t payload = vb2_get_plane_payload(vb, 0);
+
+ if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS)
+ return rkisp1_params_prepare_ext_params(params, vb);
+
+ /*
+ * For the fixed parameters format the payload size must be exactly the
+ * size of the parameters structure.
+ */
+ if (payload != sizeof(*cfg))
return -EINVAL;
/*
* Copy the parameters buffer to the internal scratch buffer to avoid
* userspace modifying the buffer content while the driver processes it.
*/
- memcpy(params_buf->cfg, cfg, sizeof(*cfg));
+ memcpy(params_buf->cfg, cfg, payload);
return 0;
}
@@ -1898,6 +2471,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
list_for_each_entry(buf, &tmp_list, queue)
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+
+ params->enabled_blocks = 0;
}
static const struct vb2_ops rkisp1_params_vb2_ops = {
@@ -1909,7 +2484,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
.buf_queue = rkisp1_params_vb2_buf_queue,
.buf_prepare = rkisp1_params_vb2_buf_prepare,
.stop_streaming = rkisp1_params_vb2_stop_streaming,
-
};
static const struct v4l2_file_operations rkisp1_params_fops = {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v5 4/7] media: rkisp1: Copy the parameters buffer
2024-07-03 16:10 ` [PATCH v5 4/7] media: rkisp1: Copy the parameters buffer Jacopo Mondi
@ 2024-07-05 10:52 ` Paul Elder
0 siblings, 0 replies; 21+ messages in thread
From: Paul Elder @ 2024-07-05 10:52 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Linux Media Mailing List, Laurent Pinchart, Sakari Ailus,
Hans Verkuil, Stefan Klug, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
On Wed, Jul 03, 2024 at 06:10:43PM +0200, Jacopo Mondi wrote:
> The ISP parameters buffers are queued by userspace to the params video
> device and appended by the driver to the list of available buffers for
> later consumption.
>
> As the parameters buffer is mapped in the userspace process memory,
> applications have access to the buffer content after the buffer has
> been queued.
>
> To prevent userspace from modifying the contents of the parameters buffer
> after it has been queued to the video device, add to 'struct
> rkisp1_params_buffer' a scratch buffer where to copy the parameters.
>
> Allocate the scratch buffer in the vb2 buf_init() operation and copy the
> buffer content in the buf_prepare() operation. Free the scratch
> buffer in the newly introduced buf_cleanup() operation handler.
>
> Modify the ISP configuration function to access the ISP configuration
> from the cached copy of the parameters buffer instead of using the
> userspace-mapped one.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> ---
> .../platform/rockchip/rkisp1/rkisp1-common.h | 8 ++
> .../platform/rockchip/rkisp1/rkisp1-params.c | 83 ++++++++++++-------
> 2 files changed, 60 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> index a615bbb0255e..8d520c5c71c3 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> @@ -250,12 +250,20 @@ struct rkisp1_buffer {
> *
> * @vb: vb2 buffer
> * @queue: entry of the buffer in the queue
> + * @cfg: scratch buffer used for caching the ISP configuration parameters
> */
> struct rkisp1_params_buffer {
> struct vb2_v4l2_buffer vb;
> struct list_head queue;
> + struct rkisp1_params_cfg *cfg;
> };
>
> +static inline struct rkisp1_params_buffer *
> +to_rkisp1_params_buffer(struct vb2_v4l2_buffer *vbuf)
> +{
> + return container_of(vbuf, struct rkisp1_params_buffer, vb);
> +}
> +
> /*
> * struct rkisp1_dummy_buffer - A buffer to write the next frame to in case
> * there are no vb2 buffers available.
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 2844e55bc4f2..e333cda21fdd 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -5,6 +5,8 @@
> * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> */
>
> +#include <linux/string.h>
> +
> #include <media/v4l2-common.h>
> #include <media/v4l2-event.h>
> #include <media/v4l2-ioctl.h>
> @@ -1501,20 +1503,6 @@ static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params,
> }
> }
>
> -static bool rkisp1_params_get_buffer(struct rkisp1_params *params,
> - struct rkisp1_params_buffer **buf,
> - struct rkisp1_params_cfg **cfg)
> -{
> - if (list_empty(¶ms->params))
> - return false;
> -
> - *buf = list_first_entry(¶ms->params, struct rkisp1_params_buffer,
> - queue);
> - *cfg = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0);
> -
> - return true;
> -}
> -
> static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> struct rkisp1_params_buffer *buf,
> unsigned int frame_sequence)
> @@ -1528,17 +1516,18 @@ static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> void rkisp1_params_isr(struct rkisp1_device *rkisp1)
> {
> struct rkisp1_params *params = &rkisp1->params;
> - struct rkisp1_params_cfg *new_params;
> struct rkisp1_params_buffer *cur_buf;
>
> spin_lock(¶ms->config_lock);
>
> - if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params))
> + cur_buf = list_first_entry_or_null(¶ms->params,
> + struct rkisp1_params_buffer, queue);
> + if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, new_params);
> - rkisp1_isp_isr_lsc_config(params, new_params);
> - rkisp1_isp_isr_meas_config(params, new_params);
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1604,7 +1593,6 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
> enum v4l2_ycbcr_encoding ycbcr_encoding)
> {
> struct rkisp1_cif_isp_hst_config hst = rkisp1_hst_params_default_config;
> - struct rkisp1_params_cfg *new_params;
> struct rkisp1_params_buffer *cur_buf;
>
> params->quantization = quantization;
> @@ -1634,11 +1622,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
>
> /* apply the first buffer if there is one already */
>
> - if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params))
> + cur_buf = list_first_entry_or_null(¶ms->params,
> + struct rkisp1_params_buffer, queue);
> + if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, new_params);
> - rkisp1_isp_isr_meas_config(params, new_params);
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1650,7 +1640,6 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
>
> void rkisp1_params_post_configure(struct rkisp1_params *params)
> {
> - struct rkisp1_params_cfg *new_params;
> struct rkisp1_params_buffer *cur_buf;
>
> spin_lock_irq(¶ms->config_lock);
> @@ -1663,11 +1652,12 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
> * ordering doesn't affect other ISP versions negatively, do so
> * unconditionally.
> */
> -
> - if (!rkisp1_params_get_buffer(params, &cur_buf, &new_params))
> + cur_buf = list_first_entry_or_null(¶ms->params,
> + struct rkisp1_params_buffer, queue);
> + if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_lsc_config(params, new_params);
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1819,11 +1809,31 @@ static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
> return 0;
> }
>
> +static int rkisp1_params_vb2_buf_init(struct vb2_buffer *vb)
> +{
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> +
> + params_buf->cfg = kvmalloc(sizeof(*params_buf->cfg), GFP_KERNEL);
> + if (!params_buf->cfg)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> +static void rkisp1_params_vb2_buf_cleanup(struct vb2_buffer *vb)
> +{
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> +
> + kvfree(params_buf->cfg);
> + params_buf->cfg = NULL;
> +}
> +
> static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> {
> struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> - struct rkisp1_params_buffer *params_buf =
> - container_of(vbuf, struct rkisp1_params_buffer, vb);
> + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> struct vb2_queue *vq = vb->vb2_queue;
> struct rkisp1_params *params = vq->drv_priv;
>
> @@ -1834,10 +1844,19 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
>
> static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> {
> - if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_params_cfg))
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> + struct rkisp1_params_cfg *cfg =
> + vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
> +
> + if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
> return -EINVAL;
>
> - vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_params_cfg));
> + /*
> + * Copy the parameters buffer to the internal scratch buffer to avoid
> + * userspace modifying the buffer content while the driver processes it.
> + */
> + memcpy(params_buf->cfg, cfg, sizeof(*cfg));
>
> return 0;
> }
> @@ -1863,6 +1882,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
>
> static const struct vb2_ops rkisp1_params_vb2_ops = {
> .queue_setup = rkisp1_params_vb2_queue_setup,
> + .buf_init = rkisp1_params_vb2_buf_init,
> + .buf_cleanup = rkisp1_params_vb2_buf_cleanup,
> .wait_prepare = vb2_ops_wait_prepare,
> .wait_finish = vb2_ops_wait_finish,
> .buf_queue = rkisp1_params_vb2_buf_queue,
> --
> 2.45.2
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v5 5/7] media: rkisp1: Cache the currently active format
2024-07-03 16:10 ` [PATCH v5 5/7] media: rkisp1: Cache the currently active format Jacopo Mondi
@ 2024-07-05 10:56 ` Paul Elder
0 siblings, 0 replies; 21+ messages in thread
From: Paul Elder @ 2024-07-05 10:56 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Linux Media Mailing List, Laurent Pinchart, Sakari Ailus,
Hans Verkuil, Stefan Klug, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
On Wed, Jul 03, 2024 at 06:10:44PM +0200, Jacopo Mondi wrote:
> The rkisp1-params driver assumes the data buffer format is the only
> currently supported "fixed" one. The usage of the "fixed" format is
> assumed when allocating memory for the scratch buffers and when
> initializing the vb2 queue.
>
> In order to prepare to support the "extensible" format beside the
> existing "fixed" one, add support in the driver for both formats by
> caching a pointer to the active one in the driver structure and use it
> in the vb2 queue operations and subdev pad operations implementations.
>
> Do not yet allow userspace to select between the two formats as the
> support for the "extensible" format parsing will be introduced in a later
> patch in the series.
>
> While at it, document the un-documented ycbcr_encoding field of
> struct rkisp1_params_ops.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> ---
> .../platform/rockchip/rkisp1/rkisp1-common.h | 8 +--
> .../platform/rockchip/rkisp1/rkisp1-params.c | 52 ++++++++++++-------
> 2 files changed, 38 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> index 8d520c5c71c3..43cc727a628d 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> @@ -255,7 +255,7 @@ struct rkisp1_buffer {
> struct rkisp1_params_buffer {
> struct vb2_v4l2_buffer vb;
> struct list_head queue;
> - struct rkisp1_params_cfg *cfg;
> + void *cfg;
> };
>
> static inline struct rkisp1_params_buffer *
> @@ -392,8 +392,9 @@ struct rkisp1_params_ops {
> * @ops: pointer to the variant-specific operations
> * @config_lock: locks the buffer list 'params'
> * @params: queue of rkisp1_buffer
> - * @vdev_fmt: v4l2_format of the metadata format
> + * @metafmt the currently enabled metadata format
> * @quantization: the quantization configured on the isp's src pad
> + * @ycbcr_encoding the YCbCr encoding
> * @raw_type: the bayer pattern on the isp video sink pad
> */
> struct rkisp1_params {
> @@ -403,7 +404,8 @@ struct rkisp1_params {
>
> spinlock_t config_lock; /* locks the buffers list 'params' */
> struct list_head params;
> - struct v4l2_format vdev_fmt;
> +
> + const struct v4l2_meta_format *metafmt;
>
> enum v4l2_quantization quantization;
> enum v4l2_ycbcr_encoding ycbcr_encoding;
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index e333cda21fdd..45c4b1bcee63 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -35,6 +35,22 @@
> #define RKISP1_ISP_CC_COEFF(n) \
> (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
>
> +enum rkisp1_params_formats {
> + RKISP1_PARAMS_FIXED,
> + RKISP1_PARAMS_EXTENSIBLE,
> +};
> +
> +static const struct v4l2_meta_format rkisp1_params_formats[] = {
> + [RKISP1_PARAMS_FIXED] = {
> + .dataformat = V4L2_META_FMT_RK_ISP1_PARAMS,
> + .buffersize = sizeof(struct rkisp1_params_cfg),
> + },
> + [RKISP1_PARAMS_EXTENSIBLE] = {
> + .dataformat = V4L2_META_FMT_RK_ISP1_EXT_PARAMS,
> + .buffersize = sizeof(struct rkisp1_ext_params_cfg),
> + },
> +};
> +
> static inline void
> rkisp1_param_set_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask)
> {
> @@ -1738,7 +1754,7 @@ static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv,
> if (f->index > 0 || f->type != video->queue->type)
> return -EINVAL;
>
> - f->pixelformat = params->vdev_fmt.fmt.meta.dataformat;
> + f->pixelformat = params->metafmt->dataformat;
>
> return 0;
> }
> @@ -1754,8 +1770,8 @@ static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh,
> return -EINVAL;
>
> memset(meta, 0, sizeof(*meta));
> - meta->dataformat = params->vdev_fmt.fmt.meta.dataformat;
> - meta->buffersize = params->vdev_fmt.fmt.meta.buffersize;
> + meta->dataformat = params->metafmt->dataformat;
> + meta->buffersize = params->metafmt->buffersize;
>
> return 0;
> }
> @@ -1798,13 +1814,15 @@ static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
> unsigned int sizes[],
> struct device *alloc_devs[])
> {
> + struct rkisp1_params *params = vq->drv_priv;
> +
> *num_buffers = clamp_t(u32, *num_buffers,
> RKISP1_ISP_PARAMS_REQ_BUFS_MIN,
> RKISP1_ISP_PARAMS_REQ_BUFS_MAX);
>
> *num_planes = 1;
>
> - sizes[0] = sizeof(struct rkisp1_params_cfg);
> + sizes[0] = params->metafmt->buffersize;
>
> return 0;
> }
> @@ -1813,8 +1831,10 @@ static int rkisp1_params_vb2_buf_init(struct vb2_buffer *vb)
> {
> struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> + struct rkisp1_params *params = vb->vb2_queue->drv_priv;
>
> - params_buf->cfg = kvmalloc(sizeof(*params_buf->cfg), GFP_KERNEL);
> + params_buf->cfg = kvmalloc(params->metafmt->buffersize,
> + GFP_KERNEL);
> if (!params_buf->cfg)
> return -ENOMEM;
>
> @@ -1919,19 +1939,6 @@ static int rkisp1_params_init_vb2_queue(struct vb2_queue *q,
> return vb2_queue_init(q);
> }
>
> -static void rkisp1_init_params(struct rkisp1_params *params)
> -{
> - params->vdev_fmt.fmt.meta.dataformat =
> - V4L2_META_FMT_RK_ISP1_PARAMS;
> - params->vdev_fmt.fmt.meta.buffersize =
> - sizeof(struct rkisp1_params_cfg);
> -
> - if (params->rkisp1->info->isp_ver == RKISP1_V12)
> - params->ops = &rkisp1_v12_params_ops;
> - else
> - params->ops = &rkisp1_v10_params_ops;
> -}
> -
> int rkisp1_params_register(struct rkisp1_device *rkisp1)
> {
> struct rkisp1_params *params = &rkisp1->params;
> @@ -1960,7 +1967,14 @@ int rkisp1_params_register(struct rkisp1_device *rkisp1)
> vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT;
> vdev->vfl_dir = VFL_DIR_TX;
> rkisp1_params_init_vb2_queue(vdev->queue, params);
> - rkisp1_init_params(params);
> +
> + params->metafmt = &rkisp1_params_formats[RKISP1_PARAMS_FIXED];
> +
> + if (params->rkisp1->info->isp_ver == RKISP1_V12)
> + params->ops = &rkisp1_v12_params_ops;
> + else
> + params->ops = &rkisp1_v10_params_ops;
> +
> video_set_drvdata(vdev, params);
>
> node->pad.flags = MEDIA_PAD_FL_SOURCE;
> --
> 2.45.2
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v5.2 6/7] media: rkisp1: Implement extensible params support
2024-07-04 9:56 ` [PATCH v5.2 " Laurent Pinchart
@ 2024-07-05 11:21 ` Paul Elder
2024-07-08 8:39 ` Jacopo Mondi
0 siblings, 1 reply; 21+ messages in thread
From: Paul Elder @ 2024-07-05 11:21 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Jacopo Mondi, Sakari Ailus, Hans Verkuil,
Stefan Klug, Daniel Scally, Kieran Bingham, Umang Jain,
Dafna Hirschfeld, Mauro Carvalho Chehab, Heiko Stuebner
On Thu, Jul 04, 2024 at 12:56:11PM +0300, Laurent Pinchart wrote:
> From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>
> Implement support in rkisp1-params for the extensible configuration
> parameters format.
>
> Create a list of handlers for each ISP block that wraps the existing
> configuration functions and handles the ISP block enablement.
>
> Parse the configuration parameters buffer in rkisp1_ext_params_config
> and filter the enable blocks by group, to allow setting the 'other'
> groups separately from the 'lsc' group to support the pre/post-configure
> operations.
>
> Implement parameter buffer validation for the extensible format at
> .buf_prepare() time.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> Changes since v5.1:
>
> - Fix incorrect debug message
> - Avoid rewrapping comments unnecessarily
>
> Changes since v5:
>
> - Use correct struct type for cfg in rkisp1_params_vb2_buf_prepare()
> - Replace sizeof(type) with sizeof(var)
> - Refactor rkisp1_params_vb2_buf_prepare() to reduce indentation
> ---
> .../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
> .../platform/rockchip/rkisp1/rkisp1-params.c | 598 +++++++++++++++++-
> 2 files changed, 589 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> index b4369bbccea3..c1689c0fa05a 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> @@ -401,6 +401,7 @@ struct rkisp1_params_ops {
> * @quantization: the quantization configured on the isp's src pad
> * @ycbcr_encoding the YCbCr encoding
> * @raw_type: the bayer pattern on the isp video sink pad
> + * @enabled_blocks: bitmask of enabled ISP blocks
> */
> struct rkisp1_params {
> struct rkisp1_vdev_node vnode;
> @@ -415,6 +416,8 @@ struct rkisp1_params {
> enum v4l2_quantization quantization;
> enum v4l2_ycbcr_encoding ycbcr_encoding;
> enum rkisp1_fmt_raw_pat_type raw_type;
> +
> + u32 enabled_blocks;
> };
>
> /*
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 45c4b1bcee63..c216aec4252f 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -35,6 +35,30 @@
> #define RKISP1_ISP_CC_COEFF(n) \
> (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
>
> +#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;
> +};
> +
I was wondering if this would cause uapi breakages if a bigger one was
added in the future but I see that based on how this is used it should
be fine.
> enum rkisp1_params_formats {
> RKISP1_PARAMS_FIXED,
> RKISP1_PARAMS_EXTENSIBLE,
> @@ -1519,6 +1543,451 @@ 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)
> +{
> + const struct rkisp1_ext_params_bls_config *bls = &block->bls;
> +
> + if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> + RKISP1_CIF_ISP_BLS_ENA);
> + return;
> + }
> +
> + rkisp1_bls_config(params, &bls->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> + RKISP1_CIF_ISP_BLS_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
> +
> + if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> + return;
> + }
> +
> + rkisp1_dpcc_config(params, &dpcc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> +}
> +
> +static void
> +rkisp1_ext_params_sdg(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> + return;
> + }
> +
> + rkisp1_sdg_config(params, &sdg->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + 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)
> +{
> + const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> + return;
> + }
> +
> + rkisp1_lsc_config(params, &lsc->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_awbg(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> + return;
> + }
> +
> + params->ops->awb_gain_config(params, &awbg->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_flt(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_flt_config *flt = &block->flt;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> + RKISP1_CIF_ISP_FLT_ENA);
> + return;
> + }
> +
> + rkisp1_flt_config(params, &flt->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> + RKISP1_CIF_ISP_FLT_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_bdm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> + return;
> + }
> +
> + rkisp1_bdm_config(params, &bdm->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> +}
> +
> +static void
> +rkisp1_ext_params_ctk(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_ctk_enable(params, false);
> + return;
> + }
> +
> + rkisp1_ctk_config(params, &ctk->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
> + rkisp1_ctk_enable(params, true);
> +}
> +
> +static void
> +rkisp1_ext_params_goc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_goc_config *goc = &block->goc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> + return;
> + }
> +
> + params->ops->goc_config(params, &goc->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + 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)
> +{
> + const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> + RKISP1_CIF_ISP_DPF_MODE_EN);
> + return;
> + }
> +
> + rkisp1_dpf_config(params, &dpf->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> + RKISP1_CIF_ISP_DPF_MODE_EN);
> +}
> +
> +static void
> +rkisp1_ext_params_dpfs(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
> +
> + rkisp1_dpf_strength_config(params, &dpfs->config);
> +}
> +
> +static void
> +rkisp1_ext_params_cproc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
> + RKISP1_CIF_C_PROC_CTR_ENABLE);
> + return;
> + }
> +
> + rkisp1_cproc_config(params, &cproc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
> + RKISP1_CIF_C_PROC_CTR_ENABLE);
> +}
> +
> +static void
> +rkisp1_ext_params_ie(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_ie_config *ie = &block->ie;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_ie_enable(params, false);
> + return;
> + }
> +
> + rkisp1_ie_config(params, &ie->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
> + rkisp1_ie_enable(params, true);
> +}
> +
> +static void
> +rkisp1_ext_params_awbm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + params->ops->awb_meas_enable(params, &awbm->config,
> + false);
> + return;
> + }
> +
> + params->ops->awb_meas_config(params, &awbm->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
> + params->ops->awb_meas_enable(params, &awbm->config,
> + true);
> +}
> +
> +static void
> +rkisp1_ext_params_hstm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_hst_config *hst = &block->hst;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + params->ops->hst_enable(params, &hst->config, false);
> + return;
> + }
> +
> + params->ops->hst_config(params, &hst->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
> + 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)
> +{
> + const struct rkisp1_ext_params_aec_config *aec = &block->aec;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> + RKISP1_CIF_ISP_EXP_ENA);
> + return;
> + }
> +
> + params->ops->aec_config(params, &aec->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> + RKISP1_CIF_ISP_EXP_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_afcm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_afc_config *afc = &block->afc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> + RKISP1_CIF_ISP_AFM_ENA);
> + return;
> + }
> +
> + params->ops->afm_config(params, &afc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> + RKISP1_CIF_ISP_AFM_ENA);
> +}
> +
> +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;
> + unsigned int group;
> +} rkisp1_ext_params_handlers[] = {
> + [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,
> + },
> + [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,
> + },
> +};
> +
> +static void rkisp1_ext_params_config(struct rkisp1_params *params,
> + struct rkisp1_ext_params_cfg *cfg,
> + u32 block_group_mask)
> +{
> + size_t block_offset = 0;
> +
> + if (WARN_ON(!cfg))
> + return;
> +
> + /* 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;
> +
> + block = (const union rkisp1_ext_params_config *)
> + &cfg->data[block_offset];
> + block_offset += block->header.size;
> +
> + /* Make sure the block is in the list of groups to configure. */
> + block_handler = &rkisp1_ext_params_handlers[block->header.type];
Doesn't block->header.type come from userspace...? What if it's past the
array size...?
Oh it's validated below in rkisp1_params_prepare_ext_params ok.
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> + if (!(block_handler->group & block_group_mask))
> + continue;
> +
> + block_handler->handler(params, block);
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
> + params->enabled_blocks &= ~BIT(block->header.type);
> + else
> + params->enabled_blocks |= BIT(block->header.type);
> + }
> +}
> +
> static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> struct rkisp1_params_buffer *buf,
> unsigned int frame_sequence)
> @@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + } else {
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> + }
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + } else {
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
> + }
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + else
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1862,21 +2346,110 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> spin_unlock_irq(¶ms->config_lock);
> }
>
> -static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> + struct vb2_buffer *vb)
> {
> struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> - struct rkisp1_params_cfg *cfg =
> - vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
> + 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;
>
> - if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
> + /*
> + * 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) {
> + dev_dbg(params->rkisp1->dev,
> + "Too large buffer payload size %lu\n", payload_size);
> + return -EINVAL;
> + }
> +
> + if (payload_size < header_size) {
> + dev_dbg(params->rkisp1->dev,
> + "Buffer payload %lu smaller than header size %lu\n",
> + payload_size, header_size);
> + return -EINVAL;
> + }
> +
> + /*
> + * Copy the parameters buffer to the internal scratch buffer to avoid
> + * userspace modifying the buffer content while the driver processes it.
> + */
> + memcpy(cfg, usr_cfg, payload_size);
> +
> + /* 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 %lu different than buffer payload size %lu\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;
> + }
> +
> + 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;
> + }
> +
> + return 0;
> +}
> +
> +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +{
> + struct rkisp1_params *params = vb->vb2_queue->drv_priv;
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> + struct rkisp1_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
> + size_t payload = vb2_get_plane_payload(vb, 0);
> +
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS)
> + return rkisp1_params_prepare_ext_params(params, vb);
> +
> + /*
> + * For the fixed parameters format the payload size must be exactly the
> + * size of the parameters structure.
> + */
> + if (payload != sizeof(*cfg))
> return -EINVAL;
>
> /*
> * Copy the parameters buffer to the internal scratch buffer to avoid
> * userspace modifying the buffer content while the driver processes it.
> */
> - memcpy(params_buf->cfg, cfg, sizeof(*cfg));
> + memcpy(params_buf->cfg, cfg, payload);
>
> return 0;
> }
> @@ -1898,6 +2471,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
>
> list_for_each_entry(buf, &tmp_list, queue)
> vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> +
> + params->enabled_blocks = 0;
> }
>
> static const struct vb2_ops rkisp1_params_vb2_ops = {
> @@ -1909,7 +2484,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
> .buf_queue = rkisp1_params_vb2_buf_queue,
> .buf_prepare = rkisp1_params_vb2_buf_prepare,
> .stop_streaming = rkisp1_params_vb2_stop_streaming,
> -
> };
>
> static const struct v4l2_file_operations rkisp1_params_fops = {
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v5 7/7] media: rkisp1: Implement s_fmt/try_fmt
2024-07-03 16:10 ` [PATCH v5 7/7] media: rkisp1: Implement s_fmt/try_fmt Jacopo Mondi
@ 2024-07-05 11:23 ` Paul Elder
0 siblings, 0 replies; 21+ messages in thread
From: Paul Elder @ 2024-07-05 11:23 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Linux Media Mailing List, Laurent Pinchart, Sakari Ailus,
Hans Verkuil, Stefan Klug, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
On Wed, Jul 03, 2024 at 06:10:46PM +0200, Jacopo Mondi wrote:
> Implement in the rkisp1 driver support for the s_fmt and try_fmt
> operation to allow userspace to select between the extensible
> and the fixed parameters formats.
>
> Implement enum_mbus_code to enumerate the fixed and the extensible
> formats and disallow changing the data format while the queue is busy.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> ---
> .../platform/rockchip/rkisp1/rkisp1-params.c | 58 ++++++++++++++++---
> 1 file changed, 50 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 3ef410337aa2..ea1ad92d2b21 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -75,6 +75,17 @@ static const struct v4l2_meta_format rkisp1_params_formats[] = {
> },
> };
>
> +static const struct v4l2_meta_format *
> +rkisp1_params_get_format_info(u32 dataformat)
> +{
> + for (unsigned int i = 0; i < ARRAY_SIZE(rkisp1_params_formats); i++) {
> + if (rkisp1_params_formats[i].dataformat == dataformat)
> + return &rkisp1_params_formats[i];
> + }
> +
> + return &rkisp1_params_formats[RKISP1_PARAMS_FIXED];
> +}
> +
> static inline void
> rkisp1_param_set_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask)
> {
> @@ -2233,12 +2244,12 @@ static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv,
> struct v4l2_fmtdesc *f)
> {
> struct video_device *video = video_devdata(file);
> - struct rkisp1_params *params = video_get_drvdata(video);
>
> - if (f->index > 0 || f->type != video->queue->type)
> + if (f->index >= ARRAY_SIZE(rkisp1_params_formats) ||
> + f->type != video->queue->type)
> return -EINVAL;
>
> - f->pixelformat = params->metafmt->dataformat;
> + f->pixelformat = rkisp1_params_formats[f->index].dataformat;
>
> return 0;
> }
> @@ -2253,9 +2264,40 @@ static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh,
> if (f->type != video->queue->type)
> return -EINVAL;
>
> - memset(meta, 0, sizeof(*meta));
> - meta->dataformat = params->metafmt->dataformat;
> - meta->buffersize = params->metafmt->buffersize;
> + *meta = *params->metafmt;
> +
> + return 0;
> +}
> +
> +static int rkisp1_params_try_fmt_meta_out(struct file *file, void *fh,
> + struct v4l2_format *f)
> +{
> + struct video_device *video = video_devdata(file);
> + struct v4l2_meta_format *meta = &f->fmt.meta;
> +
> + if (f->type != video->queue->type)
> + return -EINVAL;
> +
> + *meta = *rkisp1_params_get_format_info(meta->dataformat);
> +
> + return 0;
> +}
> +
> +static int rkisp1_params_s_fmt_meta_out(struct file *file, void *fh,
> + struct v4l2_format *f)
> +{
> + struct video_device *video = video_devdata(file);
> + struct rkisp1_params *params = video_get_drvdata(video);
> + struct v4l2_meta_format *meta = &f->fmt.meta;
> +
> + if (f->type != video->queue->type)
> + return -EINVAL;
> +
> + if (vb2_is_busy(video->queue))
> + return -EBUSY;
> +
> + params->metafmt = rkisp1_params_get_format_info(meta->dataformat);
> + *meta = *params->metafmt;
>
> return 0;
> }
> @@ -2285,8 +2327,8 @@ static const struct v4l2_ioctl_ops rkisp1_params_ioctl = {
> .vidioc_streamoff = vb2_ioctl_streamoff,
> .vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out,
> .vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> - .vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> - .vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out,
> + .vidioc_s_fmt_meta_out = rkisp1_params_s_fmt_meta_out,
> + .vidioc_try_fmt_meta_out = rkisp1_params_try_fmt_meta_out,
> .vidioc_querycap = rkisp1_params_querycap,
> .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> --
> 2.45.2
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v5 6/7] media: rkisp1: Implement extensible params support
2024-07-03 16:10 ` [PATCH v5 6/7] media: rkisp1: Implement extensible params support Jacopo Mondi
` (2 preceding siblings ...)
2024-07-04 9:56 ` [PATCH v5.2 " Laurent Pinchart
@ 2024-07-06 12:18 ` Sakari Ailus
2024-07-08 8:25 ` Jacopo Mondi
3 siblings, 1 reply; 21+ messages in thread
From: Sakari Ailus @ 2024-07-06 12:18 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Linux Media Mailing List, Laurent Pinchart, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
Hi Jacopo,
On Wed, Jul 03, 2024 at 06:10:45PM +0200, Jacopo Mondi wrote:
> Implement support in rkisp1-params for the extensible configuration
> parameters format.
>
> Create a list of handlers for each ISP block that wraps the existing
> configuration functions and handles the ISP block enablement.
>
> Parse the configuration parameters buffer in rkisp1_ext_params_config
> and filter the enable blocks by group, to allow setting the 'other'
> groups separately from the 'lsc' group to support the pre/post-configure
> operations.
>
> Implement parameter buffer validation for the extensible format at
> .buf_prepare() time.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
> .../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
> .../platform/rockchip/rkisp1/rkisp1-params.c | 602 +++++++++++++++++-
> 2 files changed, 591 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> index 43cc727a628d..2f4bf7e97927 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> @@ -396,6 +396,7 @@ struct rkisp1_params_ops {
> * @quantization: the quantization configured on the isp's src pad
> * @ycbcr_encoding the YCbCr encoding
> * @raw_type: the bayer pattern on the isp video sink pad
> + * @enabled_blocks: bitmask of enabled ISP blocks
> */
> struct rkisp1_params {
> struct rkisp1_vdev_node vnode;
> @@ -410,6 +411,8 @@ struct rkisp1_params {
> enum v4l2_quantization quantization;
> enum v4l2_ycbcr_encoding ycbcr_encoding;
> enum rkisp1_fmt_raw_pat_type raw_type;
> +
> + u32 enabled_blocks;
> };
>
> /*
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 45c4b1bcee63..3ef410337aa2 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -35,6 +35,30 @@
> #define RKISP1_ISP_CC_COEFF(n) \
> (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
>
> +#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;
> +};
> +
> enum rkisp1_params_formats {
> RKISP1_PARAMS_FIXED,
> RKISP1_PARAMS_EXTENSIBLE,
> @@ -1519,6 +1543,451 @@ 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)
> +{
> + const struct rkisp1_ext_params_bls_config *bls = &block->bls;
> +
> + if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> + RKISP1_CIF_ISP_BLS_ENA);
> + return;
> + }
> +
> + rkisp1_bls_config(params, &bls->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> + RKISP1_CIF_ISP_BLS_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
> +
> + if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> + return;
> + }
> +
> + rkisp1_dpcc_config(params, &dpcc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> +}
> +
> +static void
> +rkisp1_ext_params_sdg(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> + return;
> + }
> +
> + rkisp1_sdg_config(params, &sdg->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + 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)
> +{
> + const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> + return;
> + }
> +
> + rkisp1_lsc_config(params, &lsc->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_awbg(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> + return;
> + }
> +
> + params->ops->awb_gain_config(params, &awbg->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_flt(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_flt_config *flt = &block->flt;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> + RKISP1_CIF_ISP_FLT_ENA);
> + return;
> + }
> +
> + rkisp1_flt_config(params, &flt->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> + RKISP1_CIF_ISP_FLT_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_bdm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> + return;
> + }
> +
> + rkisp1_bdm_config(params, &bdm->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> +}
> +
> +static void
> +rkisp1_ext_params_ctk(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_ctk_enable(params, false);
> + return;
> + }
> +
> + rkisp1_ctk_config(params, &ctk->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
> + rkisp1_ctk_enable(params, true);
> +}
> +
> +static void
> +rkisp1_ext_params_goc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_goc_config *goc = &block->goc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> + return;
> + }
> +
> + params->ops->goc_config(params, &goc->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> + 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)
> +{
> + const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> + RKISP1_CIF_ISP_DPF_MODE_EN);
> + return;
> + }
> +
> + rkisp1_dpf_config(params, &dpf->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> + RKISP1_CIF_ISP_DPF_MODE_EN);
> +}
> +
> +static void
> +rkisp1_ext_params_dpfs(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
> +
> + rkisp1_dpf_strength_config(params, &dpfs->config);
> +}
> +
> +static void
> +rkisp1_ext_params_cproc(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
> + RKISP1_CIF_C_PROC_CTR_ENABLE);
> + return;
> + }
> +
> + rkisp1_cproc_config(params, &cproc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
> + RKISP1_CIF_C_PROC_CTR_ENABLE);
> +}
> +
> +static void
> +rkisp1_ext_params_ie(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_ie_config *ie = &block->ie;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_ie_enable(params, false);
> + return;
> + }
> +
> + rkisp1_ie_config(params, &ie->config);
> +
> + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
> + rkisp1_ie_enable(params, true);
> +}
> +
> +static void
> +rkisp1_ext_params_awbm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + params->ops->awb_meas_enable(params, &awbm->config,
> + false);
> + return;
> + }
> +
> + params->ops->awb_meas_config(params, &awbm->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
> + params->ops->awb_meas_enable(params, &awbm->config,
> + true);
> +}
> +
> +static void
> +rkisp1_ext_params_hstm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_hst_config *hst = &block->hst;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + params->ops->hst_enable(params, &hst->config, false);
> + return;
> + }
> +
> + params->ops->hst_config(params, &hst->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
> + 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)
> +{
> + const struct rkisp1_ext_params_aec_config *aec = &block->aec;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> + RKISP1_CIF_ISP_EXP_ENA);
> + return;
> + }
> +
> + params->ops->aec_config(params, &aec->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> + RKISP1_CIF_ISP_EXP_ENA);
> +}
> +
> +static void
> +rkisp1_ext_params_afcm(struct rkisp1_params *params,
> + const union rkisp1_ext_params_config *block)
> +{
> + const struct rkisp1_ext_params_afc_config *afc = &block->afc;
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> + RKISP1_CIF_ISP_AFM_ENA);
> + return;
> + }
> +
> + params->ops->afm_config(params, &afc->config);
> +
> + if (!(params->enabled_blocks &
> + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
> + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> + RKISP1_CIF_ISP_AFM_ENA);
> +}
> +
> +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;
> + unsigned int group;
> +} rkisp1_ext_params_handlers[] = {
> + [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,
> + },
> + [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,
> + },
> +};
> +
> +static void rkisp1_ext_params_config(struct rkisp1_params *params,
> + struct rkisp1_ext_params_cfg *cfg,
> + u32 block_group_mask)
> +{
> + size_t block_offset = 0;
> +
> + if (WARN_ON(!cfg))
> + return;
> +
> + /* 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;
> +
> + block = (const union rkisp1_ext_params_config *)
> + &cfg->data[block_offset];
In validation, you only check that if full headers exist, then headers are
fine. But here you don't perform that check, meaning you may have partial
headers here only. Either check here, too, or check that there's no more
data after the last block during validation.
> + block_offset += block->header.size;
> +
> + /* Make sure the block is in the list of groups to configure. */
> + block_handler = &rkisp1_ext_params_handlers[block->header.type];
> + if (!(block_handler->group & block_group_mask))
> + continue;
> +
> + block_handler->handler(params, block);
> +
> + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
> + params->enabled_blocks &= ~BIT(block->header.type);
> + else
> + params->enabled_blocks |= BIT(block->header.type);
> + }
> +}
> +
> static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> struct rkisp1_params_buffer *buf,
> unsigned int frame_sequence)
> @@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + } else {
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> + }
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> + } else {
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
> + }
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
> if (!cur_buf)
> goto unlock;
>
> - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
> + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> + else
> + rkisp1_ext_params_config(params, cur_buf->cfg,
> + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
>
> /* update shadow register immediately */
> rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> @@ -1862,25 +2346,114 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> spin_unlock_irq(¶ms->config_lock);
> }
>
> -static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> + struct vb2_buffer *vb)
> {
> struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> - struct rkisp1_params_cfg *cfg =
> - vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
> + 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;
>
> - if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
> + /*
> + * 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) {
> + dev_dbg(params->rkisp1->dev,
> + "Too large buffer payload size %lu\n", payload_size);
> return -EINVAL;
> + }
> +
> + if (payload_size < header_size) {
> + dev_dbg(params->rkisp1->dev,
> + "Buffer payload %lu smaller than header size %lu\n",
> + payload_size, header_size);
> + return -EINVAL;
> + }
>
> /*
> - * Copy the parameters buffer to the internal scratch buffer to avoid
> - * userspace modifying the buffer content while the driver processes it.
> + * Copy the parameters buffer to the internal scratch buffer to
> + * avoid userspace modifying the buffer content while the driver
> + * processes it.
> */
> - memcpy(params_buf->cfg, cfg, sizeof(*cfg));
> + memcpy(cfg, usr_cfg, payload_size);
> +
> + /* 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 %lu larger than buffer payload size %lu\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;
> + }
> +
> + 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;
> + }
>
> return 0;
> }
>
> +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> +{
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> + struct rkisp1_ext_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
> + struct rkisp1_params *params = vb->vb2_queue->drv_priv;
> + size_t payload = vb2_get_plane_payload(vb, 0);
> +
> + /* Only validate the plane payload size for fixed parameters format. */
> + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> + if (payload != sizeof(struct rkisp1_params_cfg))
> + return -EINVAL;
> +
> + /*
> + * Copy the parameters buffer to the internal scratch buffer to
> + * avoid userspace modifying the buffer content while the driver
> + * processes it.
> + */
> + memcpy(params_buf->cfg, cfg, payload);
> +
> + return 0;
> + }
> +
> + return rkisp1_params_prepare_ext_params(params, vb);
> +}
> +
> static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
> {
> struct rkisp1_params *params = vq->drv_priv;
> @@ -1898,6 +2471,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
>
> list_for_each_entry(buf, &tmp_list, queue)
> vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> +
> + params->enabled_blocks = 0;
> }
>
> static const struct vb2_ops rkisp1_params_vb2_ops = {
> @@ -1909,7 +2484,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
> .buf_queue = rkisp1_params_vb2_buf_queue,
> .buf_prepare = rkisp1_params_vb2_buf_prepare,
> .stop_streaming = rkisp1_params_vb2_stop_streaming,
> -
> };
>
> static const struct v4l2_file_operations rkisp1_params_fops = {
--
Kind regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v5 6/7] media: rkisp1: Implement extensible params support
2024-07-06 12:18 ` [PATCH v5 " Sakari Ailus
@ 2024-07-08 8:25 ` Jacopo Mondi
2024-07-08 9:41 ` Sakari Ailus
0 siblings, 1 reply; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-08 8:25 UTC (permalink / raw)
To: Sakari Ailus
Cc: Jacopo Mondi, Linux Media Mailing List, Laurent Pinchart,
Hans Verkuil, Stefan Klug, Paul Elder, Daniel Scally,
Kieran Bingham, Umang Jain, Dafna Hirschfeld,
Mauro Carvalho Chehab, Heiko Stuebner
Hi Sakari,
thanks for review
On Sat, Jul 06, 2024 at 12:18:22PM GMT, Sakari Ailus wrote:
> Hi Jacopo,
>
> On Wed, Jul 03, 2024 at 06:10:45PM +0200, Jacopo Mondi wrote:
> > Implement support in rkisp1-params for the extensible configuration
> > parameters format.
> >
> > Create a list of handlers for each ISP block that wraps the existing
> > configuration functions and handles the ISP block enablement.
> >
> > Parse the configuration parameters buffer in rkisp1_ext_params_config
> > and filter the enable blocks by group, to allow setting the 'other'
> > groups separately from the 'lsc' group to support the pre/post-configure
> > operations.
> >
> > Implement parameter buffer validation for the extensible format at
> > .buf_prepare() time.
> >
> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > ---
> > .../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
> > .../platform/rockchip/rkisp1/rkisp1-params.c | 602 +++++++++++++++++-
> > 2 files changed, 591 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > index 43cc727a628d..2f4bf7e97927 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > @@ -396,6 +396,7 @@ struct rkisp1_params_ops {
> > * @quantization: the quantization configured on the isp's src pad
> > * @ycbcr_encoding the YCbCr encoding
> > * @raw_type: the bayer pattern on the isp video sink pad
> > + * @enabled_blocks: bitmask of enabled ISP blocks
> > */
> > struct rkisp1_params {
> > struct rkisp1_vdev_node vnode;
> > @@ -410,6 +411,8 @@ struct rkisp1_params {
> > enum v4l2_quantization quantization;
> > enum v4l2_ycbcr_encoding ycbcr_encoding;
> > enum rkisp1_fmt_raw_pat_type raw_type;
> > +
> > + u32 enabled_blocks;
> > };
> >
> > /*
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > index 45c4b1bcee63..3ef410337aa2 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > @@ -35,6 +35,30 @@
> > #define RKISP1_ISP_CC_COEFF(n) \
> > (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
> >
> > +#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;
> > +};
> > +
> > enum rkisp1_params_formats {
> > RKISP1_PARAMS_FIXED,
> > RKISP1_PARAMS_EXTENSIBLE,
> > @@ -1519,6 +1543,451 @@ 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)
> > +{
> > + const struct rkisp1_ext_params_bls_config *bls = &block->bls;
> > +
> > + if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> > + RKISP1_CIF_ISP_BLS_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_bls_config(params, &bls->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> > + RKISP1_CIF_ISP_BLS_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
> > +
> > + if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> > + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> > + return;
> > + }
> > +
> > + rkisp1_dpcc_config(params, &dpcc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> > + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_sdg(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_sdg_config(params, &sdg->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> > + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_lsc_config(params, &lsc->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> > + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_awbg(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> > + return;
> > + }
> > +
> > + params->ops->awb_gain_config(params, &awbg->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_flt(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_flt_config *flt = &block->flt;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> > + RKISP1_CIF_ISP_FLT_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_flt_config(params, &flt->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> > + RKISP1_CIF_ISP_FLT_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_bdm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> > + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> > + return;
> > + }
> > +
> > + rkisp1_bdm_config(params, &bdm->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> > + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_ctk(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_ctk_enable(params, false);
> > + return;
> > + }
> > +
> > + rkisp1_ctk_config(params, &ctk->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
> > + rkisp1_ctk_enable(params, true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_goc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_goc_config *goc = &block->goc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> > + return;
> > + }
> > +
> > + params->ops->goc_config(params, &goc->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> > + RKISP1_CIF_ISP_DPF_MODE_EN);
> > + return;
> > + }
> > +
> > + rkisp1_dpf_config(params, &dpf->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> > + RKISP1_CIF_ISP_DPF_MODE_EN);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_dpfs(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
> > +
> > + rkisp1_dpf_strength_config(params, &dpfs->config);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_cproc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
> > + RKISP1_CIF_C_PROC_CTR_ENABLE);
> > + return;
> > + }
> > +
> > + rkisp1_cproc_config(params, &cproc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
> > + RKISP1_CIF_C_PROC_CTR_ENABLE);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_ie(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_ie_config *ie = &block->ie;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_ie_enable(params, false);
> > + return;
> > + }
> > +
> > + rkisp1_ie_config(params, &ie->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
> > + rkisp1_ie_enable(params, true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_awbm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + params->ops->awb_meas_enable(params, &awbm->config,
> > + false);
> > + return;
> > + }
> > +
> > + params->ops->awb_meas_config(params, &awbm->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
> > + params->ops->awb_meas_enable(params, &awbm->config,
> > + true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_hstm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_hst_config *hst = &block->hst;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + params->ops->hst_enable(params, &hst->config, false);
> > + return;
> > + }
> > +
> > + params->ops->hst_config(params, &hst->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_aec_config *aec = &block->aec;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> > + RKISP1_CIF_ISP_EXP_ENA);
> > + return;
> > + }
> > +
> > + params->ops->aec_config(params, &aec->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> > + RKISP1_CIF_ISP_EXP_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_afcm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_afc_config *afc = &block->afc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> > + RKISP1_CIF_ISP_AFM_ENA);
> > + return;
> > + }
> > +
> > + params->ops->afm_config(params, &afc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> > + RKISP1_CIF_ISP_AFM_ENA);
> > +}
> > +
> > +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;
> > + unsigned int group;
> > +} rkisp1_ext_params_handlers[] = {
> > + [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,
> > + },
> > + [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,
> > + },
> > +};
> > +
> > +static void rkisp1_ext_params_config(struct rkisp1_params *params,
> > + struct rkisp1_ext_params_cfg *cfg,
> > + u32 block_group_mask)
> > +{
> > + size_t block_offset = 0;
> > +
> > + if (WARN_ON(!cfg))
> > + return;
> > +
> > + /* 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;
> > +
> > + block = (const union rkisp1_ext_params_config *)
> > + &cfg->data[block_offset];
>
> In validation, you only check that if full headers exist, then headers are
> fine. But here you don't perform that check, meaning you may have partial
> headers here only. Either check here, too, or check that there's no more
> data after the last block during validation.
My preference would be for checking during validation that there is
no data after the last valid header.
I think:
@@ -2438,6 +2438,12 @@ static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
cfg_size -= block->size;
}
+ if (cfg_size) {
+ dev_dbg(params->rkisp1->dev,
+ "Unexpected data after the parameters buffer end\n");
+ return -EINVAL;
+ }
+
return 0;
}
would do ?
Thanks
j
>
> > + block_offset += block->header.size;
> > +
> > + /* Make sure the block is in the list of groups to configure. */
> > + block_handler = &rkisp1_ext_params_handlers[block->header.type];
> > + if (!(block_handler->group & block_group_mask))
> > + continue;
> > +
> > + block_handler->handler(params, block);
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
> > + params->enabled_blocks &= ~BIT(block->header.type);
> > + else
> > + params->enabled_blocks |= BIT(block->header.type);
> > + }
> > +}
> > +
> > static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> > struct rkisp1_params_buffer *buf,
> > unsigned int frame_sequence)
> > @@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> > + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + } else {
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> > + }
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> > + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + } else {
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
> > + }
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
> > + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + else
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1862,25 +2346,114 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> > spin_unlock_irq(¶ms->config_lock);
> > }
> >
> > -static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> > +static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> > + struct vb2_buffer *vb)
> > {
> > struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> > struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> > - struct rkisp1_params_cfg *cfg =
> > - vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
> > + 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;
> >
> > - if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
> > + /*
> > + * 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) {
> > + dev_dbg(params->rkisp1->dev,
> > + "Too large buffer payload size %lu\n", payload_size);
> > return -EINVAL;
> > + }
> > +
> > + if (payload_size < header_size) {
> > + dev_dbg(params->rkisp1->dev,
> > + "Buffer payload %lu smaller than header size %lu\n",
> > + payload_size, header_size);
> > + return -EINVAL;
> > + }
> >
> > /*
> > - * Copy the parameters buffer to the internal scratch buffer to avoid
> > - * userspace modifying the buffer content while the driver processes it.
> > + * Copy the parameters buffer to the internal scratch buffer to
> > + * avoid userspace modifying the buffer content while the driver
> > + * processes it.
> > */
> > - memcpy(params_buf->cfg, cfg, sizeof(*cfg));
> > + memcpy(cfg, usr_cfg, payload_size);
> > +
> > + /* 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 %lu larger than buffer payload size %lu\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;
> > + }
> > +
> > + 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;
> > + }
> >
> > return 0;
> > }
> >
> > +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> > +{
> > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> > + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> > + struct rkisp1_ext_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
> > + struct rkisp1_params *params = vb->vb2_queue->drv_priv;
> > + size_t payload = vb2_get_plane_payload(vb, 0);
> > +
> > + /* Only validate the plane payload size for fixed parameters format. */
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> > + if (payload != sizeof(struct rkisp1_params_cfg))
> > + return -EINVAL;
> > +
> > + /*
> > + * Copy the parameters buffer to the internal scratch buffer to
> > + * avoid userspace modifying the buffer content while the driver
> > + * processes it.
> > + */
> > + memcpy(params_buf->cfg, cfg, payload);
> > +
> > + return 0;
> > + }
> > +
> > + return rkisp1_params_prepare_ext_params(params, vb);
> > +}
> > +
> > static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
> > {
> > struct rkisp1_params *params = vq->drv_priv;
> > @@ -1898,6 +2471,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
> >
> > list_for_each_entry(buf, &tmp_list, queue)
> > vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> > +
> > + params->enabled_blocks = 0;
> > }
> >
> > static const struct vb2_ops rkisp1_params_vb2_ops = {
> > @@ -1909,7 +2484,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
> > .buf_queue = rkisp1_params_vb2_buf_queue,
> > .buf_prepare = rkisp1_params_vb2_buf_prepare,
> > .stop_streaming = rkisp1_params_vb2_stop_streaming,
> > -
> > };
> >
> > static const struct v4l2_file_operations rkisp1_params_fops = {
>
> --
> Kind regards,
>
> Sakari Ailus
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v5.2 6/7] media: rkisp1: Implement extensible params support
2024-07-05 11:21 ` Paul Elder
@ 2024-07-08 8:39 ` Jacopo Mondi
0 siblings, 0 replies; 21+ messages in thread
From: Jacopo Mondi @ 2024-07-08 8:39 UTC (permalink / raw)
To: Paul Elder
Cc: Laurent Pinchart, linux-media, Jacopo Mondi, Sakari Ailus,
Hans Verkuil, Stefan Klug, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
Hi Paul
On Fri, Jul 05, 2024 at 08:21:28PM GMT, Paul Elder wrote:
> On Thu, Jul 04, 2024 at 12:56:11PM +0300, Laurent Pinchart wrote:
> > From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >
> > Implement support in rkisp1-params for the extensible configuration
> > parameters format.
> >
> > Create a list of handlers for each ISP block that wraps the existing
> > configuration functions and handles the ISP block enablement.
> >
> > Parse the configuration parameters buffer in rkisp1_ext_params_config
> > and filter the enable blocks by group, to allow setting the 'other'
> > groups separately from the 'lsc' group to support the pre/post-configure
> > operations.
> >
> > Implement parameter buffer validation for the extensible format at
> > .buf_prepare() time.
> >
> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > ---
> > Changes since v5.1:
> >
> > - Fix incorrect debug message
> > - Avoid rewrapping comments unnecessarily
> >
> > Changes since v5:
> >
> > - Use correct struct type for cfg in rkisp1_params_vb2_buf_prepare()
> > - Replace sizeof(type) with sizeof(var)
> > - Refactor rkisp1_params_vb2_buf_prepare() to reduce indentation
> > ---
> > .../platform/rockchip/rkisp1/rkisp1-common.h | 3 +
> > .../platform/rockchip/rkisp1/rkisp1-params.c | 598 +++++++++++++++++-
> > 2 files changed, 589 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > index b4369bbccea3..c1689c0fa05a 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> > @@ -401,6 +401,7 @@ struct rkisp1_params_ops {
> > * @quantization: the quantization configured on the isp's src pad
> > * @ycbcr_encoding the YCbCr encoding
> > * @raw_type: the bayer pattern on the isp video sink pad
> > + * @enabled_blocks: bitmask of enabled ISP blocks
> > */
> > struct rkisp1_params {
> > struct rkisp1_vdev_node vnode;
> > @@ -415,6 +416,8 @@ struct rkisp1_params {
> > enum v4l2_quantization quantization;
> > enum v4l2_ycbcr_encoding ycbcr_encoding;
> > enum rkisp1_fmt_raw_pat_type raw_type;
> > +
> > + u32 enabled_blocks;
> > };
> >
> > /*
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > index 45c4b1bcee63..c216aec4252f 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > @@ -35,6 +35,30 @@
> > #define RKISP1_ISP_CC_COEFF(n) \
> > (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4)
> >
> > +#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;
> > +};
> > +
>
> I was wondering if this would cause uapi breakages if a bigger one was
> added in the future but I see that based on how this is used it should
> be fine.
>
Please note this is in the driver .c file and not part of the uAPI
> > enum rkisp1_params_formats {
> > RKISP1_PARAMS_FIXED,
> > RKISP1_PARAMS_EXTENSIBLE,
> > @@ -1519,6 +1543,451 @@ 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)
> > +{
> > + const struct rkisp1_ext_params_bls_config *bls = &block->bls;
> > +
> > + if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> > + RKISP1_CIF_ISP_BLS_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_bls_config(params, &bls->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_BLS_CTRL,
> > + RKISP1_CIF_ISP_BLS_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_dpcc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_dpcc_config *dpcc = &block->dpcc;
> > +
> > + if (dpcc->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> > + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> > + return;
> > + }
> > +
> > + rkisp1_dpcc_config(params, &dpcc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPCC_MODE,
> > + RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_sdg(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_sdg_config *sdg = &block->sdg;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_sdg_config(params, &sdg->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_lsc_config *lsc = &block->lsc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> > + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_lsc_config(params, &lsc->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL,
> > + RKISP1_CIF_ISP_LSC_CTRL_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_awbg(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_awb_gain_config *awbg = &block->awbg;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> > + return;
> > + }
> > +
> > + params->ops->awb_gain_config(params, &awbg->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAIN)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_flt(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_flt_config *flt = &block->flt;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> > + RKISP1_CIF_ISP_FLT_ENA);
> > + return;
> > + }
> > +
> > + rkisp1_flt_config(params, &flt->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_FILT_MODE,
> > + RKISP1_CIF_ISP_FLT_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_bdm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_bdm_config *bdm = &block->bdm;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> > + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> > + return;
> > + }
> > +
> > + rkisp1_bdm_config(params, &bdm->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_BDM)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DEMOSAIC,
> > + RKISP1_CIF_ISP_DEMOSAIC_BYPASS);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_ctk(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_ctk_config *ctk = &block->ctk;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_ctk_enable(params, false);
> > + return;
> > + }
> > +
> > + rkisp1_ctk_config(params, &ctk->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CTK)))
> > + rkisp1_ctk_enable(params, true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_goc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_goc_config *goc = &block->goc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL,
> > + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA);
> > + return;
> > + }
> > +
> > + params->ops->goc_config(params, &goc->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_GOC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_dpf_config *dpf = &block->dpf;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> > + RKISP1_CIF_ISP_DPF_MODE_EN);
> > + return;
> > + }
> > +
> > + rkisp1_dpf_config(params, &dpf->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE,
> > + RKISP1_CIF_ISP_DPF_MODE_EN);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_dpfs(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_dpf_strength_config *dpfs = &block->dpfs;
> > +
> > + rkisp1_dpf_strength_config(params, &dpfs->config);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_cproc(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_cproc_config *cproc = &block->cproc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL,
> > + RKISP1_CIF_C_PROC_CTR_ENABLE);
> > + return;
> > + }
> > +
> > + rkisp1_cproc_config(params, &cproc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL,
> > + RKISP1_CIF_C_PROC_CTR_ENABLE);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_ie(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_ie_config *ie = &block->ie;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_ie_enable(params, false);
> > + return;
> > + }
> > +
> > + rkisp1_ie_config(params, &ie->config);
> > +
> > + if (!(params->enabled_blocks & BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_IE)))
> > + rkisp1_ie_enable(params, true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_awbm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_awb_meas_config *awbm = &block->awbm;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + params->ops->awb_meas_enable(params, &awbm->config,
> > + false);
> > + return;
> > + }
> > +
> > + params->ops->awb_meas_config(params, &awbm->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS)))
> > + params->ops->awb_meas_enable(params, &awbm->config,
> > + true);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_hstm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_hst_config *hst = &block->hst;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + params->ops->hst_enable(params, &hst->config, false);
> > + return;
> > + }
> > +
> > + params->ops->hst_config(params, &hst->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS)))
> > + 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)
> > +{
> > + const struct rkisp1_ext_params_aec_config *aec = &block->aec;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> > + RKISP1_CIF_ISP_EXP_ENA);
> > + return;
> > + }
> > +
> > + params->ops->aec_config(params, &aec->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL,
> > + RKISP1_CIF_ISP_EXP_ENA);
> > +}
> > +
> > +static void
> > +rkisp1_ext_params_afcm(struct rkisp1_params *params,
> > + const union rkisp1_ext_params_config *block)
> > +{
> > + const struct rkisp1_ext_params_afc_config *afc = &block->afc;
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> > + RKISP1_CIF_ISP_AFM_ENA);
> > + return;
> > + }
> > +
> > + params->ops->afm_config(params, &afc->config);
> > +
> > + if (!(params->enabled_blocks &
> > + BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS)))
> > + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL,
> > + RKISP1_CIF_ISP_AFM_ENA);
> > +}
> > +
> > +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;
> > + unsigned int group;
> > +} rkisp1_ext_params_handlers[] = {
> > + [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,
> > + },
> > + [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,
> > + },
> > +};
> > +
> > +static void rkisp1_ext_params_config(struct rkisp1_params *params,
> > + struct rkisp1_ext_params_cfg *cfg,
> > + u32 block_group_mask)
> > +{
> > + size_t block_offset = 0;
> > +
> > + if (WARN_ON(!cfg))
> > + return;
> > +
> > + /* 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;
> > +
> > + block = (const union rkisp1_ext_params_config *)
> > + &cfg->data[block_offset];
> > + block_offset += block->header.size;
> > +
> > + /* Make sure the block is in the list of groups to configure. */
> > + block_handler = &rkisp1_ext_params_handlers[block->header.type];
>
> Doesn't block->header.type come from userspace...? What if it's past the
> array size...?
>
> Oh it's validated below in rkisp1_params_prepare_ext_params ok.
>
>
> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
>
Thanks
j
> > + if (!(block_handler->group & block_group_mask))
> > + continue;
> > +
> > + block_handler->handler(params, block);
> > +
> > + if (block->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE)
> > + params->enabled_blocks &= ~BIT(block->header.type);
> > + else
> > + params->enabled_blocks |= BIT(block->header.type);
> > + }
> > +}
> > +
> > static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
> > struct rkisp1_params_buffer *buf,
> > unsigned int frame_sequence)
> > @@ -1541,9 +2010,15 @@ void rkisp1_params_isr(struct rkisp1_device *rkisp1)
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> > + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + } else {
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> > + }
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1643,8 +2118,13 @@ void rkisp1_params_pre_configure(struct rkisp1_params *params,
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > - rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
> > + rkisp1_isp_isr_other_config(params, cur_buf->cfg);
> > + rkisp1_isp_isr_meas_config(params, cur_buf->cfg);
> > + } else {
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS);
> > + }
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1673,7 +2153,11 @@ void rkisp1_params_post_configure(struct rkisp1_params *params)
> > if (!cur_buf)
> > goto unlock;
> >
> > - rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS)
> > + rkisp1_isp_isr_lsc_config(params, cur_buf->cfg);
> > + else
> > + rkisp1_ext_params_config(params, cur_buf->cfg,
> > + RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
> >
> > /* update shadow register immediately */
> > rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL,
> > @@ -1862,21 +2346,110 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
> > spin_unlock_irq(¶ms->config_lock);
> > }
> >
> > -static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> > +static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> > + struct vb2_buffer *vb)
> > {
> > struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> > struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> > - struct rkisp1_params_cfg *cfg =
> > - vb2_plane_vaddr(¶ms_buf->vb.vb2_buf, 0);
> > + 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;
> >
> > - if (vb2_get_plane_payload(vb, 0) != sizeof(*cfg))
> > + /*
> > + * 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) {
> > + dev_dbg(params->rkisp1->dev,
> > + "Too large buffer payload size %lu\n", payload_size);
> > + return -EINVAL;
> > + }
> > +
> > + if (payload_size < header_size) {
> > + dev_dbg(params->rkisp1->dev,
> > + "Buffer payload %lu smaller than header size %lu\n",
> > + payload_size, header_size);
> > + return -EINVAL;
> > + }
> > +
> > + /*
> > + * Copy the parameters buffer to the internal scratch buffer to avoid
> > + * userspace modifying the buffer content while the driver processes it.
> > + */
> > + memcpy(cfg, usr_cfg, payload_size);
> > +
> > + /* 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 %lu different than buffer payload size %lu\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;
> > + }
> > +
> > + 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;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
> > +{
> > + struct rkisp1_params *params = vb->vb2_queue->drv_priv;
> > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> > + struct rkisp1_params_buffer *params_buf = to_rkisp1_params_buffer(vbuf);
> > + struct rkisp1_params_cfg *cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
> > + size_t payload = vb2_get_plane_payload(vb, 0);
> > +
> > + if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS)
> > + return rkisp1_params_prepare_ext_params(params, vb);
> > +
> > + /*
> > + * For the fixed parameters format the payload size must be exactly the
> > + * size of the parameters structure.
> > + */
> > + if (payload != sizeof(*cfg))
> > return -EINVAL;
> >
> > /*
> > * Copy the parameters buffer to the internal scratch buffer to avoid
> > * userspace modifying the buffer content while the driver processes it.
> > */
> > - memcpy(params_buf->cfg, cfg, sizeof(*cfg));
> > + memcpy(params_buf->cfg, cfg, payload);
> >
> > return 0;
> > }
> > @@ -1898,6 +2471,8 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
> >
> > list_for_each_entry(buf, &tmp_list, queue)
> > vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> > +
> > + params->enabled_blocks = 0;
> > }
> >
> > static const struct vb2_ops rkisp1_params_vb2_ops = {
> > @@ -1909,7 +2484,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
> > .buf_queue = rkisp1_params_vb2_buf_queue,
> > .buf_prepare = rkisp1_params_vb2_buf_prepare,
> > .stop_streaming = rkisp1_params_vb2_stop_streaming,
> > -
> > };
> >
> > static const struct v4l2_file_operations rkisp1_params_fops = {
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v5 6/7] media: rkisp1: Implement extensible params support
2024-07-08 8:25 ` Jacopo Mondi
@ 2024-07-08 9:41 ` Sakari Ailus
0 siblings, 0 replies; 21+ messages in thread
From: Sakari Ailus @ 2024-07-08 9:41 UTC (permalink / raw)
To: Jacopo Mondi
Cc: Linux Media Mailing List, Laurent Pinchart, Hans Verkuil,
Stefan Klug, Paul Elder, Daniel Scally, Kieran Bingham,
Umang Jain, Dafna Hirschfeld, Mauro Carvalho Chehab,
Heiko Stuebner
Hi Jacopo,
On Mon, Jul 08, 2024 at 10:25:34AM +0200, Jacopo Mondi wrote:
> > > +static void rkisp1_ext_params_config(struct rkisp1_params *params,
> > > + struct rkisp1_ext_params_cfg *cfg,
> > > + u32 block_group_mask)
> > > +{
> > > + size_t block_offset = 0;
> > > +
> > > + if (WARN_ON(!cfg))
> > > + return;
> > > +
> > > + /* 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;
> > > +
> > > + block = (const union rkisp1_ext_params_config *)
> > > + &cfg->data[block_offset];
> >
> > In validation, you only check that if full headers exist, then headers are
> > fine. But here you don't perform that check, meaning you may have partial
> > headers here only. Either check here, too, or check that there's no more
> > data after the last block during validation.
>
> My preference would be for checking during validation that there is
> no data after the last valid header.
>
> I think:
>
> @@ -2438,6 +2438,12 @@ static int rkisp1_params_prepare_ext_params(struct rkisp1_params *params,
> cfg_size -= block->size;
> }
>
> + if (cfg_size) {
> + dev_dbg(params->rkisp1->dev,
> + "Unexpected data after the parameters buffer end\n");
> + return -EINVAL;
> + }
> +
> return 0;
> }
>
> would do ?
I believe it would. I also think it's better to address this during the
validation.
--
Kind regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2024-07-08 9:42 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-03 16:10 [PATCH v5 0/7] media: rkisp1: Implement support for extensible parameters Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 1/7] uapi: rkisp1-config: Add extensible parameters format Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 2/7] uapi: videodev2: Add V4L2_META_FMT_RK_ISP1_EXT_PARAMS Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 3/7] media: rkisp1: Add struct rkisp1_params_buffer Jacopo Mondi
2024-07-03 16:10 ` [PATCH v5 4/7] media: rkisp1: Copy the parameters buffer Jacopo Mondi
2024-07-05 10:52 ` Paul Elder
2024-07-03 16:10 ` [PATCH v5 5/7] media: rkisp1: Cache the currently active format Jacopo Mondi
2024-07-05 10:56 ` Paul Elder
2024-07-03 16:10 ` [PATCH v5 6/7] media: rkisp1: Implement extensible params support Jacopo Mondi
2024-07-03 20:56 ` Laurent Pinchart
2024-07-03 21:17 ` [PATCH v5.1 " Laurent Pinchart
2024-07-04 7:36 ` Jacopo Mondi
2024-07-04 9:40 ` Laurent Pinchart
2024-07-04 9:56 ` [PATCH v5.2 " Laurent Pinchart
2024-07-05 11:21 ` Paul Elder
2024-07-08 8:39 ` Jacopo Mondi
2024-07-06 12:18 ` [PATCH v5 " Sakari Ailus
2024-07-08 8:25 ` Jacopo Mondi
2024-07-08 9:41 ` Sakari Ailus
2024-07-03 16:10 ` [PATCH v5 7/7] media: rkisp1: Implement s_fmt/try_fmt Jacopo Mondi
2024-07-05 11:23 ` Paul Elder
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.