[{"id":37392,"web_url":"https://patchwork.libcamera.org/comment/37392/","msgid":"<176581886524.1098171.5072828196311756827@ping.linuxembedded.co.uk>","date":"2025-12-15T17:14:25","subject":"Re: [PATCH v7 5/5] ipa: mali-c55: Introduce MaliC55Params","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Jacopo Mondi (2025-12-15 15:11:25)\n> Implement MaliC55Params to derive from V4L2Params and use the new\n> helpers in the Mali C55 IPA algorithms implementation.\n> \n> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> Tested-by: Antoine Bouyer <antoine.bouyer@nxp.com>\n> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>\n\nWell I got all the way to the bottom. It's terse, but there's nothing\nthat jumped out to me as incorrect - and it's all about converting to\nthe new types so:\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> ---\n>  src/ipa/mali-c55/algorithms/agc.cpp | 87 +++++++++++++++----------------------\n>  src/ipa/mali-c55/algorithms/agc.h   | 14 +++---\n>  src/ipa/mali-c55/algorithms/awb.cpp | 64 +++++++++++----------------\n>  src/ipa/mali-c55/algorithms/awb.h   | 10 ++---\n>  src/ipa/mali-c55/algorithms/blc.cpp | 20 +++------\n>  src/ipa/mali-c55/algorithms/blc.h   |  3 +-\n>  src/ipa/mali-c55/algorithms/lsc.cpp | 58 ++++++++++---------------\n>  src/ipa/mali-c55/algorithms/lsc.h   |  8 ++--\n>  src/ipa/mali-c55/mali-c55.cpp       | 20 +++------\n>  src/ipa/mali-c55/module.h           |  3 +-\n>  src/ipa/mali-c55/params.h           | 77 ++++++++++++++++++++++++++++++++\n>  11 files changed, 191 insertions(+), 173 deletions(-)\n> \n> diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp\n> index 78e7e07b2348a711e6261bac45e006f49a59513a..5d60cd8c9ff8a90e2e48e5d6939b538135b7ec3d 100644\n> --- a/src/ipa/mali-c55/algorithms/agc.cpp\n> +++ b/src/ipa/mali-c55/algorithms/agc.cpp\n> @@ -241,8 +241,8 @@ void Agc::queueRequest(IPAContext &context, const uint32_t frame,\n>         }\n>  }\n>  \n> -size_t Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContext,\n> -                              mali_c55_params_block block)\n> +void Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContext,\n> +                            MaliC55Params *params)\n>  {\n>         IPAActiveState &activeState = context.activeState;\n>         double gain;\n> @@ -252,52 +252,50 @@ size_t Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContex\n>         else\n>                 gain = activeState.agc.manual.ispGain;\n>  \n> -       block.header->type = MALI_C55_PARAM_BLOCK_DIGITAL_GAIN;\n> -       block.header->flags = 0;\n> -       block.header->size = sizeof(struct mali_c55_params_digital_gain);\n> +       auto block = params->block<MaliC55Blocks::Dgain>();\n> +       block->gain = floatingToFixedPoint<5, 8, uint16_t, double>(gain);\n>  \n> -       block.digital_gain->gain = floatingToFixedPoint<5, 8, uint16_t, double>(gain);\n>         frameContext.agc.ispGain = gain;\n> -\n> -       return block.header->size;\n>  }\n>  \n> -size_t Agc::fillParamsBuffer(mali_c55_params_block block,\n> -                            enum mali_c55_param_block_type type)\n> +void Agc::fillParamsBuffer(MaliC55Params *params, enum MaliC55Blocks type)\n>  {\n> -       block.header->type = type;\n> -       block.header->flags = 0;\n> -       block.header->size = sizeof(struct mali_c55_params_aexp_hist);\n> +\n> +       assert(type == MaliC55Blocks::AexpHist || type == MaliC55Blocks::AexpIhist);\n> +\n> +       auto block = type == MaliC55Blocks::AexpHist ?\n> +                       params->block<MaliC55Blocks::AexpHist>() :\n> +                       params->block<MaliC55Blocks::AexpIhist>();\n>  \n>         /* Collect every 3rd pixel horizontally */\n> -       block.aexp_hist->skip_x = 1;\n> +       block->skip_x = 1;\n>         /* Start from first column */\n> -       block.aexp_hist->offset_x = 0;\n> +       block->offset_x = 0;\n>         /* Collect every pixel vertically */\n> -       block.aexp_hist->skip_y = 0;\n> +       block->skip_y = 0;\n>         /* Start from the first row */\n> -       block.aexp_hist->offset_y = 0;\n> +       block->offset_y = 0;\n>         /* 1x scaling (i.e. none) */\n> -       block.aexp_hist->scale_bottom = 0;\n> -       block.aexp_hist->scale_top = 0;\n> +       block->scale_bottom = 0;\n> +       block->scale_top = 0;\n>         /* Collect all Bayer planes into 4 separate histograms */\n> -       block.aexp_hist->plane_mode = 1;\n> +       block->plane_mode = 1;\n>         /* Tap the data immediately after the digital gain block */\n> -       block.aexp_hist->tap_point = MALI_C55_AEXP_HIST_TAP_FS;\n> -\n> -       return block.header->size;\n> +       block->tap_point = MALI_C55_AEXP_HIST_TAP_FS;\n>  }\n>  \n> -size_t Agc::fillWeightsArrayBuffer(mali_c55_params_block block,\n> -                                  enum mali_c55_param_block_type type)\n> +void Agc::fillWeightsArrayBuffer(MaliC55Params *params, const enum MaliC55Blocks type)\n>  {\n> -       block.header->type = type;\n> -       block.header->flags = 0;\n> -       block.header->size = sizeof(struct mali_c55_params_aexp_weights);\n> +       assert(type == MaliC55Blocks::AexpHistWeights ||\n> +              type == MaliC55Blocks::AexpIhistWeights);\n> +\n> +       auto block = type == MaliC55Blocks::AexpHistWeights ?\n> +                       params->block<MaliC55Blocks::AexpHistWeights>() :\n> +                       params->block<MaliC55Blocks::AexpIhistWeights>();\n>  \n>         /* We use every zone - a 15x15 grid */\n> -       block.aexp_weights->nodes_used_horiz = 15;\n> -       block.aexp_weights->nodes_used_vert = 15;\n> +       block->nodes_used_horiz = 15;\n> +       block->nodes_used_vert = 15;\n>  \n>         /*\n>          * We uniformly weight the zones to 1 - this results in the collected\n> @@ -305,40 +303,25 @@ size_t Agc::fillWeightsArrayBuffer(mali_c55_params_block block,\n>          * approximate colour channel averages for the image.\n>          */\n>         Span<uint8_t> weights{\n> -               block.aexp_weights->zone_weights,\n> +               block->zone_weights,\n>                 MALI_C55_MAX_ZONES\n>         };\n>         std::fill(weights.begin(), weights.end(), 1);\n> -\n> -       return block.header->size;\n>  }\n>  \n>  void Agc::prepare(IPAContext &context, const uint32_t frame,\n> -                 IPAFrameContext &frameContext, v4l2_isp_params_buffer *params)\n> +                 IPAFrameContext &frameContext, MaliC55Params *params)\n>  {\n> -       mali_c55_params_block block;\n> -\n> -       block.data = &params->data[params->data_size];\n> -       params->data_size += fillGainParamBlock(context, frameContext, block);\n> +       fillGainParamBlock(context, frameContext, params);\n>  \n>         if (frame > 0)\n>                 return;\n>  \n> -       block.data = &params->data[params->data_size];\n> -       params->data_size += fillParamsBuffer(block,\n> -                                              MALI_C55_PARAM_BLOCK_AEXP_HIST);\n> -\n> -       block.data = &params->data[params->data_size];\n> -       params->data_size += fillWeightsArrayBuffer(block,\n> -                                                    MALI_C55_PARAM_BLOCK_AEXP_HIST_WEIGHTS);\n> -\n> -       block.data = &params->data[params->data_size];\n> -       params->data_size += fillParamsBuffer(block,\n> -                                              MALI_C55_PARAM_BLOCK_AEXP_IHIST);\n> +       fillParamsBuffer(params, MaliC55Blocks::AexpHist);\n> +       fillWeightsArrayBuffer(params, MaliC55Blocks::AexpHistWeights);\n>  \n> -       block.data = &params->data[params->data_size];\n> -       params->data_size += fillWeightsArrayBuffer(block,\n> -                                                    MALI_C55_PARAM_BLOCK_AEXP_IHIST_WEIGHTS);\n> +       fillParamsBuffer(params, MaliC55Blocks::AexpIhist);\n> +       fillWeightsArrayBuffer(params, MaliC55Blocks::AexpIhistWeights);\n>  }\n>  \n>  double Agc::estimateLuminance(const double gain) const\n> diff --git a/src/ipa/mali-c55/algorithms/agc.h b/src/ipa/mali-c55/algorithms/agc.h\n> index 4325ef5a9b7dcef36107b64a65db993f194d4167..9684fff664bc67d287bb00f8dc88e238d8dd0cea 100644\n> --- a/src/ipa/mali-c55/algorithms/agc.h\n> +++ b/src/ipa/mali-c55/algorithms/agc.h\n> @@ -57,7 +57,7 @@ public:\n>                           const ControlList &controls) override;\n>         void prepare(IPAContext &context, const uint32_t frame,\n>                      IPAFrameContext &frameContext,\n> -                    v4l2_isp_params_buffer *params) override;\n> +                    MaliC55Params *params) override;\n>         void process(IPAContext &context, const uint32_t frame,\n>                      IPAFrameContext &frameContext,\n>                      const mali_c55_stats_buffer *stats,\n> @@ -65,13 +65,11 @@ public:\n>  \n>  private:\n>         double estimateLuminance(const double gain) const override;\n> -       size_t fillGainParamBlock(IPAContext &context,\n> -                                 IPAFrameContext &frameContext,\n> -                                 mali_c55_params_block block);\n> -       size_t fillParamsBuffer(mali_c55_params_block block,\n> -                               enum mali_c55_param_block_type type);\n> -       size_t fillWeightsArrayBuffer(mali_c55_params_block block,\n> -                                     enum mali_c55_param_block_type type);\n> +       void fillGainParamBlock(IPAContext &context,\n> +                               IPAFrameContext &frameContext,\n> +                               MaliC55Params *params);\n> +       void fillParamsBuffer(MaliC55Params *params, enum MaliC55Blocks type);\n> +       void fillWeightsArrayBuffer(MaliC55Params *params, enum MaliC55Blocks type);\n>  \n>         AgcStatistics statistics_;\n>  };\n> diff --git a/src/ipa/mali-c55/algorithms/awb.cpp b/src/ipa/mali-c55/algorithms/awb.cpp\n> index 694c0aaa9c6804bb58e380ba9c744f11c39224fe..964e810882a93cce02f991675d74bbf163d51e7c 100644\n> --- a/src/ipa/mali-c55/algorithms/awb.cpp\n> +++ b/src/ipa/mali-c55/algorithms/awb.cpp\n> @@ -43,13 +43,9 @@ int Awb::configure([[maybe_unused]] IPAContext &context,\n>         return 0;\n>  }\n>  \n> -size_t Awb::fillGainsParamBlock(mali_c55_params_block block, IPAContext &context,\n> +void Awb::fillGainsParamBlock(MaliC55Params *params, IPAContext &context,\n>                                 IPAFrameContext &frameContext)\n>  {\n> -       block.header->type = MALI_C55_PARAM_BLOCK_AWB_GAINS;\n> -       block.header->flags = 0;\n> -       block.header->size = sizeof(struct mali_c55_params_awb_gains);\n> -\n>         double rGain = context.activeState.awb.rGain;\n>         double bGain = context.activeState.awb.bGain;\n>  \n> @@ -63,34 +59,32 @@ size_t Awb::fillGainsParamBlock(mali_c55_params_block block, IPAContext &context\n>          * This holds true regardless of the bayer order of the input data, as\n>          * the mapping is done internally in the ISP.\n>          */\n> -       block.awb_gains->gain00 = floatingToFixedPoint<4, 8, uint16_t, double>(rGain);\n> -       block.awb_gains->gain01 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0);\n> -       block.awb_gains->gain10 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0);\n> -       block.awb_gains->gain11 = floatingToFixedPoint<4, 8, uint16_t, double>(bGain);\n> +       auto block = params->block<MaliC55Blocks::AwbGains>();\n> +\n> +       block->gain00 = floatingToFixedPoint<4, 8, uint16_t, double>(rGain);\n> +       block->gain01 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0);\n> +       block->gain10 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0);\n> +       block->gain11 = floatingToFixedPoint<4, 8, uint16_t, double>(bGain);\n>  \n>         frameContext.awb.rGain = rGain;\n>         frameContext.awb.bGain = bGain;\n> -\n> -       return sizeof(struct mali_c55_params_awb_gains);\n>  }\n>  \n> -size_t Awb::fillConfigParamBlock(mali_c55_params_block block)\n> +void Awb::fillConfigParamBlock(MaliC55Params *params)\n>  {\n> -       block.header->type = MALI_C55_PARAM_BLOCK_AWB_CONFIG;\n> -       block.header->flags = 0;\n> -       block.header->size = sizeof(struct mali_c55_params_awb_config);\n> +       auto block = params->block<MaliC55Blocks::AwbConfig>();\n>  \n>         /* Tap the stats after the purple fringe block */\n> -       block.awb_config->tap_point = MALI_C55_AWB_STATS_TAP_PF;\n> +       block->tap_point = MALI_C55_AWB_STATS_TAP_PF;\n>  \n>         /* Get R/G and B/G ratios as statistics */\n> -       block.awb_config->stats_mode = MALI_C55_AWB_MODE_RGBG;\n> +       block->stats_mode = MALI_C55_AWB_MODE_RGBG;\n>  \n>         /* Default white level */\n> -       block.awb_config->white_level = 1023;\n> +       block->white_level = 1023;\n>  \n>         /* Default black level */\n> -       block.awb_config->black_level = 0;\n> +       block->black_level = 0;\n>  \n>         /*\n>          * By default pixels are included who's colour ratios are bounded in a\n> @@ -104,40 +98,34 @@ size_t Awb::fillConfigParamBlock(mali_c55_params_block block)\n>          *\n>          * \\todo should these perhaps be tunable?\n>          */\n> -       block.awb_config->cr_max = 511;\n> -       block.awb_config->cr_min = 64;\n> -       block.awb_config->cb_max = 511;\n> -       block.awb_config->cb_min = 64;\n> +       block->cr_max = 511;\n> +       block->cr_min = 64;\n> +       block->cb_max = 511;\n> +       block->cb_min = 64;\n>  \n>         /* We use the full 15x15 zoning scheme */\n> -       block.awb_config->nodes_used_horiz = 15;\n> -       block.awb_config->nodes_used_vert = 15;\n> +       block->nodes_used_horiz = 15;\n> +       block->nodes_used_vert = 15;\n>  \n>         /*\n>          * We set the trimming boundaries equivalent to the main boundaries. In\n>          * other words; no trimming.\n>          */\n> -       block.awb_config->cr_high = 511;\n> -       block.awb_config->cr_low = 64;\n> -       block.awb_config->cb_high = 511;\n> -       block.awb_config->cb_low = 64;\n> -\n> -       return sizeof(struct mali_c55_params_awb_config);\n> +       block->cr_high = 511;\n> +       block->cr_low = 64;\n> +       block->cb_high = 511;\n> +       block->cb_low = 64;\n>  }\n>  \n>  void Awb::prepare(IPAContext &context, const uint32_t frame,\n> -                 IPAFrameContext &frameContext, v4l2_isp_params_buffer *params)\n> +                 IPAFrameContext &frameContext, MaliC55Params *params)\n>  {\n> -       mali_c55_params_block block;\n> -       block.data = &params->data[params->data_size];\n> -\n> -       params->data_size += fillGainsParamBlock(block, context, frameContext);\n> +       fillGainsParamBlock(params, context, frameContext);\n>  \n>         if (frame > 0)\n>                 return;\n>  \n> -       block.data = &params->data[params->data_size];\n> -       params->data_size += fillConfigParamBlock(block);\n> +       fillConfigParamBlock(params);\n>  }\n>  \n>  void Awb::process(IPAContext &context, const uint32_t frame,\n> diff --git a/src/ipa/mali-c55/algorithms/awb.h b/src/ipa/mali-c55/algorithms/awb.h\n> index 647525ff700e8281e3cce63e64ba56a91294bcc2..683a62af263a14d2f5d5b261448953ada6669b2f 100644\n> --- a/src/ipa/mali-c55/algorithms/awb.h\n> +++ b/src/ipa/mali-c55/algorithms/awb.h\n> @@ -22,17 +22,17 @@ public:\n>                       const IPACameraSensorInfo &configInfo) override;\n>         void prepare(IPAContext &context, const uint32_t frame,\n>                      IPAFrameContext &frameContext,\n> -                    v4l2_isp_params_buffer *params) override;\n> +                    MaliC55Params *params) override;\n>         void process(IPAContext &context, const uint32_t frame,\n>                      IPAFrameContext &frameContext,\n>                      const mali_c55_stats_buffer *stats,\n>                      ControlList &metadata) override;\n>  \n>  private:\n> -       size_t fillGainsParamBlock(mali_c55_params_block block,\n> -                                  IPAContext &context,\n> -                                  IPAFrameContext &frameContext);\n> -       size_t fillConfigParamBlock(mali_c55_params_block block);\n> +       void fillGainsParamBlock(MaliC55Params *params,\n> +                                IPAContext &context,\n> +                                IPAFrameContext &frameContext);\n> +       void fillConfigParamBlock(MaliC55Params *params);\n>  };\n>  \n>  } /* namespace ipa::mali_c55::algorithms */\n> diff --git a/src/ipa/mali-c55/algorithms/blc.cpp b/src/ipa/mali-c55/algorithms/blc.cpp\n> index 543ba96cb57ac0cca2b8f822180d8d8b42f21fc7..d099219c3e43ec96fa452ed13fa46ada2025edc9 100644\n> --- a/src/ipa/mali-c55/algorithms/blc.cpp\n> +++ b/src/ipa/mali-c55/algorithms/blc.cpp\n> @@ -85,27 +85,19 @@ int BlackLevelCorrection::configure(IPAContext &context,\n>  void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context,\n>                                    const uint32_t frame,\n>                                    [[maybe_unused]] IPAFrameContext &frameContext,\n> -                                  v4l2_isp_params_buffer *params)\n> +                                  MaliC55Params *params)\n>  {\n> -       mali_c55_params_block block;\n> -       block.data = &params->data[params->data_size];\n> -\n>         if (frame > 0)\n>                 return;\n>  \n>         if (!tuningParameters_)\n>                 return;\n>  \n> -       block.header->type = MALI_C55_PARAM_BLOCK_SENSOR_OFFS;\n> -       block.header->flags = 0;\n> -       block.header->size = sizeof(mali_c55_params_sensor_off_preshading);\n> -\n> -       block.sensor_offs->chan00 = offset00;\n> -       block.sensor_offs->chan01 = offset01;\n> -       block.sensor_offs->chan10 = offset10;\n> -       block.sensor_offs->chan11 = offset11;\n> -\n> -       params->data_size += block.header->size;\n> +       auto block = params->block<MaliC55Blocks::Bls>();\n> +       block->chan00 = offset00;\n> +       block->chan01 = offset01;\n> +       block->chan10 = offset10;\n> +       block->chan11 = offset11;\n>  }\n>  \n>  void BlackLevelCorrection::process([[maybe_unused]] IPAContext &context,\n> diff --git a/src/ipa/mali-c55/algorithms/blc.h b/src/ipa/mali-c55/algorithms/blc.h\n> index ee6c889ed89ac2230b231cb58a9fe4412c0ce164..fc5a7ea310cbdbcf271eb26c73b17243aea744cd 100644\n> --- a/src/ipa/mali-c55/algorithms/blc.h\n> +++ b/src/ipa/mali-c55/algorithms/blc.h\n> @@ -6,6 +6,7 @@\n>   */\n>  \n>  #include \"algorithm.h\"\n> +#include \"params.h\"\n>  \n>  namespace libcamera {\n>  \n> @@ -22,7 +23,7 @@ public:\n>                       const IPACameraSensorInfo &configInfo) override;\n>         void prepare(IPAContext &context, const uint32_t frame,\n>                      IPAFrameContext &frameContext,\n> -                    v4l2_isp_params_buffer *params) override;\n> +                    MaliC55Params *params) override;\n>         void process(IPAContext &context, const uint32_t frame,\n>                      IPAFrameContext &frameContext,\n>                      const mali_c55_stats_buffer *stats,\n> diff --git a/src/ipa/mali-c55/algorithms/lsc.cpp b/src/ipa/mali-c55/algorithms/lsc.cpp\n> index cb915c5efd3c22952035f2b03ee659f293942ec9..5b042c757bc70fe4eb4a5aaa848266b3afce9100 100644\n> --- a/src/ipa/mali-c55/algorithms/lsc.cpp\n> +++ b/src/ipa/mali-c55/algorithms/lsc.cpp\n> @@ -108,41 +108,33 @@ int Lsc::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData\n>         return 0;\n>  }\n>  \n> -size_t Lsc::fillConfigParamsBlock(mali_c55_params_block block) const\n> +void Lsc::fillConfigParamsBlock(MaliC55Params *params) const\n>  {\n> -       block.header->type = MALI_C55_PARAM_MESH_SHADING_CONFIG;\n> -       block.header->flags = 0;\n> -       block.header->size = sizeof(struct mali_c55_params_mesh_shading_config);\n> +       auto block = params->block<MaliC55Blocks::MeshShadingConfig>();\n>  \n> -       block.shading_config->mesh_show = false;\n> -       block.shading_config->mesh_scale = meshScale_;\n> -       block.shading_config->mesh_page_r = 0;\n> -       block.shading_config->mesh_page_g = 1;\n> -       block.shading_config->mesh_page_b = 2;\n> -       block.shading_config->mesh_width = meshSize_;\n> -       block.shading_config->mesh_height = meshSize_;\n> +       block->mesh_show = false;\n> +       block->mesh_scale = meshScale_;\n> +       block->mesh_page_r = 0;\n> +       block->mesh_page_g = 1;\n> +       block->mesh_page_b = 2;\n> +       block->mesh_width = meshSize_;\n> +       block->mesh_height = meshSize_;\n>  \n> -       std::copy(mesh_.begin(), mesh_.end(), block.shading_config->mesh);\n> -\n> -       return block.header->size;\n> +       std::copy(mesh_.begin(), mesh_.end(), block->mesh);\n>  }\n>  \n> -size_t Lsc::fillSelectionParamsBlock(mali_c55_params_block block, uint8_t bank,\n> +void Lsc::fillSelectionParamsBlock(MaliC55Params *params, uint8_t bank,\n>                                      uint8_t alpha) const\n>  {\n> -       block.header->type = MALI_C55_PARAM_MESH_SHADING_SELECTION;\n> -       block.header->flags = 0;\n> -       block.header->size = sizeof(struct mali_c55_params_mesh_shading_selection);\n> -\n> -       block.shading_selection->mesh_alpha_bank_r = bank;\n> -       block.shading_selection->mesh_alpha_bank_g = bank;\n> -       block.shading_selection->mesh_alpha_bank_b = bank;\n> -       block.shading_selection->mesh_alpha_r = alpha;\n> -       block.shading_selection->mesh_alpha_g = alpha;\n> -       block.shading_selection->mesh_alpha_b = alpha;\n> -       block.shading_selection->mesh_strength = 0x1000; /* Otherwise known as 1.0 */\n> -\n> -       return block.header->size;\n> +       auto block = params->block<MaliC55Blocks::MeshShadingSel>();\n> +\n> +       block->mesh_alpha_bank_r = bank;\n> +       block->mesh_alpha_bank_g = bank;\n> +       block->mesh_alpha_bank_b = bank;\n> +       block->mesh_alpha_r = alpha;\n> +       block->mesh_alpha_g = alpha;\n> +       block->mesh_alpha_b = alpha;\n> +       block->mesh_strength = 0x1000; /* Otherwise known as 1.0 */\n>  }\n>  \n>  std::tuple<uint8_t, uint8_t> Lsc::findBankAndAlpha(uint32_t ct) const\n> @@ -170,7 +162,7 @@ std::tuple<uint8_t, uint8_t> Lsc::findBankAndAlpha(uint32_t ct) const\n>  \n>  void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n>                   [[maybe_unused]] IPAFrameContext &frameContext,\n> -                 v4l2_isp_params_buffer *params)\n> +                 MaliC55Params *params)\n>  {\n>         /*\n>          * For each frame we assess the colour temperature of the **last** frame\n> @@ -193,10 +185,7 @@ void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n>                 std::tie(bank, alpha) = findBankAndAlpha(temperatureK);\n>         }\n>  \n> -       mali_c55_params_block block;\n> -       block.data = &params->data[params->data_size];\n> -\n> -       params->data_size += fillSelectionParamsBlock(block, bank, alpha);\n> +       fillSelectionParamsBlock(params, bank, alpha);\n>  \n>         if (frame > 0)\n>                 return;\n> @@ -205,8 +194,7 @@ void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n>          * If this is the first frame, we need to load the parsed coefficient\n>          * tables from tuning data to the ISP.\n>          */\n> -       block.data = &params->data[params->data_size];\n> -       params->data_size += fillConfigParamsBlock(block);\n> +       fillConfigParamsBlock(params);\n>  }\n>  \n>  REGISTER_IPA_ALGORITHM(Lsc, \"Lsc\")\n> diff --git a/src/ipa/mali-c55/algorithms/lsc.h b/src/ipa/mali-c55/algorithms/lsc.h\n> index c287900502528ca82ab6c62d732b6ffc28ad8df6..e7092bc74a0b0301463167d16e1e888696547d10 100644\n> --- a/src/ipa/mali-c55/algorithms/lsc.h\n> +++ b/src/ipa/mali-c55/algorithms/lsc.h\n> @@ -23,15 +23,15 @@ public:\n>         int init(IPAContext &context, const YamlObject &tuningData) override;\n>         void prepare(IPAContext &context, const uint32_t frame,\n>                      IPAFrameContext &frameContext,\n> -                    v4l2_isp_params_buffer *params) override;\n> +                    MaliC55Params *params) override;\n>  private:\n>         static constexpr unsigned int kRedOffset = 0;\n>         static constexpr unsigned int kGreenOffset = 1024;\n>         static constexpr unsigned int kBlueOffset = 2048;\n>  \n> -       size_t fillConfigParamsBlock(mali_c55_params_block block) const;\n> -       size_t fillSelectionParamsBlock(mali_c55_params_block block,\n> -                                       uint8_t bank, uint8_t alpha) const;\n> +       void fillConfigParamsBlock(MaliC55Params *params) const;\n> +       void fillSelectionParamsBlock(MaliC55Params *params,\n> +                                     uint8_t bank, uint8_t alpha) const;\n>         std::tuple<uint8_t, uint8_t> findBankAndAlpha(uint32_t ct) const;\n>  \n>         std::vector<uint32_t> mesh_ = std::vector<uint32_t>(3072);\n> diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp\n> index 3f56604a0488dc853800ad54a54378166d7a112b..1d2a4f75cf8c7908ecebd02e71028d9f84ab1f94 100644\n> --- a/src/ipa/mali-c55/mali-c55.cpp\n> +++ b/src/ipa/mali-c55/mali-c55.cpp\n> @@ -30,6 +30,7 @@\n>  #include \"libipa/camera_sensor_helper.h\"\n>  \n>  #include \"ipa_context.h\"\n> +#include \"params.h\"\n>  \n>  namespace libcamera {\n>  \n> @@ -333,24 +334,13 @@ void IPAMaliC55::queueRequest(const uint32_t request, const ControlList &control\n>  void IPAMaliC55::fillParams(unsigned int request,\n>                             [[maybe_unused]] uint32_t bufferId)\n>  {\n> -       struct v4l2_isp_params_buffer *params;\n>         IPAFrameContext &frameContext = context_.frameContexts.get(request);\n> +       MaliC55Params params(buffers_.at(bufferId).planes()[0]);\n>  \n> -       params = reinterpret_cast<v4l2_isp_params_buffer *>(\n> -               buffers_.at(bufferId).planes()[0].data());\n> -       memset(params, 0,\n> -              buffers_.at(bufferId).planes()[0].size());\n> -\n> -       params->version = V4L2_ISP_PARAMS_VERSION_V1;\n> -\n> -       for (auto const &algo : algorithms()) {\n> -               algo->prepare(context_, request, frameContext, params);\n> -\n> -               ASSERT(params->data_size <= MALI_C55_PARAMS_MAX_SIZE);\n> -       }\n> +       for (auto const &algo : algorithms())\n> +               algo->prepare(context_, request, frameContext, &params);\n>  \n> -       size_t bytesused = offsetof(struct v4l2_isp_params_buffer, data) + params->data_size;\n> -       paramsComputed.emit(request, bytesused);\n> +       paramsComputed.emit(request, params.bytesused());\n>  }\n>  \n>  void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId,\n> diff --git a/src/ipa/mali-c55/module.h b/src/ipa/mali-c55/module.h\n> index a8dcb20841a4ebd7bde22cae4ff1f8eef530d8bb..13b34eb2839530a3518340165e6ca895d0f6bcaf 100644\n> --- a/src/ipa/mali-c55/module.h\n> +++ b/src/ipa/mali-c55/module.h\n> @@ -14,13 +14,14 @@\n>  #include <libipa/module.h>\n>  \n>  #include \"ipa_context.h\"\n> +#include \"params.h\"\n>  \n>  namespace libcamera {\n>  \n>  namespace ipa::mali_c55 {\n>  \n>  using Module = ipa::Module<IPAContext, IPAFrameContext, IPACameraSensorInfo,\n> -                          v4l2_isp_params_buffer, mali_c55_stats_buffer>;\n> +                          MaliC55Params, mali_c55_stats_buffer>;\n>  \n>  } /* namespace ipa::mali_c55 */\n>  \n> diff --git a/src/ipa/mali-c55/params.h b/src/ipa/mali-c55/params.h\n> new file mode 100644\n> index 0000000000000000000000000000000000000000..370f1b8b77bcf9ca5658ff75fca855b4c5f8467b\n> --- /dev/null\n> +++ b/src/ipa/mali-c55/params.h\n> @@ -0,0 +1,77 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2025, Ideas On Board\n> + *\n> + * Mali C55 ISP Parameters\n> + */\n> +\n> +#pragma once\n> +\n> +#include <linux/mali-c55-config.h>\n> +#include <linux/videodev2.h>\n> +\n> +#include <libipa/v4l2_params.h>\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::mali_c55 {\n> +\n> +enum class MaliC55Blocks {\n> +       Bls,\n> +       AexpHist,\n> +       AexpHistWeights,\n> +       AexpIhist,\n> +       AexpIhistWeights,\n> +       Dgain,\n> +       AwbGains,\n> +       AwbConfig,\n> +       MeshShadingConfig,\n> +       MeshShadingSel,\n> +};\n> +\n> +namespace details {\n> +\n> +template<MaliC55Blocks B>\n> +struct block_type {\n> +};\n> +\n> +#define MALI_C55_DEFINE_BLOCK_TYPE(id, cfgType, blkType)               \\\n> +template<>                                                             \\\n> +struct block_type<MaliC55Blocks::id> {                                 \\\n> +       using type = struct mali_c55_params_##cfgType;                  \\\n> +       static constexpr mali_c55_param_block_type blockType =          \\\n> +               mali_c55_param_block_type::MALI_C55_PARAM_##blkType;    \\\n> +}\n> +\n> +MALI_C55_DEFINE_BLOCK_TYPE(Bls,                        sensor_off_preshading,  BLOCK_SENSOR_OFFS);\n> +MALI_C55_DEFINE_BLOCK_TYPE(AexpHist,           aexp_hist,              BLOCK_AEXP_HIST);\n> +MALI_C55_DEFINE_BLOCK_TYPE(AexpHistWeights,    aexp_weights,           BLOCK_AEXP_HIST_WEIGHTS);\n> +MALI_C55_DEFINE_BLOCK_TYPE(AexpIhist,          aexp_hist,              BLOCK_AEXP_IHIST);\n> +MALI_C55_DEFINE_BLOCK_TYPE(AexpIhistWeights,   aexp_weights,           BLOCK_AEXP_IHIST_WEIGHTS);\n> +MALI_C55_DEFINE_BLOCK_TYPE(Dgain,              digital_gain,           BLOCK_DIGITAL_GAIN);\n> +MALI_C55_DEFINE_BLOCK_TYPE(AwbGains,           awb_gains,              BLOCK_AWB_GAINS);\n> +MALI_C55_DEFINE_BLOCK_TYPE(AwbConfig,          awb_config,             BLOCK_AWB_CONFIG);\n> +MALI_C55_DEFINE_BLOCK_TYPE(MeshShadingConfig,  mesh_shading_config,    MESH_SHADING_CONFIG);\n> +MALI_C55_DEFINE_BLOCK_TYPE(MeshShadingSel,     mesh_shading_selection, MESH_SHADING_SELECTION);\n> +\n> +struct param_traits {\n> +       using id_type = MaliC55Blocks;\n> +\n> +       template<id_type Id>\n> +       using id_to_details = block_type<Id>;\n> +};\n> +\n> +} /* namespace details */\n> +\n> +class MaliC55Params : public V4L2Params<details::param_traits>\n> +{\n> +public:\n> +       MaliC55Params(Span<uint8_t> data)\n> +               : V4L2Params(data, V4L2_ISP_PARAMS_VERSION_V1)\n> +       {\n> +       }\n> +};\n> +\n> +} /* namespace ipa::mali_c55 */\n> +\n> +} /* namespace libcamera */\n> \n> -- \n> 2.52.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id B3014C3257\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 15 Dec 2025 17:14:31 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B409E619EF;\n\tMon, 15 Dec 2025 18:14:30 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 2BD88619D8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 15 Dec 2025 18:14:29 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id DAEE6C66;\n\tMon, 15 Dec 2025 18:14:23 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"auGUS5ga\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1765818864;\n\tbh=lIMhqhAo99jp0AUDi+5s1EdeHUrKqqLPNjqtr4NHyvM=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=auGUS5gauf9x9CIqK6hs9P+sb8jQYGcZFRvxnTCTy/aIyR+iNxwB5nuhHD27za0Ye\n\t5vbyiOKbGsz8Kc37isCuf/DqE/OiCHBNgnfb7L+HeJcP3ImKKi3hJJBthh3lZViZMe\n\t3Wsz6wUdR1PjWrMPybmxTv9GXYrEfFyP751Wa7KU=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20251215-v4l2-params-v7-5-be2b8c75ad09@ideasonboard.com>","References":"<20251215-v4l2-params-v7-0-be2b8c75ad09@ideasonboard.com>\n\t<20251215-v4l2-params-v7-5-be2b8c75ad09@ideasonboard.com>","Subject":"Re: [PATCH v7 5/5] ipa: mali-c55: Introduce MaliC55Params","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tAntoine Bouyer <antoine.bouyer@nxp.com>,\n\tDaniel Scally <dan.scally@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 15 Dec 2025 17:14:25 +0000","Message-ID":"<176581886524.1098171.5072828196311756827@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]