mbox series

[v2,0/5] media: rkisp1: Add support for the companding block

Message ID 20240704154932.6686-1-laurent.pinchart@ideasonboard.com
Headers show
Series media: rkisp1: Add support for the companding block | expand

Message

Laurent Pinchart July 4, 2024, 3:49 p.m. UTC
Hello,

This patch series extends the rkisp1 driver to add support for the ISP's
companding block.

The companding block is an ISP processing block located at the front of
the processing pipeline that performs data expansion, black level
subtraction and data compression. It is found in the ISP8000Nano on the
i.MX8MP, and not present in Rockchip versions of the ISP, that implement
BLS in a dedicated block (not present in the ISP8000Nano) already
supported by the driver.

The first two patches start with preparatory work. Patch 1/5 refactors
existing duplicate code to share a common function, that will also be
used later in this series. Patch 2/5 then improves the ISP parameters
extensible format handler by making it possible to condition support for
particular ISP blocks based on device features.

Support for the companding block follows in the next three patches.
Patch 3/5 adds macros for the companding block registers, and patch 4/5
adds feature flags to differentiate between the dedicated BLS block and
the companding block. Finally, patch 5/5 adds support for the companding
block in the ISP parameters.

The series is based on Jacopo's support for extensible parameters in the
rkisp1 driver ("[PATCH v5 0/7] media: rkisp1: Implement support for
extensible parameters", see [1]). Thanks to that work, adding support
for a new ISP block in a backward compatible way is easy. I have pushed
a branch to [2] that includes all the dependencies, on top of the media
stage master branch.

[1] https://lore.kernel.org/r/20240703161048.247124-1-jacopo.mondi@ideasonboard.com
[2] https://git.kernel.org/pub/scm/linux/kernel/git/pinchartl/linux.git/log/?h=next/media/rkisp1

Laurent Pinchart (2):
  media: rkisp1: Add helper function to swap colour channels
  media: rkisp1: Add features mask to extensible block handlers

Paul Elder (3):
  media: rkisp1: Add register definitions for the companding block
  media: rkisp1: Add feature flags for BLS and compand
  media: rkisp1: Add support for the companding block

 .../platform/rockchip/rkisp1/rkisp1-common.c  |  14 +
 .../platform/rockchip/rkisp1/rkisp1-common.h  |   7 +
 .../platform/rockchip/rkisp1/rkisp1-dev.c     |   9 +-
 .../platform/rockchip/rkisp1/rkisp1-params.c  | 243 ++++++++++++++----
 .../platform/rockchip/rkisp1/rkisp1-regs.h    |  23 ++
 .../platform/rockchip/rkisp1/rkisp1-stats.c   |  51 +---
 include/uapi/linux/rkisp1-config.h            |  89 ++++++-
 7 files changed, 348 insertions(+), 88 deletions(-)


base-commit: 06d29a973fc1d19dc5d3337565b83e83344c14ea

Comments

Jacopo Mondi July 4, 2024, 8:03 p.m. UTC | #1
Hi Laurent

On Thu, Jul 04, 2024 at 06:49:32PM GMT, Laurent Pinchart wrote:
> From: Paul Elder <paul.elder@ideasonboard.com>
>
> Add support to the rkisp1 driver for the companding block that exists on
> the i.MX8MP version of the ISP. This requires usage of the new
> extensible parameters format, and showcases how the format allows for
> extensions without breaking backward compatibility.
>
> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

Thanks
   j

> ---
> Changes since v1:
>
> - Refactor rkisp1_compand_write_px_curve()
> - Use unsigned int instead of size_t for loop indices
> - Hardcode RKISP1_CIF_ISP_COMPAND_NUM_POINTS points
> - Rename RKISP1_CIF_ISP_COMPAND_MAX_SAMPLES to
>   RKISP1_CIF_ISP_COMPAND_NUM_POINTS
> - Add comment to explain why rkisp1_ext_params_compand_curve_config is
>   counted twice in RKISP1_EXT_PARAMS_MAX_SIZE
> - Fix typo
>
> Changes since v0:
>
> - Drop RKISP1_EXT_PARAM_BUFFER_V2
> - Use common structure for compression and expansion curves
> - Rename config fields in rkisp1_ext_params_*_config to just config
> - Mention block type in structures documentation
> - Constify arguments
> - Replace __uxx types with uxx
> - Use rkisp1_bls_swap_regs() helper in rkisp1_compand_bls_config()
> - Use generic feature handling mechanism
> ---
>  .../platform/rockchip/rkisp1/rkisp1-params.c  | 168 ++++++++++++++++++
>  include/uapi/linux/rkisp1-config.h            |  89 +++++++++-
>  2 files changed, 256 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 20bc6d582527..430d36aedd76 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -5,6 +5,7 @@
>   * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>   */
>
> +#include <linux/math.h>
>  #include <linux/string.h>
>
>  #include <media/v4l2-common.h>
> @@ -57,6 +58,8 @@ union rkisp1_ext_params_config {
>  	struct rkisp1_ext_params_hst_config hst;
>  	struct rkisp1_ext_params_aec_config aec;
>  	struct rkisp1_ext_params_afc_config afc;
> +	struct rkisp1_ext_params_compand_bls_config compand_bls;
> +	struct rkisp1_ext_params_compand_curve_config compand_curve;
>  };
>
>  enum rkisp1_params_formats {
> @@ -1258,6 +1261,93 @@ rkisp1_dpf_strength_config(struct rkisp1_params *params,
>  	rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_R, arg->r);
>  }
>
> +static void rkisp1_compand_write_px_curve(struct rkisp1_params *params,
> +					  unsigned int addr, const u8 *curve)
> +{
> +	const unsigned int points_per_reg = 6;
> +	const unsigned int num_regs =
> +		DIV_ROUND_UP(RKISP1_CIF_ISP_COMPAND_NUM_POINTS,
> +			     points_per_reg);
> +
> +	/*
> +	 * The compand curve is specified as a piecewise linear function with
> +	 * 64 points. X coordinates are stored as a log2 of the displacement
> +	 * from the previous point, in 5 bits, with 6 values per register. The
> +	 * last register stores 4 values.
> +	 */
> +	for (unsigned int reg = 0; reg < num_regs; ++reg) {
> +		unsigned int num_points =
> +			min(RKISP1_CIF_ISP_COMPAND_NUM_POINTS -
> +			    reg * points_per_reg, points_per_reg);
> +		u32 val = 0;
> +
> +		for (unsigned int i = 0; i < num_points; i++)
> +			val |= (*curve++ & 0x1f) << (i * 5);
> +
> +		rkisp1_write(params->rkisp1, addr, val);
> +		addr += 4;
> +	}
> +}
> +
> +static void
> +rkisp1_compand_write_curve_mem(struct rkisp1_params *params,
> +			       unsigned int reg_addr, unsigned int reg_data,
> +			       const u32 curve[RKISP1_CIF_ISP_COMPAND_NUM_POINTS])
> +{
> +	for (unsigned int i = 0; i < RKISP1_CIF_ISP_COMPAND_NUM_POINTS; i++) {
> +		rkisp1_write(params->rkisp1, reg_addr, i);
> +		rkisp1_write(params->rkisp1, reg_data, curve[i]);
> +	}
> +}
> +
> +static void
> +rkisp1_compand_bls_config(struct rkisp1_params *params,
> +			  const struct rkisp1_cif_isp_compand_bls_config *arg)
> +{
> +	static const u32 regs[] = {
> +		RKISP1_CIF_ISP_COMPAND_BLS_A_FIXED,
> +		RKISP1_CIF_ISP_COMPAND_BLS_B_FIXED,
> +		RKISP1_CIF_ISP_COMPAND_BLS_C_FIXED,
> +		RKISP1_CIF_ISP_COMPAND_BLS_D_FIXED,
> +	};
> +	u32 swapped[4];
> +
> +	rkisp1_bls_swap_regs(params->raw_type, regs, swapped);
> +
> +	rkisp1_write(params->rkisp1, swapped[0], arg->r);
> +	rkisp1_write(params->rkisp1, swapped[1], arg->gr);
> +	rkisp1_write(params->rkisp1, swapped[2], arg->gb);
> +	rkisp1_write(params->rkisp1, swapped[3], arg->b);
> +}
> +
> +static void
> +rkisp1_compand_expand_config(struct rkisp1_params *params,
> +			     const struct rkisp1_cif_isp_compand_curve_config *arg)
> +{
> +	rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_EXPAND_PX_N(0),
> +				      arg->px);
> +	rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_Y_ADDR,
> +				       RKISP1_CIF_ISP_COMPAND_EXPAND_Y_WRITE_DATA,
> +				       arg->y);
> +	rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_X_ADDR,
> +				       RKISP1_CIF_ISP_COMPAND_EXPAND_X_WRITE_DATA,
> +				       arg->x);
> +}
> +
> +static void
> +rkisp1_compand_compress_config(struct rkisp1_params *params,
> +			       const struct rkisp1_cif_isp_compand_curve_config *arg)
> +{
> +	rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_PX_N(0),
> +				      arg->px);
> +	rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_ADDR,
> +				       RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_WRITE_DATA,
> +				       arg->y);
> +	rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_X_ADDR,
> +				       RKISP1_CIF_ISP_COMPAND_COMPRESS_X_WRITE_DATA,
> +				       arg->x);
> +}
> +
>  static void
>  rkisp1_isp_isr_other_config(struct rkisp1_params *params,
>  			    const struct rkisp1_params_cfg *new_params)
> @@ -1844,6 +1934,66 @@ rkisp1_ext_params_afcm(struct rkisp1_params *params,
>  				      RKISP1_CIF_ISP_AFM_ENA);
>  }
>
> +static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
> +					  const union rkisp1_ext_params_config *block)
> +{
> +	const struct rkisp1_ext_params_compand_bls_config *bls =
> +		&block->compand_bls;
> +
> +	if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> +		rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +					RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> +		return;
> +	}
> +
> +	rkisp1_compand_bls_config(params, &bls->config);
> +
> +	if (!(params->enabled_blocks &
> +	      BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS)))
> +		rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +				      RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> +}
> +
> +static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
> +					     const union rkisp1_ext_params_config *block)
> +{
> +	const struct rkisp1_ext_params_compand_curve_config *curve =
> +		&block->compand_curve;
> +
> +	if (curve->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> +		rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +					RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> +		return;
> +	}
> +
> +	rkisp1_compand_expand_config(params, &curve->config);
> +
> +	if (!(params->enabled_blocks &
> +	      BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND)))
> +		rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +				      RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> +}
> +
> +static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
> +					       const union rkisp1_ext_params_config *block)
> +{
> +	const struct rkisp1_ext_params_compand_curve_config *curve =
> +		&block->compand_curve;
> +
> +	if (curve->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> +		rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +					RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> +		return;
> +	}
> +
> +	rkisp1_compand_compress_config(params, &curve->config);
> +
> +	if (!(params->enabled_blocks &
> +	      BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS)))
> +		rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +				      RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> +}
> +
>  typedef void (*rkisp1_block_handler)(struct rkisp1_params *params,
>  			     const union rkisp1_ext_params_config *config);
>
> @@ -1939,6 +2089,24 @@ static const struct rkisp1_ext_params_handler {
>  		.handler	= rkisp1_ext_params_afcm,
>  		.group		= RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
>  	},
> +	[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
> +		.size		= sizeof(struct rkisp1_ext_params_compand_bls_config),
> +		.handler	= rkisp1_ext_params_compand_bls,
> +		.group		= RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> +		.features	= RKISP1_FEATURE_COMPAND,
> +	},
> +	[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
> +		.size		= sizeof(struct rkisp1_ext_params_compand_curve_config),
> +		.handler	= rkisp1_ext_params_compand_expand,
> +		.group		= RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> +		.features	= RKISP1_FEATURE_COMPAND,
> +	},
> +	[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
> +		.size		= sizeof(struct rkisp1_ext_params_compand_curve_config),
> +		.handler	= rkisp1_ext_params_compand_compress,
> +		.group		= RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> +		.features	= RKISP1_FEATURE_COMPAND,
> +	},
>  };
>
>  static void rkisp1_ext_params_config(struct rkisp1_params *params,
> diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
> index 00b09c92cca7..c645db36f2f6 100644
> --- a/include/uapi/linux/rkisp1-config.h
> +++ b/include/uapi/linux/rkisp1-config.h
> @@ -164,6 +164,11 @@
>  #define RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS      17
>  #define RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS  6
>
> +/*
> + * Compand
> + */
> +#define RKISP1_CIF_ISP_COMPAND_NUM_POINTS	64
> +
>  /*
>   * Measurement types
>   */
> @@ -851,6 +856,39 @@ struct rkisp1_params_cfg {
>  	struct rkisp1_cif_isp_isp_other_cfg others;
>  };
>
> +/**
> + * struct rkisp1_cif_isp_compand_bls_config - Rockchip ISP1 Companding parameters (BLS)
> + * @r: Fixed subtraction value for Bayer pattern R
> + * @gr: Fixed subtraction value for Bayer pattern Gr
> + * @gb: Fixed subtraction value for Bayer pattern Gb
> + * @b: Fixed subtraction value for Bayer pattern B
> + *
> + * The values will be subtracted from the sensor values. Note that unlike the
> + * dedicated BLS block, the BLS values in the compander are 20-bit unsigned.
> + */
> +struct rkisp1_cif_isp_compand_bls_config {
> +	__u32 r;
> +	__u32 gr;
> +	__u32 gb;
> +	__u32 b;
> +};
> +
> +/**
> + * struct rkisp1_cif_isp_compand_curve_config - Rockchip ISP1 Companding
> + * parameters (expand and compression curves)
> + * @px: Compand curve x-values. Each value stores the distance from the
> + *      previous x-value, expressed as log2 of the distance on 5 bits.
> + * @x: Compand curve x-values. The functionality of these parameters are
> + *     unknown due to do a lack of hardware documentation, but these are left
> + *     here for future compatibility purposes.
> + * @y: Compand curve y-values
> + */
> +struct rkisp1_cif_isp_compand_curve_config {
> +	__u8 px[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> +	__u32 x[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> +	__u32 y[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> +};
> +
>  /*---------- PART2: Measurement Statistics ------------*/
>
>  /**
> @@ -1018,6 +1056,9 @@ struct rkisp1_stat_buffer {
>   * @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
> + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS: BLS in the compand block
> + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND: Companding expand curve
> + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS: Companding compress curve
>   */
>  enum rkisp1_ext_params_block_type {
>  	RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS,
> @@ -1037,6 +1078,9 @@ enum rkisp1_ext_params_block_type {
>  	RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS,
>  	RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS,
>  	RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS,
> +	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS,
> +	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND,
> +	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS,
>  };
>
>  /**
> @@ -1384,6 +1428,46 @@ struct rkisp1_ext_params_afc_config {
>  	struct rkisp1_cif_isp_afc_config config;
>  } __attribute__((aligned(8)));
>
> +/**
> + * struct rkisp1_ext_params_compand_bls_config - RkISP1 extensible params
> + * Compand BLS config
> + *
> + * RkISP1 extensible parameters Companding configuration block (black level
> + * subtraction). Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS`.
> + *
> + * @header: The RkISP1 extensible parameters header, see
> + *	    :c:type:`rkisp1_ext_params_block_header`
> + * @config: Companding BLS configuration, see
> + *	    :c:type:`rkisp1_cif_isp_compand_bls_config`
> + */
> +struct rkisp1_ext_params_compand_bls_config {
> +	struct rkisp1_ext_params_block_header header;
> +	struct rkisp1_cif_isp_compand_bls_config config;
> +} __attribute__((aligned(8)));
> +
> +/**
> + * struct rkisp1_ext_params_compand_curve_config - RkISP1 extensible params
> + * Compand curve config
> + *
> + * RkISP1 extensible parameters Companding configuration block (expand and
> + * compression curves). Identified by
> + * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND`or
> + * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS`.
> + *
> + * @header: The RkISP1 extensible parameters header, see
> + *	    :c:type:`rkisp1_ext_params_block_header`
> + * @config: Companding curve configuration, see
> + *	    :c:type:`rkisp1_cif_isp_compand_curve_config`
> + */
> +struct rkisp1_ext_params_compand_curve_config {
> +	struct rkisp1_ext_params_block_header header;
> +	struct rkisp1_cif_isp_compand_curve_config config;
> +} __attribute__((aligned(8)));
> +
> +/*
> + * The rkisp1_ext_params_compand_curve_config structure is counted twice as it
> + * is used for both the COMPAND_EXPAND and COMPAND_COMPRESS block types.
> + */
>  #define RKISP1_EXT_PARAMS_MAX_SIZE					\
>  	(sizeof(struct rkisp1_ext_params_bls_config)			+\
>  	sizeof(struct rkisp1_ext_params_dpcc_config)			+\
> @@ -1401,7 +1485,10 @@ struct rkisp1_ext_params_afc_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))
> +	sizeof(struct rkisp1_ext_params_afc_config)			+\
> +	sizeof(struct rkisp1_ext_params_compand_bls_config)		+\
> +	sizeof(struct rkisp1_ext_params_compand_curve_config)		+\
> +	sizeof(struct rkisp1_ext_params_compand_curve_config))
>
>  /**
>   * enum rksip1_ext_param_buffer_version - RkISP1 extensible parameters version
> --
> Regards,
>
> Laurent Pinchart
>
Paul Elder July 5, 2024, 11:28 a.m. UTC | #2
On Thu, Jul 04, 2024 at 06:49:28PM +0300, Laurent Pinchart wrote:
> The BLS parameters passed by userspace are specified for named colour
> channels (R, Gr, Gb and B), while the hardware registers reference
> positions in the 2x2 CFA pattern (A, B, C and D).
> 
> The BLS values are swapped based on the CFA pattern when writing to or
> reading from registers, using hand-roled switch statements. The logic is
> duplicated already, and new code will require similar processing. Move
> the swap logic to a shared function, using static data to control the
> channels order.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>

> ---
> Changes since v1:
> 
> - Declare swap array with explicit dimensions
> - Move i variable declaration to the loop
> - Move rkisp1_bls_swap_regs() declaration
> ---
>  .../platform/rockchip/rkisp1/rkisp1-common.c  | 14 +++++
>  .../platform/rockchip/rkisp1/rkisp1-common.h  |  3 +
>  .../platform/rockchip/rkisp1/rkisp1-params.c  | 58 ++++---------------
>  .../platform/rockchip/rkisp1/rkisp1-stats.c   | 51 +++++-----------
>  4 files changed, 43 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c
> index f956b90a407a..60c97bb7b18b 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c
> @@ -178,3 +178,17 @@ void rkisp1_sd_adjust_crop(struct v4l2_rect *crop,
>  
>  	rkisp1_sd_adjust_crop_rect(crop, &crop_bounds);
>  }
> +
> +void rkisp1_bls_swap_regs(enum rkisp1_fmt_raw_pat_type pattern,
> +			  const u32 input[4], u32 output[4])
> +{
> +	static const unsigned int swap[4][4] = {
> +		[RKISP1_RAW_RGGB] = { 0, 1, 2, 3 },
> +		[RKISP1_RAW_GRBG] = { 1, 0, 3, 2 },
> +		[RKISP1_RAW_GBRG] = { 2, 3, 0, 1 },
> +		[RKISP1_RAW_BGGR] = { 3, 2, 1, 0 },
> +	};
> +
> +	for (unsigned int i = 0; i < 4; ++i)
> +		output[i] = input[swap[pattern][i]];
> +}
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> index c1689c0fa05a..a52079261579 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
> @@ -603,6 +603,9 @@ void rkisp1_sd_adjust_crop_rect(struct v4l2_rect *crop,
>  void rkisp1_sd_adjust_crop(struct v4l2_rect *crop,
>  			   const struct v4l2_mbus_framefmt *bounds);
>  
> +void rkisp1_bls_swap_regs(enum rkisp1_fmt_raw_pat_type pattern,
> +			  const u32 input[4], u32 output[4]);
> +
>  /*
>   * rkisp1_mbus_info_get_by_code - get the isp info of the media bus code
>   *
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 25aede5e1af5..c56365c7c51f 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -165,54 +165,20 @@ static void rkisp1_bls_config(struct rkisp1_params *params,
>  	new_control &= RKISP1_CIF_ISP_BLS_ENA;
>  	/* fixed subtraction values */
>  	if (!arg->enable_auto) {
> -		const struct rkisp1_cif_isp_bls_fixed_val *pval =
> -								&arg->fixed_val;
> +		static const u32 regs[] = {
> +			RKISP1_CIF_ISP_BLS_A_FIXED,
> +			RKISP1_CIF_ISP_BLS_B_FIXED,
> +			RKISP1_CIF_ISP_BLS_C_FIXED,
> +			RKISP1_CIF_ISP_BLS_D_FIXED,
> +		};
> +		u32 swapped[4];
>  
> -		switch (params->raw_type) {
> -		case RKISP1_RAW_BGGR:
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED,
> -				     pval->r);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED,
> -				     pval->gr);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED,
> -				     pval->gb);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED,
> -				     pval->b);
> -			break;
> -		case RKISP1_RAW_GBRG:
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED,
> -				     pval->r);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED,
> -				     pval->gr);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED,
> -				     pval->gb);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED,
> -				     pval->b);
> -			break;
> -		case RKISP1_RAW_GRBG:
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED,
> -				     pval->r);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED,
> -				     pval->gr);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED,
> -				     pval->gb);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED,
> -				     pval->b);
> -			break;
> -		case RKISP1_RAW_RGGB:
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED,
> -				     pval->r);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED,
> -				     pval->gr);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED,
> -				     pval->gb);
> -			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED,
> -				     pval->b);
> -			break;
> -		default:
> -			break;
> -		}
> +		rkisp1_bls_swap_regs(params->raw_type, regs, swapped);
>  
> +		rkisp1_write(params->rkisp1, swapped[0], arg->fixed_val.r);
> +		rkisp1_write(params->rkisp1, swapped[1], arg->fixed_val.gr);
> +		rkisp1_write(params->rkisp1, swapped[2], arg->fixed_val.gb);
> +		rkisp1_write(params->rkisp1, swapped[3], arg->fixed_val.b);
>  	} else {
>  		if (arg->en_windows & BIT(1)) {
>  			rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_H2_START,
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
> index 2795eef91bdd..a502719e916a 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
> @@ -304,48 +304,25 @@ static void rkisp1_stats_get_hst_meas_v12(struct rkisp1_stats *stats,
>  static void rkisp1_stats_get_bls_meas(struct rkisp1_stats *stats,
>  				      struct rkisp1_stat_buffer *pbuf)
>  {
> +	static const u32 regs[] = {
> +		RKISP1_CIF_ISP_BLS_A_MEASURED,
> +		RKISP1_CIF_ISP_BLS_B_MEASURED,
> +		RKISP1_CIF_ISP_BLS_C_MEASURED,
> +		RKISP1_CIF_ISP_BLS_D_MEASURED,
> +	};
>  	struct rkisp1_device *rkisp1 = stats->rkisp1;
>  	const struct rkisp1_mbus_info *in_fmt = rkisp1->isp.sink_fmt;
>  	struct rkisp1_cif_isp_bls_meas_val *bls_val;
> +	u32 swapped[4];
> +
> +	rkisp1_bls_swap_regs(in_fmt->bayer_pat, regs, swapped);
>  
>  	bls_val = &pbuf->params.ae.bls_val;
> -	if (in_fmt->bayer_pat == RKISP1_RAW_BGGR) {
> -		bls_val->meas_b =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED);
> -		bls_val->meas_gb =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED);
> -		bls_val->meas_gr =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED);
> -		bls_val->meas_r =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED);
> -	} else if (in_fmt->bayer_pat == RKISP1_RAW_GBRG) {
> -		bls_val->meas_gb =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED);
> -		bls_val->meas_b =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED);
> -		bls_val->meas_r =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED);
> -		bls_val->meas_gr =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED);
> -	} else if (in_fmt->bayer_pat == RKISP1_RAW_GRBG) {
> -		bls_val->meas_gr =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED);
> -		bls_val->meas_r =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED);
> -		bls_val->meas_b =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED);
> -		bls_val->meas_gb =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED);
> -	} else if (in_fmt->bayer_pat == RKISP1_RAW_RGGB) {
> -		bls_val->meas_r =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED);
> -		bls_val->meas_gr =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED);
> -		bls_val->meas_gb =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED);
> -		bls_val->meas_b =
> -			rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED);
> -	}
> +
> +	bls_val->meas_r = rkisp1_read(rkisp1, swapped[0]);
> +	bls_val->meas_gr = rkisp1_read(rkisp1, swapped[1]);
> +	bls_val->meas_gb = rkisp1_read(rkisp1, swapped[2]);
> +	bls_val->meas_b = rkisp1_read(rkisp1, swapped[3]);
>  }
>  
>  static const struct rkisp1_stats_ops rkisp1_v10_stats_ops = {
> -- 
> Regards,
> 
> Laurent Pinchart
>
Paul Elder July 5, 2024, 11:43 a.m. UTC | #3
On Thu, Jul 04, 2024 at 06:49:32PM +0300, Laurent Pinchart wrote:
> From: Paul Elder <paul.elder@ideasonboard.com>
> 
> Add support to the rkisp1 driver for the companding block that exists on
> the i.MX8MP version of the ISP. This requires usage of the new
> extensible parameters format, and showcases how the format allows for
> extensions without breaking backward compatibility.
> 
> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>

> ---
> Changes since v1:
> 
> - Refactor rkisp1_compand_write_px_curve()
> - Use unsigned int instead of size_t for loop indices
> - Hardcode RKISP1_CIF_ISP_COMPAND_NUM_POINTS points
> - Rename RKISP1_CIF_ISP_COMPAND_MAX_SAMPLES to
>   RKISP1_CIF_ISP_COMPAND_NUM_POINTS
> - Add comment to explain why rkisp1_ext_params_compand_curve_config is
>   counted twice in RKISP1_EXT_PARAMS_MAX_SIZE
> - Fix typo
> 
> Changes since v0:
> 
> - Drop RKISP1_EXT_PARAM_BUFFER_V2
> - Use common structure for compression and expansion curves
> - Rename config fields in rkisp1_ext_params_*_config to just config
> - Mention block type in structures documentation
> - Constify arguments
> - Replace __uxx types with uxx
> - Use rkisp1_bls_swap_regs() helper in rkisp1_compand_bls_config()
> - Use generic feature handling mechanism
> ---
>  .../platform/rockchip/rkisp1/rkisp1-params.c  | 168 ++++++++++++++++++
>  include/uapi/linux/rkisp1-config.h            |  89 +++++++++-
>  2 files changed, 256 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> index 20bc6d582527..430d36aedd76 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> @@ -5,6 +5,7 @@
>   * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>   */
>  
> +#include <linux/math.h>
>  #include <linux/string.h>
>  
>  #include <media/v4l2-common.h>
> @@ -57,6 +58,8 @@ union rkisp1_ext_params_config {
>  	struct rkisp1_ext_params_hst_config hst;
>  	struct rkisp1_ext_params_aec_config aec;
>  	struct rkisp1_ext_params_afc_config afc;
> +	struct rkisp1_ext_params_compand_bls_config compand_bls;
> +	struct rkisp1_ext_params_compand_curve_config compand_curve;
>  };
>  
>  enum rkisp1_params_formats {
> @@ -1258,6 +1261,93 @@ rkisp1_dpf_strength_config(struct rkisp1_params *params,
>  	rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_R, arg->r);
>  }
>  
> +static void rkisp1_compand_write_px_curve(struct rkisp1_params *params,
> +					  unsigned int addr, const u8 *curve)
> +{
> +	const unsigned int points_per_reg = 6;
> +	const unsigned int num_regs =
> +		DIV_ROUND_UP(RKISP1_CIF_ISP_COMPAND_NUM_POINTS,
> +			     points_per_reg);
> +
> +	/*
> +	 * The compand curve is specified as a piecewise linear function with
> +	 * 64 points. X coordinates are stored as a log2 of the displacement
> +	 * from the previous point, in 5 bits, with 6 values per register. The
> +	 * last register stores 4 values.
> +	 */
> +	for (unsigned int reg = 0; reg < num_regs; ++reg) {
> +		unsigned int num_points =
> +			min(RKISP1_CIF_ISP_COMPAND_NUM_POINTS -
> +			    reg * points_per_reg, points_per_reg);
> +		u32 val = 0;
> +
> +		for (unsigned int i = 0; i < num_points; i++)
> +			val |= (*curve++ & 0x1f) << (i * 5);
> +
> +		rkisp1_write(params->rkisp1, addr, val);
> +		addr += 4;
> +	}
> +}
> +
> +static void
> +rkisp1_compand_write_curve_mem(struct rkisp1_params *params,
> +			       unsigned int reg_addr, unsigned int reg_data,
> +			       const u32 curve[RKISP1_CIF_ISP_COMPAND_NUM_POINTS])
> +{
> +	for (unsigned int i = 0; i < RKISP1_CIF_ISP_COMPAND_NUM_POINTS; i++) {
> +		rkisp1_write(params->rkisp1, reg_addr, i);
> +		rkisp1_write(params->rkisp1, reg_data, curve[i]);
> +	}
> +}
> +
> +static void
> +rkisp1_compand_bls_config(struct rkisp1_params *params,
> +			  const struct rkisp1_cif_isp_compand_bls_config *arg)
> +{
> +	static const u32 regs[] = {
> +		RKISP1_CIF_ISP_COMPAND_BLS_A_FIXED,
> +		RKISP1_CIF_ISP_COMPAND_BLS_B_FIXED,
> +		RKISP1_CIF_ISP_COMPAND_BLS_C_FIXED,
> +		RKISP1_CIF_ISP_COMPAND_BLS_D_FIXED,
> +	};
> +	u32 swapped[4];
> +
> +	rkisp1_bls_swap_regs(params->raw_type, regs, swapped);
> +
> +	rkisp1_write(params->rkisp1, swapped[0], arg->r);
> +	rkisp1_write(params->rkisp1, swapped[1], arg->gr);
> +	rkisp1_write(params->rkisp1, swapped[2], arg->gb);
> +	rkisp1_write(params->rkisp1, swapped[3], arg->b);
> +}
> +
> +static void
> +rkisp1_compand_expand_config(struct rkisp1_params *params,
> +			     const struct rkisp1_cif_isp_compand_curve_config *arg)
> +{
> +	rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_EXPAND_PX_N(0),
> +				      arg->px);
> +	rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_Y_ADDR,
> +				       RKISP1_CIF_ISP_COMPAND_EXPAND_Y_WRITE_DATA,
> +				       arg->y);
> +	rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_X_ADDR,
> +				       RKISP1_CIF_ISP_COMPAND_EXPAND_X_WRITE_DATA,
> +				       arg->x);
> +}
> +
> +static void
> +rkisp1_compand_compress_config(struct rkisp1_params *params,
> +			       const struct rkisp1_cif_isp_compand_curve_config *arg)
> +{
> +	rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_PX_N(0),
> +				      arg->px);
> +	rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_ADDR,
> +				       RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_WRITE_DATA,
> +				       arg->y);
> +	rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_X_ADDR,
> +				       RKISP1_CIF_ISP_COMPAND_COMPRESS_X_WRITE_DATA,
> +				       arg->x);
> +}
> +
>  static void
>  rkisp1_isp_isr_other_config(struct rkisp1_params *params,
>  			    const struct rkisp1_params_cfg *new_params)
> @@ -1844,6 +1934,66 @@ rkisp1_ext_params_afcm(struct rkisp1_params *params,
>  				      RKISP1_CIF_ISP_AFM_ENA);
>  }
>  
> +static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
> +					  const union rkisp1_ext_params_config *block)
> +{
> +	const struct rkisp1_ext_params_compand_bls_config *bls =
> +		&block->compand_bls;
> +
> +	if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> +		rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +					RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> +		return;
> +	}
> +
> +	rkisp1_compand_bls_config(params, &bls->config);
> +
> +	if (!(params->enabled_blocks &
> +	      BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS)))
> +		rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +				      RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> +}
> +
> +static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
> +					     const union rkisp1_ext_params_config *block)
> +{
> +	const struct rkisp1_ext_params_compand_curve_config *curve =
> +		&block->compand_curve;
> +
> +	if (curve->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> +		rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +					RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> +		return;
> +	}
> +
> +	rkisp1_compand_expand_config(params, &curve->config);
> +
> +	if (!(params->enabled_blocks &
> +	      BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND)))
> +		rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +				      RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> +}
> +
> +static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
> +					       const union rkisp1_ext_params_config *block)
> +{
> +	const struct rkisp1_ext_params_compand_curve_config *curve =
> +		&block->compand_curve;
> +
> +	if (curve->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> +		rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +					RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> +		return;
> +	}
> +
> +	rkisp1_compand_compress_config(params, &curve->config);
> +
> +	if (!(params->enabled_blocks &
> +	      BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS)))
> +		rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> +				      RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> +}
> +
>  typedef void (*rkisp1_block_handler)(struct rkisp1_params *params,
>  			     const union rkisp1_ext_params_config *config);
>  
> @@ -1939,6 +2089,24 @@ static const struct rkisp1_ext_params_handler {
>  		.handler	= rkisp1_ext_params_afcm,
>  		.group		= RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
>  	},
> +	[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
> +		.size		= sizeof(struct rkisp1_ext_params_compand_bls_config),
> +		.handler	= rkisp1_ext_params_compand_bls,
> +		.group		= RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> +		.features	= RKISP1_FEATURE_COMPAND,
> +	},
> +	[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
> +		.size		= sizeof(struct rkisp1_ext_params_compand_curve_config),
> +		.handler	= rkisp1_ext_params_compand_expand,
> +		.group		= RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> +		.features	= RKISP1_FEATURE_COMPAND,
> +	},
> +	[RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
> +		.size		= sizeof(struct rkisp1_ext_params_compand_curve_config),
> +		.handler	= rkisp1_ext_params_compand_compress,
> +		.group		= RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> +		.features	= RKISP1_FEATURE_COMPAND,
> +	},
>  };
>  
>  static void rkisp1_ext_params_config(struct rkisp1_params *params,
> diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
> index 00b09c92cca7..c645db36f2f6 100644
> --- a/include/uapi/linux/rkisp1-config.h
> +++ b/include/uapi/linux/rkisp1-config.h
> @@ -164,6 +164,11 @@
>  #define RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS      17
>  #define RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS  6
>  
> +/*
> + * Compand
> + */
> +#define RKISP1_CIF_ISP_COMPAND_NUM_POINTS	64
> +
>  /*
>   * Measurement types
>   */
> @@ -851,6 +856,39 @@ struct rkisp1_params_cfg {
>  	struct rkisp1_cif_isp_isp_other_cfg others;
>  };
>  
> +/**
> + * struct rkisp1_cif_isp_compand_bls_config - Rockchip ISP1 Companding parameters (BLS)
> + * @r: Fixed subtraction value for Bayer pattern R
> + * @gr: Fixed subtraction value for Bayer pattern Gr
> + * @gb: Fixed subtraction value for Bayer pattern Gb
> + * @b: Fixed subtraction value for Bayer pattern B
> + *
> + * The values will be subtracted from the sensor values. Note that unlike the
> + * dedicated BLS block, the BLS values in the compander are 20-bit unsigned.
> + */
> +struct rkisp1_cif_isp_compand_bls_config {
> +	__u32 r;
> +	__u32 gr;
> +	__u32 gb;
> +	__u32 b;
> +};
> +
> +/**
> + * struct rkisp1_cif_isp_compand_curve_config - Rockchip ISP1 Companding
> + * parameters (expand and compression curves)
> + * @px: Compand curve x-values. Each value stores the distance from the
> + *      previous x-value, expressed as log2 of the distance on 5 bits.
> + * @x: Compand curve x-values. The functionality of these parameters are
> + *     unknown due to do a lack of hardware documentation, but these are left
> + *     here for future compatibility purposes.
> + * @y: Compand curve y-values
> + */
> +struct rkisp1_cif_isp_compand_curve_config {
> +	__u8 px[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> +	__u32 x[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> +	__u32 y[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> +};
> +
>  /*---------- PART2: Measurement Statistics ------------*/
>  
>  /**
> @@ -1018,6 +1056,9 @@ struct rkisp1_stat_buffer {
>   * @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
> + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS: BLS in the compand block
> + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND: Companding expand curve
> + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS: Companding compress curve
>   */
>  enum rkisp1_ext_params_block_type {
>  	RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS,
> @@ -1037,6 +1078,9 @@ enum rkisp1_ext_params_block_type {
>  	RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS,
>  	RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS,
>  	RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS,
> +	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS,
> +	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND,
> +	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS,
>  };
>  
>  /**
> @@ -1384,6 +1428,46 @@ struct rkisp1_ext_params_afc_config {
>  	struct rkisp1_cif_isp_afc_config config;
>  } __attribute__((aligned(8)));
>  
> +/**
> + * struct rkisp1_ext_params_compand_bls_config - RkISP1 extensible params
> + * Compand BLS config
> + *
> + * RkISP1 extensible parameters Companding configuration block (black level
> + * subtraction). Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS`.
> + *
> + * @header: The RkISP1 extensible parameters header, see
> + *	    :c:type:`rkisp1_ext_params_block_header`
> + * @config: Companding BLS configuration, see
> + *	    :c:type:`rkisp1_cif_isp_compand_bls_config`
> + */
> +struct rkisp1_ext_params_compand_bls_config {
> +	struct rkisp1_ext_params_block_header header;
> +	struct rkisp1_cif_isp_compand_bls_config config;
> +} __attribute__((aligned(8)));
> +
> +/**
> + * struct rkisp1_ext_params_compand_curve_config - RkISP1 extensible params
> + * Compand curve config
> + *
> + * RkISP1 extensible parameters Companding configuration block (expand and
> + * compression curves). Identified by
> + * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND`or
> + * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS`.
> + *
> + * @header: The RkISP1 extensible parameters header, see
> + *	    :c:type:`rkisp1_ext_params_block_header`
> + * @config: Companding curve configuration, see
> + *	    :c:type:`rkisp1_cif_isp_compand_curve_config`
> + */
> +struct rkisp1_ext_params_compand_curve_config {
> +	struct rkisp1_ext_params_block_header header;
> +	struct rkisp1_cif_isp_compand_curve_config config;
> +} __attribute__((aligned(8)));
> +
> +/*
> + * The rkisp1_ext_params_compand_curve_config structure is counted twice as it
> + * is used for both the COMPAND_EXPAND and COMPAND_COMPRESS block types.
> + */
>  #define RKISP1_EXT_PARAMS_MAX_SIZE					\
>  	(sizeof(struct rkisp1_ext_params_bls_config)			+\
>  	sizeof(struct rkisp1_ext_params_dpcc_config)			+\
> @@ -1401,7 +1485,10 @@ struct rkisp1_ext_params_afc_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))
> +	sizeof(struct rkisp1_ext_params_afc_config)			+\
> +	sizeof(struct rkisp1_ext_params_compand_bls_config)		+\
> +	sizeof(struct rkisp1_ext_params_compand_curve_config)		+\
> +	sizeof(struct rkisp1_ext_params_compand_curve_config))
>  
>  /**
>   * enum rksip1_ext_param_buffer_version - RkISP1 extensible parameters version
Adam Ford July 9, 2024, 4:53 p.m. UTC | #4
On Fri, Jul 5, 2024 at 6:43 AM Paul Elder <paul.elder@ideasonboard.com> wrote:
>
> On Thu, Jul 04, 2024 at 06:49:32PM +0300, Laurent Pinchart wrote:
> > From: Paul Elder <paul.elder@ideasonboard.com>
> >
> > Add support to the rkisp1 driver for the companding block that exists on
> > the i.MX8MP version of the ISP. This requires usage of the new
> > extensible parameters format, and showcases how the format allows for
> > extensions without breaking backward compatibility.
> >
> > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>
> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>

If you guys send me instructions on how to use these new features, I
can test this on an 8MP w/ a Sony imx219 sensor configured in 4-lane
mode.

adam

>
> > ---
> > Changes since v1:
> >
> > - Refactor rkisp1_compand_write_px_curve()
> > - Use unsigned int instead of size_t for loop indices
> > - Hardcode RKISP1_CIF_ISP_COMPAND_NUM_POINTS points
> > - Rename RKISP1_CIF_ISP_COMPAND_MAX_SAMPLES to
> >   RKISP1_CIF_ISP_COMPAND_NUM_POINTS
> > - Add comment to explain why rkisp1_ext_params_compand_curve_config is
> >   counted twice in RKISP1_EXT_PARAMS_MAX_SIZE
> > - Fix typo
> >
> > Changes since v0:
> >
> > - Drop RKISP1_EXT_PARAM_BUFFER_V2
> > - Use common structure for compression and expansion curves
> > - Rename config fields in rkisp1_ext_params_*_config to just config
> > - Mention block type in structures documentation
> > - Constify arguments
> > - Replace __uxx types with uxx
> > - Use rkisp1_bls_swap_regs() helper in rkisp1_compand_bls_config()
> > - Use generic feature handling mechanism
> > ---
> >  .../platform/rockchip/rkisp1/rkisp1-params.c  | 168 ++++++++++++++++++
> >  include/uapi/linux/rkisp1-config.h            |  89 +++++++++-
> >  2 files changed, 256 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > index 20bc6d582527..430d36aedd76 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > @@ -5,6 +5,7 @@
> >   * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> >   */
> >
> > +#include <linux/math.h>
> >  #include <linux/string.h>
> >
> >  #include <media/v4l2-common.h>
> > @@ -57,6 +58,8 @@ union rkisp1_ext_params_config {
> >       struct rkisp1_ext_params_hst_config hst;
> >       struct rkisp1_ext_params_aec_config aec;
> >       struct rkisp1_ext_params_afc_config afc;
> > +     struct rkisp1_ext_params_compand_bls_config compand_bls;
> > +     struct rkisp1_ext_params_compand_curve_config compand_curve;
> >  };
> >
> >  enum rkisp1_params_formats {
> > @@ -1258,6 +1261,93 @@ rkisp1_dpf_strength_config(struct rkisp1_params *params,
> >       rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_R, arg->r);
> >  }
> >
> > +static void rkisp1_compand_write_px_curve(struct rkisp1_params *params,
> > +                                       unsigned int addr, const u8 *curve)
> > +{
> > +     const unsigned int points_per_reg = 6;
> > +     const unsigned int num_regs =
> > +             DIV_ROUND_UP(RKISP1_CIF_ISP_COMPAND_NUM_POINTS,
> > +                          points_per_reg);
> > +
> > +     /*
> > +      * The compand curve is specified as a piecewise linear function with
> > +      * 64 points. X coordinates are stored as a log2 of the displacement
> > +      * from the previous point, in 5 bits, with 6 values per register. The
> > +      * last register stores 4 values.
> > +      */
> > +     for (unsigned int reg = 0; reg < num_regs; ++reg) {
> > +             unsigned int num_points =
> > +                     min(RKISP1_CIF_ISP_COMPAND_NUM_POINTS -
> > +                         reg * points_per_reg, points_per_reg);
> > +             u32 val = 0;
> > +
> > +             for (unsigned int i = 0; i < num_points; i++)
> > +                     val |= (*curve++ & 0x1f) << (i * 5);
> > +
> > +             rkisp1_write(params->rkisp1, addr, val);
> > +             addr += 4;
> > +     }
> > +}
> > +
> > +static void
> > +rkisp1_compand_write_curve_mem(struct rkisp1_params *params,
> > +                            unsigned int reg_addr, unsigned int reg_data,
> > +                            const u32 curve[RKISP1_CIF_ISP_COMPAND_NUM_POINTS])
> > +{
> > +     for (unsigned int i = 0; i < RKISP1_CIF_ISP_COMPAND_NUM_POINTS; i++) {
> > +             rkisp1_write(params->rkisp1, reg_addr, i);
> > +             rkisp1_write(params->rkisp1, reg_data, curve[i]);
> > +     }
> > +}
> > +
> > +static void
> > +rkisp1_compand_bls_config(struct rkisp1_params *params,
> > +                       const struct rkisp1_cif_isp_compand_bls_config *arg)
> > +{
> > +     static const u32 regs[] = {
> > +             RKISP1_CIF_ISP_COMPAND_BLS_A_FIXED,
> > +             RKISP1_CIF_ISP_COMPAND_BLS_B_FIXED,
> > +             RKISP1_CIF_ISP_COMPAND_BLS_C_FIXED,
> > +             RKISP1_CIF_ISP_COMPAND_BLS_D_FIXED,
> > +     };
> > +     u32 swapped[4];
> > +
> > +     rkisp1_bls_swap_regs(params->raw_type, regs, swapped);
> > +
> > +     rkisp1_write(params->rkisp1, swapped[0], arg->r);
> > +     rkisp1_write(params->rkisp1, swapped[1], arg->gr);
> > +     rkisp1_write(params->rkisp1, swapped[2], arg->gb);
> > +     rkisp1_write(params->rkisp1, swapped[3], arg->b);
> > +}
> > +
> > +static void
> > +rkisp1_compand_expand_config(struct rkisp1_params *params,
> > +                          const struct rkisp1_cif_isp_compand_curve_config *arg)
> > +{
> > +     rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_EXPAND_PX_N(0),
> > +                                   arg->px);
> > +     rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_Y_ADDR,
> > +                                    RKISP1_CIF_ISP_COMPAND_EXPAND_Y_WRITE_DATA,
> > +                                    arg->y);
> > +     rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_X_ADDR,
> > +                                    RKISP1_CIF_ISP_COMPAND_EXPAND_X_WRITE_DATA,
> > +                                    arg->x);
> > +}
> > +
> > +static void
> > +rkisp1_compand_compress_config(struct rkisp1_params *params,
> > +                            const struct rkisp1_cif_isp_compand_curve_config *arg)
> > +{
> > +     rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_PX_N(0),
> > +                                   arg->px);
> > +     rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_ADDR,
> > +                                    RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_WRITE_DATA,
> > +                                    arg->y);
> > +     rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_X_ADDR,
> > +                                    RKISP1_CIF_ISP_COMPAND_COMPRESS_X_WRITE_DATA,
> > +                                    arg->x);
> > +}
> > +
> >  static void
> >  rkisp1_isp_isr_other_config(struct rkisp1_params *params,
> >                           const struct rkisp1_params_cfg *new_params)
> > @@ -1844,6 +1934,66 @@ rkisp1_ext_params_afcm(struct rkisp1_params *params,
> >                                     RKISP1_CIF_ISP_AFM_ENA);
> >  }
> >
> > +static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
> > +                                       const union rkisp1_ext_params_config *block)
> > +{
> > +     const struct rkisp1_ext_params_compand_bls_config *bls =
> > +             &block->compand_bls;
> > +
> > +     if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > +             rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > +                                     RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> > +             return;
> > +     }
> > +
> > +     rkisp1_compand_bls_config(params, &bls->config);
> > +
> > +     if (!(params->enabled_blocks &
> > +           BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS)))
> > +             rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > +                                   RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> > +}
> > +
> > +static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
> > +                                          const union rkisp1_ext_params_config *block)
> > +{
> > +     const struct rkisp1_ext_params_compand_curve_config *curve =
> > +             &block->compand_curve;
> > +
> > +     if (curve->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > +             rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > +                                     RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> > +             return;
> > +     }
> > +
> > +     rkisp1_compand_expand_config(params, &curve->config);
> > +
> > +     if (!(params->enabled_blocks &
> > +           BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND)))
> > +             rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > +                                   RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> > +}
> > +
> > +static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
> > +                                            const union rkisp1_ext_params_config *block)
> > +{
> > +     const struct rkisp1_ext_params_compand_curve_config *curve =
> > +             &block->compand_curve;
> > +
> > +     if (curve->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > +             rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > +                                     RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> > +             return;
> > +     }
> > +
> > +     rkisp1_compand_compress_config(params, &curve->config);
> > +
> > +     if (!(params->enabled_blocks &
> > +           BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS)))
> > +             rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > +                                   RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> > +}
> > +
> >  typedef void (*rkisp1_block_handler)(struct rkisp1_params *params,
> >                            const union rkisp1_ext_params_config *config);
> >
> > @@ -1939,6 +2089,24 @@ static const struct rkisp1_ext_params_handler {
> >               .handler        = rkisp1_ext_params_afcm,
> >               .group          = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> >       },
> > +     [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
> > +             .size           = sizeof(struct rkisp1_ext_params_compand_bls_config),
> > +             .handler        = rkisp1_ext_params_compand_bls,
> > +             .group          = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> > +             .features       = RKISP1_FEATURE_COMPAND,
> > +     },
> > +     [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
> > +             .size           = sizeof(struct rkisp1_ext_params_compand_curve_config),
> > +             .handler        = rkisp1_ext_params_compand_expand,
> > +             .group          = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> > +             .features       = RKISP1_FEATURE_COMPAND,
> > +     },
> > +     [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
> > +             .size           = sizeof(struct rkisp1_ext_params_compand_curve_config),
> > +             .handler        = rkisp1_ext_params_compand_compress,
> > +             .group          = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> > +             .features       = RKISP1_FEATURE_COMPAND,
> > +     },
> >  };
> >
> >  static void rkisp1_ext_params_config(struct rkisp1_params *params,
> > diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
> > index 00b09c92cca7..c645db36f2f6 100644
> > --- a/include/uapi/linux/rkisp1-config.h
> > +++ b/include/uapi/linux/rkisp1-config.h
> > @@ -164,6 +164,11 @@
> >  #define RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS      17
> >  #define RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS  6
> >
> > +/*
> > + * Compand
> > + */
> > +#define RKISP1_CIF_ISP_COMPAND_NUM_POINTS    64
> > +
> >  /*
> >   * Measurement types
> >   */
> > @@ -851,6 +856,39 @@ struct rkisp1_params_cfg {
> >       struct rkisp1_cif_isp_isp_other_cfg others;
> >  };
> >
> > +/**
> > + * struct rkisp1_cif_isp_compand_bls_config - Rockchip ISP1 Companding parameters (BLS)
> > + * @r: Fixed subtraction value for Bayer pattern R
> > + * @gr: Fixed subtraction value for Bayer pattern Gr
> > + * @gb: Fixed subtraction value for Bayer pattern Gb
> > + * @b: Fixed subtraction value for Bayer pattern B
> > + *
> > + * The values will be subtracted from the sensor values. Note that unlike the
> > + * dedicated BLS block, the BLS values in the compander are 20-bit unsigned.
> > + */
> > +struct rkisp1_cif_isp_compand_bls_config {
> > +     __u32 r;
> > +     __u32 gr;
> > +     __u32 gb;
> > +     __u32 b;
> > +};
> > +
> > +/**
> > + * struct rkisp1_cif_isp_compand_curve_config - Rockchip ISP1 Companding
> > + * parameters (expand and compression curves)
> > + * @px: Compand curve x-values. Each value stores the distance from the
> > + *      previous x-value, expressed as log2 of the distance on 5 bits.
> > + * @x: Compand curve x-values. The functionality of these parameters are
> > + *     unknown due to do a lack of hardware documentation, but these are left
> > + *     here for future compatibility purposes.
> > + * @y: Compand curve y-values
> > + */
> > +struct rkisp1_cif_isp_compand_curve_config {
> > +     __u8 px[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> > +     __u32 x[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> > +     __u32 y[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> > +};
> > +
> >  /*---------- PART2: Measurement Statistics ------------*/
> >
> >  /**
> > @@ -1018,6 +1056,9 @@ struct rkisp1_stat_buffer {
> >   * @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
> > + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS: BLS in the compand block
> > + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND: Companding expand curve
> > + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS: Companding compress curve
> >   */
> >  enum rkisp1_ext_params_block_type {
> >       RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS,
> > @@ -1037,6 +1078,9 @@ enum rkisp1_ext_params_block_type {
> >       RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS,
> >       RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS,
> >       RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS,
> > +     RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS,
> > +     RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND,
> > +     RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS,
> >  };
> >
> >  /**
> > @@ -1384,6 +1428,46 @@ struct rkisp1_ext_params_afc_config {
> >       struct rkisp1_cif_isp_afc_config config;
> >  } __attribute__((aligned(8)));
> >
> > +/**
> > + * struct rkisp1_ext_params_compand_bls_config - RkISP1 extensible params
> > + * Compand BLS config
> > + *
> > + * RkISP1 extensible parameters Companding configuration block (black level
> > + * subtraction). Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS`.
> > + *
> > + * @header: The RkISP1 extensible parameters header, see
> > + *       :c:type:`rkisp1_ext_params_block_header`
> > + * @config: Companding BLS configuration, see
> > + *       :c:type:`rkisp1_cif_isp_compand_bls_config`
> > + */
> > +struct rkisp1_ext_params_compand_bls_config {
> > +     struct rkisp1_ext_params_block_header header;
> > +     struct rkisp1_cif_isp_compand_bls_config config;
> > +} __attribute__((aligned(8)));
> > +
> > +/**
> > + * struct rkisp1_ext_params_compand_curve_config - RkISP1 extensible params
> > + * Compand curve config
> > + *
> > + * RkISP1 extensible parameters Companding configuration block (expand and
> > + * compression curves). Identified by
> > + * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND`or
> > + * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS`.
> > + *
> > + * @header: The RkISP1 extensible parameters header, see
> > + *       :c:type:`rkisp1_ext_params_block_header`
> > + * @config: Companding curve configuration, see
> > + *       :c:type:`rkisp1_cif_isp_compand_curve_config`
> > + */
> > +struct rkisp1_ext_params_compand_curve_config {
> > +     struct rkisp1_ext_params_block_header header;
> > +     struct rkisp1_cif_isp_compand_curve_config config;
> > +} __attribute__((aligned(8)));
> > +
> > +/*
> > + * The rkisp1_ext_params_compand_curve_config structure is counted twice as it
> > + * is used for both the COMPAND_EXPAND and COMPAND_COMPRESS block types.
> > + */
> >  #define RKISP1_EXT_PARAMS_MAX_SIZE                                   \
> >       (sizeof(struct rkisp1_ext_params_bls_config)                    +\
> >       sizeof(struct rkisp1_ext_params_dpcc_config)                    +\
> > @@ -1401,7 +1485,10 @@ struct rkisp1_ext_params_afc_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))
> > +     sizeof(struct rkisp1_ext_params_afc_config)                     +\
> > +     sizeof(struct rkisp1_ext_params_compand_bls_config)             +\
> > +     sizeof(struct rkisp1_ext_params_compand_curve_config)           +\
> > +     sizeof(struct rkisp1_ext_params_compand_curve_config))
> >
> >  /**
> >   * enum rksip1_ext_param_buffer_version - RkISP1 extensible parameters version
>
Jacopo Mondi July 10, 2024, 8:09 a.m. UTC | #5
Hi Adam

On Tue, Jul 09, 2024 at 11:53:38AM GMT, Adam Ford wrote:
> On Fri, Jul 5, 2024 at 6:43 AM Paul Elder <paul.elder@ideasonboard.com> wrote:
> >
> > On Thu, Jul 04, 2024 at 06:49:32PM +0300, Laurent Pinchart wrote:
> > > From: Paul Elder <paul.elder@ideasonboard.com>
> > >
> > > Add support to the rkisp1 driver for the companding block that exists on
> > > the i.MX8MP version of the ISP. This requires usage of the new
> > > extensible parameters format, and showcases how the format allows for
> > > extensions without breaking backward compatibility.
> > >
> > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >
> > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
>
> If you guys send me instructions on how to use these new features, I
> can test this on an 8MP w/ a Sony imx219 sensor configured in 4-lane
> mode.

Thanks!

This branch here
https://gitlab.com/ideasonboard/nxp/linux/-/tree/v6.10/merge?ref_type=heads
contains all the extensible parameters format and the companding
support for i.MX8MP

libcamera support for the extensible parameters format has not been
yet merged but is available on fdo's gitlab at:
https://gitlab.freedesktop.org/camera/libcamera/-/commits/patchwork/4445/?ref_type=heads

The BLC level for imx219 should be already enabled on master so I've
rebased 'patchwork/4445' on master here:
https://gitlab.freedesktop.org/camera/libcamera/-/tree/imx8mp/extensible-blc-imx219?ref_type=heads

and this should be all you need.

As a bonus, if you want to have a 'live stream' of your camera over
network, have a look at Stefan's:
https://gitlab.freedesktop.org/camera/camshark

>
> adam
>
> >
> > > ---
> > > Changes since v1:
> > >
> > > - Refactor rkisp1_compand_write_px_curve()
> > > - Use unsigned int instead of size_t for loop indices
> > > - Hardcode RKISP1_CIF_ISP_COMPAND_NUM_POINTS points
> > > - Rename RKISP1_CIF_ISP_COMPAND_MAX_SAMPLES to
> > >   RKISP1_CIF_ISP_COMPAND_NUM_POINTS
> > > - Add comment to explain why rkisp1_ext_params_compand_curve_config is
> > >   counted twice in RKISP1_EXT_PARAMS_MAX_SIZE
> > > - Fix typo
> > >
> > > Changes since v0:
> > >
> > > - Drop RKISP1_EXT_PARAM_BUFFER_V2
> > > - Use common structure for compression and expansion curves
> > > - Rename config fields in rkisp1_ext_params_*_config to just config
> > > - Mention block type in structures documentation
> > > - Constify arguments
> > > - Replace __uxx types with uxx
> > > - Use rkisp1_bls_swap_regs() helper in rkisp1_compand_bls_config()
> > > - Use generic feature handling mechanism
> > > ---
> > >  .../platform/rockchip/rkisp1/rkisp1-params.c  | 168 ++++++++++++++++++
> > >  include/uapi/linux/rkisp1-config.h            |  89 +++++++++-
> > >  2 files changed, 256 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > > index 20bc6d582527..430d36aedd76 100644
> > > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
> > > @@ -5,6 +5,7 @@
> > >   * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> > >   */
> > >
> > > +#include <linux/math.h>
> > >  #include <linux/string.h>
> > >
> > >  #include <media/v4l2-common.h>
> > > @@ -57,6 +58,8 @@ union rkisp1_ext_params_config {
> > >       struct rkisp1_ext_params_hst_config hst;
> > >       struct rkisp1_ext_params_aec_config aec;
> > >       struct rkisp1_ext_params_afc_config afc;
> > > +     struct rkisp1_ext_params_compand_bls_config compand_bls;
> > > +     struct rkisp1_ext_params_compand_curve_config compand_curve;
> > >  };
> > >
> > >  enum rkisp1_params_formats {
> > > @@ -1258,6 +1261,93 @@ rkisp1_dpf_strength_config(struct rkisp1_params *params,
> > >       rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_R, arg->r);
> > >  }
> > >
> > > +static void rkisp1_compand_write_px_curve(struct rkisp1_params *params,
> > > +                                       unsigned int addr, const u8 *curve)
> > > +{
> > > +     const unsigned int points_per_reg = 6;
> > > +     const unsigned int num_regs =
> > > +             DIV_ROUND_UP(RKISP1_CIF_ISP_COMPAND_NUM_POINTS,
> > > +                          points_per_reg);
> > > +
> > > +     /*
> > > +      * The compand curve is specified as a piecewise linear function with
> > > +      * 64 points. X coordinates are stored as a log2 of the displacement
> > > +      * from the previous point, in 5 bits, with 6 values per register. The
> > > +      * last register stores 4 values.
> > > +      */
> > > +     for (unsigned int reg = 0; reg < num_regs; ++reg) {
> > > +             unsigned int num_points =
> > > +                     min(RKISP1_CIF_ISP_COMPAND_NUM_POINTS -
> > > +                         reg * points_per_reg, points_per_reg);
> > > +             u32 val = 0;
> > > +
> > > +             for (unsigned int i = 0; i < num_points; i++)
> > > +                     val |= (*curve++ & 0x1f) << (i * 5);
> > > +
> > > +             rkisp1_write(params->rkisp1, addr, val);
> > > +             addr += 4;
> > > +     }
> > > +}
> > > +
> > > +static void
> > > +rkisp1_compand_write_curve_mem(struct rkisp1_params *params,
> > > +                            unsigned int reg_addr, unsigned int reg_data,
> > > +                            const u32 curve[RKISP1_CIF_ISP_COMPAND_NUM_POINTS])
> > > +{
> > > +     for (unsigned int i = 0; i < RKISP1_CIF_ISP_COMPAND_NUM_POINTS; i++) {
> > > +             rkisp1_write(params->rkisp1, reg_addr, i);
> > > +             rkisp1_write(params->rkisp1, reg_data, curve[i]);
> > > +     }
> > > +}
> > > +
> > > +static void
> > > +rkisp1_compand_bls_config(struct rkisp1_params *params,
> > > +                       const struct rkisp1_cif_isp_compand_bls_config *arg)
> > > +{
> > > +     static const u32 regs[] = {
> > > +             RKISP1_CIF_ISP_COMPAND_BLS_A_FIXED,
> > > +             RKISP1_CIF_ISP_COMPAND_BLS_B_FIXED,
> > > +             RKISP1_CIF_ISP_COMPAND_BLS_C_FIXED,
> > > +             RKISP1_CIF_ISP_COMPAND_BLS_D_FIXED,
> > > +     };
> > > +     u32 swapped[4];
> > > +
> > > +     rkisp1_bls_swap_regs(params->raw_type, regs, swapped);
> > > +
> > > +     rkisp1_write(params->rkisp1, swapped[0], arg->r);
> > > +     rkisp1_write(params->rkisp1, swapped[1], arg->gr);
> > > +     rkisp1_write(params->rkisp1, swapped[2], arg->gb);
> > > +     rkisp1_write(params->rkisp1, swapped[3], arg->b);
> > > +}
> > > +
> > > +static void
> > > +rkisp1_compand_expand_config(struct rkisp1_params *params,
> > > +                          const struct rkisp1_cif_isp_compand_curve_config *arg)
> > > +{
> > > +     rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_EXPAND_PX_N(0),
> > > +                                   arg->px);
> > > +     rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_Y_ADDR,
> > > +                                    RKISP1_CIF_ISP_COMPAND_EXPAND_Y_WRITE_DATA,
> > > +                                    arg->y);
> > > +     rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_X_ADDR,
> > > +                                    RKISP1_CIF_ISP_COMPAND_EXPAND_X_WRITE_DATA,
> > > +                                    arg->x);
> > > +}
> > > +
> > > +static void
> > > +rkisp1_compand_compress_config(struct rkisp1_params *params,
> > > +                            const struct rkisp1_cif_isp_compand_curve_config *arg)
> > > +{
> > > +     rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_PX_N(0),
> > > +                                   arg->px);
> > > +     rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_ADDR,
> > > +                                    RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_WRITE_DATA,
> > > +                                    arg->y);
> > > +     rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_X_ADDR,
> > > +                                    RKISP1_CIF_ISP_COMPAND_COMPRESS_X_WRITE_DATA,
> > > +                                    arg->x);
> > > +}
> > > +
> > >  static void
> > >  rkisp1_isp_isr_other_config(struct rkisp1_params *params,
> > >                           const struct rkisp1_params_cfg *new_params)
> > > @@ -1844,6 +1934,66 @@ rkisp1_ext_params_afcm(struct rkisp1_params *params,
> > >                                     RKISP1_CIF_ISP_AFM_ENA);
> > >  }
> > >
> > > +static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
> > > +                                       const union rkisp1_ext_params_config *block)
> > > +{
> > > +     const struct rkisp1_ext_params_compand_bls_config *bls =
> > > +             &block->compand_bls;
> > > +
> > > +     if (bls->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > > +             rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > > +                                     RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> > > +             return;
> > > +     }
> > > +
> > > +     rkisp1_compand_bls_config(params, &bls->config);
> > > +
> > > +     if (!(params->enabled_blocks &
> > > +           BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS)))
> > > +             rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > > +                                   RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
> > > +}
> > > +
> > > +static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
> > > +                                          const union rkisp1_ext_params_config *block)
> > > +{
> > > +     const struct rkisp1_ext_params_compand_curve_config *curve =
> > > +             &block->compand_curve;
> > > +
> > > +     if (curve->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > > +             rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > > +                                     RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> > > +             return;
> > > +     }
> > > +
> > > +     rkisp1_compand_expand_config(params, &curve->config);
> > > +
> > > +     if (!(params->enabled_blocks &
> > > +           BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND)))
> > > +             rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > > +                                   RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
> > > +}
> > > +
> > > +static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
> > > +                                            const union rkisp1_ext_params_config *block)
> > > +{
> > > +     const struct rkisp1_ext_params_compand_curve_config *curve =
> > > +             &block->compand_curve;
> > > +
> > > +     if (curve->header.enable == RKISP1_EXT_PARAMS_BLOCK_DISABLE) {
> > > +             rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > > +                                     RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> > > +             return;
> > > +     }
> > > +
> > > +     rkisp1_compand_compress_config(params, &curve->config);
> > > +
> > > +     if (!(params->enabled_blocks &
> > > +           BIT(RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS)))
> > > +             rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
> > > +                                   RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
> > > +}
> > > +
> > >  typedef void (*rkisp1_block_handler)(struct rkisp1_params *params,
> > >                            const union rkisp1_ext_params_config *config);
> > >
> > > @@ -1939,6 +2089,24 @@ static const struct rkisp1_ext_params_handler {
> > >               .handler        = rkisp1_ext_params_afcm,
> > >               .group          = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> > >       },
> > > +     [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
> > > +             .size           = sizeof(struct rkisp1_ext_params_compand_bls_config),
> > > +             .handler        = rkisp1_ext_params_compand_bls,
> > > +             .group          = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> > > +             .features       = RKISP1_FEATURE_COMPAND,
> > > +     },
> > > +     [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
> > > +             .size           = sizeof(struct rkisp1_ext_params_compand_curve_config),
> > > +             .handler        = rkisp1_ext_params_compand_expand,
> > > +             .group          = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> > > +             .features       = RKISP1_FEATURE_COMPAND,
> > > +     },
> > > +     [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
> > > +             .size           = sizeof(struct rkisp1_ext_params_compand_curve_config),
> > > +             .handler        = rkisp1_ext_params_compand_compress,
> > > +             .group          = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
> > > +             .features       = RKISP1_FEATURE_COMPAND,
> > > +     },
> > >  };
> > >
> > >  static void rkisp1_ext_params_config(struct rkisp1_params *params,
> > > diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
> > > index 00b09c92cca7..c645db36f2f6 100644
> > > --- a/include/uapi/linux/rkisp1-config.h
> > > +++ b/include/uapi/linux/rkisp1-config.h
> > > @@ -164,6 +164,11 @@
> > >  #define RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS      17
> > >  #define RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS  6
> > >
> > > +/*
> > > + * Compand
> > > + */
> > > +#define RKISP1_CIF_ISP_COMPAND_NUM_POINTS    64
> > > +
> > >  /*
> > >   * Measurement types
> > >   */
> > > @@ -851,6 +856,39 @@ struct rkisp1_params_cfg {
> > >       struct rkisp1_cif_isp_isp_other_cfg others;
> > >  };
> > >
> > > +/**
> > > + * struct rkisp1_cif_isp_compand_bls_config - Rockchip ISP1 Companding parameters (BLS)
> > > + * @r: Fixed subtraction value for Bayer pattern R
> > > + * @gr: Fixed subtraction value for Bayer pattern Gr
> > > + * @gb: Fixed subtraction value for Bayer pattern Gb
> > > + * @b: Fixed subtraction value for Bayer pattern B
> > > + *
> > > + * The values will be subtracted from the sensor values. Note that unlike the
> > > + * dedicated BLS block, the BLS values in the compander are 20-bit unsigned.
> > > + */
> > > +struct rkisp1_cif_isp_compand_bls_config {
> > > +     __u32 r;
> > > +     __u32 gr;
> > > +     __u32 gb;
> > > +     __u32 b;
> > > +};
> > > +
> > > +/**
> > > + * struct rkisp1_cif_isp_compand_curve_config - Rockchip ISP1 Companding
> > > + * parameters (expand and compression curves)
> > > + * @px: Compand curve x-values. Each value stores the distance from the
> > > + *      previous x-value, expressed as log2 of the distance on 5 bits.
> > > + * @x: Compand curve x-values. The functionality of these parameters are
> > > + *     unknown due to do a lack of hardware documentation, but these are left
> > > + *     here for future compatibility purposes.
> > > + * @y: Compand curve y-values
> > > + */
> > > +struct rkisp1_cif_isp_compand_curve_config {
> > > +     __u8 px[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> > > +     __u32 x[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> > > +     __u32 y[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
> > > +};
> > > +
> > >  /*---------- PART2: Measurement Statistics ------------*/
> > >
> > >  /**
> > > @@ -1018,6 +1056,9 @@ struct rkisp1_stat_buffer {
> > >   * @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
> > > + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS: BLS in the compand block
> > > + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND: Companding expand curve
> > > + * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS: Companding compress curve
> > >   */
> > >  enum rkisp1_ext_params_block_type {
> > >       RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS,
> > > @@ -1037,6 +1078,9 @@ enum rkisp1_ext_params_block_type {
> > >       RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS,
> > >       RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS,
> > >       RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS,
> > > +     RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS,
> > > +     RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND,
> > > +     RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS,
> > >  };
> > >
> > >  /**
> > > @@ -1384,6 +1428,46 @@ struct rkisp1_ext_params_afc_config {
> > >       struct rkisp1_cif_isp_afc_config config;
> > >  } __attribute__((aligned(8)));
> > >
> > > +/**
> > > + * struct rkisp1_ext_params_compand_bls_config - RkISP1 extensible params
> > > + * Compand BLS config
> > > + *
> > > + * RkISP1 extensible parameters Companding configuration block (black level
> > > + * subtraction). Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS`.
> > > + *
> > > + * @header: The RkISP1 extensible parameters header, see
> > > + *       :c:type:`rkisp1_ext_params_block_header`
> > > + * @config: Companding BLS configuration, see
> > > + *       :c:type:`rkisp1_cif_isp_compand_bls_config`
> > > + */
> > > +struct rkisp1_ext_params_compand_bls_config {
> > > +     struct rkisp1_ext_params_block_header header;
> > > +     struct rkisp1_cif_isp_compand_bls_config config;
> > > +} __attribute__((aligned(8)));
> > > +
> > > +/**
> > > + * struct rkisp1_ext_params_compand_curve_config - RkISP1 extensible params
> > > + * Compand curve config
> > > + *
> > > + * RkISP1 extensible parameters Companding configuration block (expand and
> > > + * compression curves). Identified by
> > > + * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND`or
> > > + * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS`.
> > > + *
> > > + * @header: The RkISP1 extensible parameters header, see
> > > + *       :c:type:`rkisp1_ext_params_block_header`
> > > + * @config: Companding curve configuration, see
> > > + *       :c:type:`rkisp1_cif_isp_compand_curve_config`
> > > + */
> > > +struct rkisp1_ext_params_compand_curve_config {
> > > +     struct rkisp1_ext_params_block_header header;
> > > +     struct rkisp1_cif_isp_compand_curve_config config;
> > > +} __attribute__((aligned(8)));
> > > +
> > > +/*
> > > + * The rkisp1_ext_params_compand_curve_config structure is counted twice as it
> > > + * is used for both the COMPAND_EXPAND and COMPAND_COMPRESS block types.
> > > + */
> > >  #define RKISP1_EXT_PARAMS_MAX_SIZE                                   \
> > >       (sizeof(struct rkisp1_ext_params_bls_config)                    +\
> > >       sizeof(struct rkisp1_ext_params_dpcc_config)                    +\
> > > @@ -1401,7 +1485,10 @@ struct rkisp1_ext_params_afc_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))
> > > +     sizeof(struct rkisp1_ext_params_afc_config)                     +\
> > > +     sizeof(struct rkisp1_ext_params_compand_bls_config)             +\
> > > +     sizeof(struct rkisp1_ext_params_compand_curve_config)           +\
> > > +     sizeof(struct rkisp1_ext_params_compand_curve_config))
> > >
> > >  /**
> > >   * enum rksip1_ext_param_buffer_version - RkISP1 extensible parameters version
> >