From 4acc8e35cff7548eba9fb1e4be4052d5340a9254 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 31 May 2024 12:20:34 +0200 Subject: ipa: rkisp1: Use the extensible parameters format Signed-off-by: Jacopo Mondi --- src/ipa/rkisp1/algorithms/agc.cpp | 73 ++++++++++++------- src/ipa/rkisp1/algorithms/agc.h | 7 +- src/ipa/rkisp1/algorithms/awb.cpp | 116 +++++++++++++++++-------------- src/ipa/rkisp1/algorithms/awb.h | 6 +- src/ipa/rkisp1/algorithms/blc.cpp | 21 +++--- src/ipa/rkisp1/algorithms/blc.h | 2 +- src/ipa/rkisp1/algorithms/cproc.cpp | 17 +++-- src/ipa/rkisp1/algorithms/cproc.h | 2 +- src/ipa/rkisp1/algorithms/dpcc.cpp | 13 ++-- src/ipa/rkisp1/algorithms/dpcc.h | 2 +- src/ipa/rkisp1/algorithms/dpf.cpp | 98 +++++++++++++++++--------- src/ipa/rkisp1/algorithms/dpf.h | 4 +- src/ipa/rkisp1/algorithms/filter.cpp | 15 ++-- src/ipa/rkisp1/algorithms/filter.h | 2 +- src/ipa/rkisp1/algorithms/gsl.cpp | 25 +++---- src/ipa/rkisp1/algorithms/gsl.h | 2 +- src/ipa/rkisp1/algorithms/lsc.cpp | 39 +++++------ src/ipa/rkisp1/algorithms/lsc.h | 4 +- src/ipa/rkisp1/module.h | 2 +- src/ipa/rkisp1/rkisp1.cpp | 34 +++++++-- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 2 +- 21 files changed, 302 insertions(+), 184 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 50e0690f..e2e47453 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -149,11 +149,49 @@ void Agc::queueRequest(IPAContext &context, } } +void Agc::prepareAecMeas(IPAContext &context, + rkisp1_ext_params_aec_config *aec) +{ + aec->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS; + aec->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + aec->header.size = sizeof(rkisp1_ext_params_aec_config); + + /* Configure the measurement window. */ + aec->aec_config.meas_window = context.configuration.agc.measureWindow; + /* Use a continuous method for measure. */ + aec->aec_config.autostop = RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0; + /* Estimate Y as (R + G + B) x (85/256). */ + aec->aec_config.mode = RKISP1_CIF_ISP_EXP_MEASURING_MODE_1; +} + +void Agc::prepareHistMeas(IPAContext &context, + rkisp1_ext_params_hst_config *hst) +{ + hst->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS; + hst->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + hst->header.size = sizeof(rkisp1_ext_params_hst_config); + + hst->hst_config.meas_window = context.configuration.agc.measureWindow; + + /* Produce the luminance histogram. */ + hst->hst_config.mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM; + + /* Set an average weighted histogram. */ + Span weights{ + hst->hst_config.hist_weight, + context.hw->numHistogramWeights + }; + std::fill(weights.begin(), weights.end(), 1); + + /* Step size can't be less than 3. */ + hst->hst_config.histogram_predivider = 4; +} + /** * \copydoc libcamera::ipa::Algorithm::prepare */ void Agc::prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, rkisp1_params_cfg *params) + IPAFrameContext &frameContext, rkisp1_ext_params_block_header *hdr) { if (frameContext.agc.autoEnabled) { frameContext.agc.exposure = context.activeState.agc.automatic.exposure; @@ -163,35 +201,18 @@ void Agc::prepare(IPAContext &context, const uint32_t frame, if (frame > 0) return; - /* Configure the measurement window. */ - params->meas.aec_config.meas_window = context.configuration.agc.measureWindow; - /* Use a continuous method for measure. */ - params->meas.aec_config.autostop = RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0; - /* Estimate Y as (R + G + B) x (85/256). */ - params->meas.aec_config.mode = RKISP1_CIF_ISP_EXP_MEASURING_MODE_1; + struct rkisp1_ext_params_aec_config *aec = + reinterpret_cast(hdr); - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AEC; - params->module_ens |= RKISP1_CIF_ISP_MODULE_AEC; - params->module_en_update |= RKISP1_CIF_ISP_MODULE_AEC; + prepareAecMeas(context, aec); /* Configure histogram. */ - params->meas.hst_config.meas_window = context.configuration.agc.measureWindow; - /* Produce the luminance histogram. */ - params->meas.hst_config.mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM; - /* Set an average weighted histogram. */ - Span weights{ - params->meas.hst_config.hist_weight, - context.hw->numHistogramWeights - }; - std::fill(weights.begin(), weights.end(), 1); - /* Step size can't be less than 3. */ - params->meas.hst_config.histogram_predivider = 4; + char *hst_hdr = reinterpret_cast(hdr); + struct rkisp1_ext_params_hst_config *hst = + reinterpret_cast + (hst_hdr + sizeof(rkisp1_ext_params_aec_config)); - /* Update the configuration for histogram. */ - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_HST; - /* Enable the histogram measure unit. */ - params->module_ens |= RKISP1_CIF_ISP_MODULE_HST; - params->module_en_update |= RKISP1_CIF_ISP_MODULE_HST; + prepareHistMeas(context, hst); } void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext, diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h index 04b3247e..7e994206 100644 --- a/src/ipa/rkisp1/algorithms/agc.h +++ b/src/ipa/rkisp1/algorithms/agc.h @@ -37,7 +37,7 @@ public: const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const rkisp1_stat_buffer *stats, @@ -48,6 +48,11 @@ private: ControlList &metadata); double estimateLuminance(double gain) const override; + void prepareAecMeas(IPAContext &context, + rkisp1_ext_params_aec_config *aec); + void prepareHistMeas(IPAContext &context, + rkisp1_ext_params_hst_config *hst); + Span expMeans_; }; diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index a01fe5d9..b6ca27ba 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -104,45 +104,34 @@ void Awb::queueRequest(IPAContext &context, } } -/** - * \copydoc libcamera::ipa::Algorithm::prepare - */ -void Awb::prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, rkisp1_params_cfg *params) +void Awb::prepareAwbGains(IPAFrameContext &frameContext, + rkisp1_ext_params_awb_gain_config *awbg) { - /* - * This is the latest time we can read the active state. This is the - * most up-to-date automatic values we can read. - */ - if (frameContext.awb.autoEnabled) { - frameContext.awb.gains.red = context.activeState.awb.gains.automatic.red; - frameContext.awb.gains.green = context.activeState.awb.gains.automatic.green; - frameContext.awb.gains.blue = context.activeState.awb.gains.automatic.blue; - } - - params->others.awb_gain_config.gain_green_b = 256 * frameContext.awb.gains.green; - params->others.awb_gain_config.gain_blue = 256 * frameContext.awb.gains.blue; - params->others.awb_gain_config.gain_red = 256 * frameContext.awb.gains.red; - params->others.awb_gain_config.gain_green_r = 256 * frameContext.awb.gains.green; - - /* Update the gains. */ - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN; - - /* If we have already set the AWB measurement parameters, return. */ - if (frame > 0) - return; + awbg->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_GAINS; + awbg->header.size = sizeof(rkisp1_ext_params_awb_gain_config); + awbg->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + + awbg->awb_config.gain_green_b = 256 * frameContext.awb.gains.green; + awbg->awb_config.gain_blue = 256 * frameContext.awb.gains.blue; + awbg->awb_config.gain_red = 256 * frameContext.awb.gains.red; + awbg->awb_config.gain_green_r = 256 * frameContext.awb.gains.green; +} - rkisp1_cif_isp_awb_meas_config &awb_config = params->meas.awb_meas_config; +void Awb::prepareAwbMeas(IPAContext &context, + rkisp1_ext_params_awb_meas_config *awbm) +{ + awbm->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS; + awbm->header.size = sizeof(rkisp1_ext_params_awb_meas_config); + awbm->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; - /* Configure the measure window for AWB. */ - awb_config.awb_wnd = context.configuration.awb.measureWindow; + awbm->awb_meas_config.awb_wnd = context.configuration.awb.measureWindow; /* Number of frames to use to estimate the means (0 means 1 frame). */ - awb_config.frames = 0; + awbm->awb_meas_config.frames = 0; /* Select RGB or YCbCr means measurement. */ if (rgbMode_) { - awb_config.awb_mode = RKISP1_CIF_ISP_AWB_MODE_RGB; + awbm->awb_meas_config.awb_mode = RKISP1_CIF_ISP_AWB_MODE_RGB; /* * For RGB-based measurements, pixels are selected with maximum @@ -150,19 +139,19 @@ void Awb::prepare(IPAContext &context, const uint32_t frame, * awb_ref_cr, awb_min_y and awb_ref_cb respectively. The other * values are not used, set them to 0. */ - awb_config.awb_ref_cr = 250; - awb_config.min_y = 250; - awb_config.awb_ref_cb = 250; + awbm->awb_meas_config.awb_ref_cr = 250; + awbm->awb_meas_config.min_y = 250; + awbm->awb_meas_config.awb_ref_cb = 250; - awb_config.max_y = 0; - awb_config.min_c = 0; - awb_config.max_csum = 0; + awbm->awb_meas_config.max_y = 0; + awbm->awb_meas_config.min_c = 0; + awbm->awb_meas_config.max_csum = 0; } else { - awb_config.awb_mode = RKISP1_CIF_ISP_AWB_MODE_YCBCR; + awbm->awb_meas_config.awb_mode = RKISP1_CIF_ISP_AWB_MODE_YCBCR; /* Set the reference Cr and Cb (AWB target) to white. */ - awb_config.awb_ref_cb = 128; - awb_config.awb_ref_cr = 128; + awbm->awb_meas_config.awb_ref_cb = 128; + awbm->awb_meas_config.awb_ref_cr = 128; /* * Filter out pixels based on luminance and chrominance values. @@ -170,20 +159,45 @@ void Awb::prepare(IPAContext &context, const uint32_t frame, * range, while the acceptable chroma values are specified with * a minimum of 16 and a maximum Cb+Cr sum of 250. */ - awb_config.min_y = 16; - awb_config.max_y = 250; - awb_config.min_c = 16; - awb_config.max_csum = 250; + awbm->awb_meas_config.min_y = 16; + awbm->awb_meas_config.max_y = 250; + awbm->awb_meas_config.min_c = 16; + awbm->awb_meas_config.max_csum = 250; } +} - /* Enable the AWB gains. */ - params->module_en_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN; - params->module_ens |= RKISP1_CIF_ISP_MODULE_AWB_GAIN; +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Awb::prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, rkisp1_ext_params_block_header *hdr) +{ + /* + * This is the latest time we can read the active state. This is the + * most up-to-date automatic values we can read. + */ + if (frameContext.awb.autoEnabled) { + frameContext.awb.gains.red = context.activeState.awb.gains.automatic.red; + frameContext.awb.gains.green = context.activeState.awb.gains.automatic.green; + frameContext.awb.gains.blue = context.activeState.awb.gains.automatic.blue; + } + + struct rkisp1_ext_params_awb_gain_config *awbg = + reinterpret_cast(hdr); + + prepareAwbGains(frameContext, awbg); + + /* If we have already set the AWB measurement parameters, return. */ + if (frame > 0) + return; + + /* Configure the measure window for AWB. */ + char *awb_hdr = reinterpret_cast(hdr); + struct rkisp1_ext_params_awb_meas_config *awbm = + reinterpret_cast + (awb_hdr + sizeof(rkisp1_ext_params_awb_gain_config)); - /* Update the AWB measurement parameters and enable the AWB module. */ - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AWB; - params->module_en_update |= RKISP1_CIF_ISP_MODULE_AWB; - params->module_ens |= RKISP1_CIF_ISP_MODULE_AWB; + prepareAwbMeas(context, awbm); } uint32_t Awb::estimateCCT(double red, double green, double blue) diff --git a/src/ipa/rkisp1/algorithms/awb.h b/src/ipa/rkisp1/algorithms/awb.h index 06c92896..acc1940e 100644 --- a/src/ipa/rkisp1/algorithms/awb.h +++ b/src/ipa/rkisp1/algorithms/awb.h @@ -25,7 +25,7 @@ public: const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const rkisp1_stat_buffer *stats, @@ -33,6 +33,10 @@ public: private: uint32_t estimateCCT(double red, double green, double blue); + void prepareAwbGains(IPAFrameContext &frameContext, + rkisp1_ext_params_awb_gain_config *awbg); + void prepareAwbMeas(IPAContext &context, + rkisp1_ext_params_awb_meas_config *awbm); bool rgbMode_; }; diff --git a/src/ipa/rkisp1/algorithms/blc.cpp b/src/ipa/rkisp1/algorithms/blc.cpp index d2e74354..def3bb80 100644 --- a/src/ipa/rkisp1/algorithms/blc.cpp +++ b/src/ipa/rkisp1/algorithms/blc.cpp @@ -68,7 +68,7 @@ int BlackLevelCorrection::init([[maybe_unused]] IPAContext &context, void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context, const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - rkisp1_params_cfg *params) + rkisp1_ext_params_block_header *hdr) { if (frame > 0) return; @@ -76,15 +76,18 @@ void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context, if (!tuningParameters_) return; - params->others.bls_config.enable_auto = 0; - params->others.bls_config.fixed_val.r = blackLevelRed_; - params->others.bls_config.fixed_val.gr = blackLevelGreenR_; - params->others.bls_config.fixed_val.gb = blackLevelGreenB_; - params->others.bls_config.fixed_val.b = blackLevelBlue_; + struct rkisp1_ext_params_bls_config *bls = + reinterpret_cast(hdr); - params->module_en_update |= RKISP1_CIF_ISP_MODULE_BLS; - params->module_ens |= RKISP1_CIF_ISP_MODULE_BLS; - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_BLS; + bls->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS; + bls->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + bls->header.size = sizeof(rkisp1_ext_params_bls_config); + + bls->bls_config.enable_auto = 0; + bls->bls_config.fixed_val.r = blackLevelRed_; + bls->bls_config.fixed_val.gr = blackLevelGreenR_; + bls->bls_config.fixed_val.gb = blackLevelGreenB_; + bls->bls_config.fixed_val.b = blackLevelBlue_; } REGISTER_IPA_ALGORITHM(BlackLevelCorrection, "BlackLevelCorrection") diff --git a/src/ipa/rkisp1/algorithms/blc.h b/src/ipa/rkisp1/algorithms/blc.h index 460ebcc1..73348807 100644 --- a/src/ipa/rkisp1/algorithms/blc.h +++ b/src/ipa/rkisp1/algorithms/blc.h @@ -22,7 +22,7 @@ public: int init(IPAContext &context, const YamlObject &tuningData) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; private: bool tuningParameters_; diff --git a/src/ipa/rkisp1/algorithms/cproc.cpp b/src/ipa/rkisp1/algorithms/cproc.cpp index 68bb8180..a994302d 100644 --- a/src/ipa/rkisp1/algorithms/cproc.cpp +++ b/src/ipa/rkisp1/algorithms/cproc.cpp @@ -89,19 +89,22 @@ void ColorProcessing::queueRequest(IPAContext &context, void ColorProcessing::prepare([[maybe_unused]] IPAContext &context, [[maybe_unused]] const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) + rkisp1_ext_params_block_header *hdr) { /* Check if the algorithm configuration has been updated. */ if (!frameContext.cproc.update) return; - params->others.cproc_config.brightness = frameContext.cproc.brightness; - params->others.cproc_config.contrast = frameContext.cproc.contrast; - params->others.cproc_config.sat = frameContext.cproc.saturation; + struct rkisp1_ext_params_cproc_config *cproc = + reinterpret_cast(hdr); - params->module_en_update |= RKISP1_CIF_ISP_MODULE_CPROC; - params->module_ens |= RKISP1_CIF_ISP_MODULE_CPROC; - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_CPROC; + cproc->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_CPROC; + cproc->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + cproc->header.size = sizeof(rkisp1_ext_params_cproc_config); + + cproc->cproc_config.brightness = frameContext.cproc.brightness; + cproc->cproc_config.contrast = frameContext.cproc.contrast; + cproc->cproc_config.sat = frameContext.cproc.saturation; } REGISTER_IPA_ALGORITHM(ColorProcessing, "ColorProcessing") diff --git a/src/ipa/rkisp1/algorithms/cproc.h b/src/ipa/rkisp1/algorithms/cproc.h index bafba5cc..1355a02e 100644 --- a/src/ipa/rkisp1/algorithms/cproc.h +++ b/src/ipa/rkisp1/algorithms/cproc.h @@ -26,7 +26,7 @@ public: const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; }; } /* namespace ipa::rkisp1::algorithms */ diff --git a/src/ipa/rkisp1/algorithms/dpcc.cpp b/src/ipa/rkisp1/algorithms/dpcc.cpp index b5a339e9..4223b3e2 100644 --- a/src/ipa/rkisp1/algorithms/dpcc.cpp +++ b/src/ipa/rkisp1/algorithms/dpcc.cpp @@ -232,16 +232,19 @@ int DefectPixelClusterCorrection::init([[maybe_unused]] IPAContext &context, void DefectPixelClusterCorrection::prepare([[maybe_unused]] IPAContext &context, const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - rkisp1_params_cfg *params) + rkisp1_ext_params_block_header *hdr) { if (frame > 0) return; - params->others.dpcc_config = config_; + struct rkisp1_ext_params_dpcc_config *dpcc = + reinterpret_cast(hdr); - params->module_en_update |= RKISP1_CIF_ISP_MODULE_DPCC; - params->module_ens |= RKISP1_CIF_ISP_MODULE_DPCC; - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_DPCC; + dpcc->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_DPCC; + dpcc->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + dpcc->header.size = sizeof(rkisp1_ext_params_dpcc_config); + + dpcc->dpcc_config = config_; } REGISTER_IPA_ALGORITHM(DefectPixelClusterCorrection, "DefectPixelClusterCorrection") diff --git a/src/ipa/rkisp1/algorithms/dpcc.h b/src/ipa/rkisp1/algorithms/dpcc.h index d39b7bed..ba9fff7c 100644 --- a/src/ipa/rkisp1/algorithms/dpcc.h +++ b/src/ipa/rkisp1/algorithms/dpcc.h @@ -22,7 +22,7 @@ public: int init(IPAContext &context, const YamlObject &tuningData) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; private: rkisp1_cif_isp_dpcc_config config_; diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp index abf95728..9f24b13b 100644 --- a/src/ipa/rkisp1/algorithms/dpf.cpp +++ b/src/ipa/rkisp1/algorithms/dpf.cpp @@ -211,46 +211,82 @@ void Dpf::queueRequest(IPAContext &context, frameContext.dpf.update = update; } +void Dpf::prepareDpf(IPAContext &context, rkisp1_ext_params_dpf_config *dpf) +{ + dpf->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF; + dpf->header.size = sizeof(rkisp1_ext_params_dpf_config); + dpf->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + + dpf->dpf_config = config_; + + /* + * The DPF needs to take into account the total amount of + * digital gain, which comes from the AWB and LSC modules. The + * DPF hardware can be programmed with a digital gain value + * manually, but can also use the gains supplied by the AWB and + * LSC modules automatically when they are enabled. Use that + * mode of operation as it simplifies control of the DPF. + */ + const auto &awb = context.configuration.awb; + const auto &lsc = context.configuration.lsc; + auto &mode = dpf->dpf_config.gain.mode; + if (awb.enabled && lsc.enabled) + mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS; + else if (awb.enabled) + mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS; + else if (lsc.enabled) + mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS; + else + mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED; +} + +void Dpf::prepareDpfStrength(rkisp1_ext_params_dpf_strength_config *dpfs) +{ + dpfs->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF_STRENGTH; + dpfs->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + dpfs->header.size = sizeof(rkisp1_ext_params_dpf_strength_config); + + dpfs->dpf_strength_config = strengthConfig_; +} + /** * \copydoc libcamera::ipa::Algorithm::prepare */ void Dpf::prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, rkisp1_params_cfg *params) + IPAFrameContext &frameContext, rkisp1_ext_params_block_header *hdr) { + struct rkisp1_ext_params_dpf_config *dpf = + reinterpret_cast(hdr); + + /* On first frame program both DPF and strenghts. */ if (frame == 0) { - params->others.dpf_config = config_; - params->others.dpf_strength_config = strengthConfig_; - - const auto &awb = context.configuration.awb; - const auto &lsc = context.configuration.lsc; - auto &mode = params->others.dpf_config.gain.mode; - - /* - * The DPF needs to take into account the total amount of - * digital gain, which comes from the AWB and LSC modules. The - * DPF hardware can be programmed with a digital gain value - * manually, but can also use the gains supplied by the AWB and - * LSC modules automatically when they are enabled. Use that - * mode of operation as it simplifies control of the DPF. - */ - if (awb.enabled && lsc.enabled) - mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS; - else if (awb.enabled) - mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS; - else if (lsc.enabled) - mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS; - else - mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED; - - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_DPF | - RKISP1_CIF_ISP_MODULE_DPF_STRENGTH; + + prepareDpf(context, dpf); + + char *dpf_hdr = reinterpret_cast(hdr); + struct rkisp1_ext_params_dpf_strength_config *dpfs = + reinterpret_cast + (dpf_hdr + sizeof(rkisp1_ext_params_dpf_config)); + + prepareDpfStrength(dpfs); + + return; } - if (frameContext.dpf.update) { - params->module_en_update |= RKISP1_CIF_ISP_MODULE_DPF; - if (frameContext.dpf.denoise) - params->module_ens |= RKISP1_CIF_ISP_MODULE_DPF; + /* If no updates, skip the DPF block completely. */ + if (!frameContext.dpf.update) + return; + + /* Re-enable DPF by re-programming it, or disable it. */ + if (frameContext.dpf.denoise) { + prepareDpf(context, dpf); + + return; } + + dpf->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_DPF; + dpf->header.size = sizeof(rkisp1_ext_params_dpf_config); + dpf->header.enable = RKISP1_EXT_PARAMS_BLOCK_DISABLE; } REGISTER_IPA_ALGORITHM(Dpf, "Dpf") diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h index da0115ba..5b8e060d 100644 --- a/src/ipa/rkisp1/algorithms/dpf.h +++ b/src/ipa/rkisp1/algorithms/dpf.h @@ -27,9 +27,11 @@ public: const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; private: + void prepareDpf(IPAContext &context, rkisp1_ext_params_dpf_config *dpf); + void prepareDpfStrength(rkisp1_ext_params_dpf_strength_config *dpfs); struct rkisp1_cif_isp_dpf_config config_; struct rkisp1_cif_isp_dpf_strength_config strengthConfig_; }; diff --git a/src/ipa/rkisp1/algorithms/filter.cpp b/src/ipa/rkisp1/algorithms/filter.cpp index 9752248a..6e278a9a 100644 --- a/src/ipa/rkisp1/algorithms/filter.cpp +++ b/src/ipa/rkisp1/algorithms/filter.cpp @@ -104,7 +104,7 @@ void Filter::queueRequest(IPAContext &context, */ void Filter::prepare([[maybe_unused]] IPAContext &context, [[maybe_unused]] const uint32_t frame, - IPAFrameContext &frameContext, rkisp1_params_cfg *params) + IPAFrameContext &frameContext, rkisp1_ext_params_block_header *hdr) { /* Check if the algorithm configuration has been updated. */ if (!frameContext.filter.update) @@ -160,7 +160,14 @@ void Filter::prepare([[maybe_unused]] IPAContext &context, uint8_t denoise = frameContext.filter.denoise; uint8_t sharpness = frameContext.filter.sharpness; - auto &flt_config = params->others.flt_config; + + struct rkisp1_ext_params_flt_config *flt = + reinterpret_cast(hdr); + auto &flt_config = flt->flt_config; + + flt->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_FLT; + flt->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + flt->header.size = sizeof(rkisp1_ext_params_flt_config); flt_config.fac_sh0 = filt_fac_sh0[sharpness]; flt_config.fac_sh1 = filt_fac_sh1[sharpness]; @@ -203,10 +210,6 @@ void Filter::prepare([[maybe_unused]] IPAContext &context, flt_config.fac_bl1 /= 2; } } - - params->module_en_update |= RKISP1_CIF_ISP_MODULE_FLT; - params->module_ens |= RKISP1_CIF_ISP_MODULE_FLT; - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_FLT; } REGISTER_IPA_ALGORITHM(Filter, "Filter") diff --git a/src/ipa/rkisp1/algorithms/filter.h b/src/ipa/rkisp1/algorithms/filter.h index d595811d..8d9a9ce1 100644 --- a/src/ipa/rkisp1/algorithms/filter.h +++ b/src/ipa/rkisp1/algorithms/filter.h @@ -26,7 +26,7 @@ public: const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; }; } /* namespace ipa::rkisp1::algorithms */ diff --git a/src/ipa/rkisp1/algorithms/gsl.cpp b/src/ipa/rkisp1/algorithms/gsl.cpp index 9b056c6e..169fada2 100644 --- a/src/ipa/rkisp1/algorithms/gsl.cpp +++ b/src/ipa/rkisp1/algorithms/gsl.cpp @@ -119,24 +119,25 @@ int GammaSensorLinearization::init([[maybe_unused]] IPAContext &context, void GammaSensorLinearization::prepare([[maybe_unused]] IPAContext &context, const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - rkisp1_params_cfg *params) + rkisp1_ext_params_block_header *hdr) { if (frame > 0) return; - params->others.sdg_config.xa_pnts.gamma_dx0 = gammaDx_[0]; - params->others.sdg_config.xa_pnts.gamma_dx1 = gammaDx_[1]; + struct rkisp1_ext_params_sdg_config *sdg = + reinterpret_cast(hdr); - std::copy(curveYr_.begin(), curveYr_.end(), - params->others.sdg_config.curve_r.gamma_y); - std::copy(curveYg_.begin(), curveYg_.end(), - params->others.sdg_config.curve_g.gamma_y); - std::copy(curveYb_.begin(), curveYb_.end(), - params->others.sdg_config.curve_b.gamma_y); + sdg->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_SDG; + sdg->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + sdg->header.size = sizeof(rkisp1_ext_params_sdg_config); - params->module_en_update |= RKISP1_CIF_ISP_MODULE_SDG; - params->module_ens |= RKISP1_CIF_ISP_MODULE_SDG; - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_SDG; + struct rkisp1_cif_isp_sdg_config &sdg_config = sdg->sdg_config; + sdg_config.xa_pnts.gamma_dx0 = gammaDx_[0]; + sdg_config.xa_pnts.gamma_dx1 = gammaDx_[1]; + + std::copy(curveYr_.begin(), curveYr_.end(), sdg_config.curve_r.gamma_y); + std::copy(curveYg_.begin(), curveYg_.end(), sdg_config.curve_g.gamma_y); + std::copy(curveYb_.begin(), curveYb_.end(), sdg_config.curve_b.gamma_y); } REGISTER_IPA_ALGORITHM(GammaSensorLinearization, "GammaSensorLinearization") diff --git a/src/ipa/rkisp1/algorithms/gsl.h b/src/ipa/rkisp1/algorithms/gsl.h index c404105e..f71add58 100644 --- a/src/ipa/rkisp1/algorithms/gsl.h +++ b/src/ipa/rkisp1/algorithms/gsl.h @@ -22,7 +22,7 @@ public: int init(IPAContext &context, const YamlObject &tuningData) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; private: uint32_t gammaDx_[2]; diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index 161183fc..3f00707b 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -185,18 +185,16 @@ int LensShadingCorrection::configure(IPAContext &context, return 0; } -void LensShadingCorrection::setParameters(rkisp1_params_cfg *params) +void LensShadingCorrection::setParameters(rkisp1_ext_params_lsc_config *lsc) { - struct rkisp1_cif_isp_lsc_config &config = params->others.lsc_config; - - memcpy(config.x_grad_tbl, xGrad_, sizeof(config.x_grad_tbl)); - memcpy(config.y_grad_tbl, yGrad_, sizeof(config.y_grad_tbl)); - memcpy(config.x_size_tbl, xSizes_, sizeof(config.x_size_tbl)); - memcpy(config.y_size_tbl, ySizes_, sizeof(config.y_size_tbl)); - - params->module_en_update |= RKISP1_CIF_ISP_MODULE_LSC; - params->module_ens |= RKISP1_CIF_ISP_MODULE_LSC; - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_LSC; + memcpy(lsc->lsc_config.x_grad_tbl, xGrad_, sizeof(lsc->lsc_config.x_grad_tbl)); + memcpy(lsc->lsc_config.y_grad_tbl, yGrad_, sizeof(lsc->lsc_config.y_grad_tbl)); + memcpy(lsc->lsc_config.x_size_tbl, xSizes_, sizeof(lsc->lsc_config.x_size_tbl)); + memcpy(lsc->lsc_config.y_size_tbl, ySizes_, sizeof(lsc->lsc_config.y_size_tbl)); + + lsc->header.type = RKISP1_EXT_PARAMS_BLOCK_TYPE_LSC; + lsc->header.enable = RKISP1_EXT_PARAMS_BLOCK_ENABLE; + lsc->header.size = sizeof(rkisp1_ext_params_lsc_config); } void LensShadingCorrection::copyTable(rkisp1_cif_isp_lsc_config &config, @@ -248,10 +246,8 @@ void LensShadingCorrection::interpolateTable(rkisp1_cif_isp_lsc_config &config, void LensShadingCorrection::prepare(IPAContext &context, const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - rkisp1_params_cfg *params) + rkisp1_ext_params_block_header *hdr) { - struct rkisp1_cif_isp_lsc_config &config = params->others.lsc_config; - /* * If there is only one set, the configuration has already been done * for first frame. @@ -259,13 +255,16 @@ void LensShadingCorrection::prepare(IPAContext &context, if (sets_.size() == 1 && frame > 0) return; + struct rkisp1_ext_params_lsc_config *lsc = + reinterpret_cast(hdr); + /* * If there is only one set, pick it. We can ignore lastCt_, as it will * never be relevant. */ if (sets_.size() == 1) { - setParameters(params); - copyTable(config, sets_.cbegin()->second); + setParameters(lsc); + copyTable(lsc->lsc_config, sets_.cbegin()->second); return; } @@ -294,13 +293,13 @@ void LensShadingCorrection::prepare(IPAContext &context, (lastCt_.adjusted <= ct && ct <= lastCt_.original)) return; - setParameters(params); + setParameters(lsc); /* * The color temperature matches exactly one of the available LSC tables. */ if (sets_.count(ct)) { - copyTable(config, sets_[ct]); + copyTable(lsc->lsc_config, sets_[ct]); lastCt_ = { ct, ct }; return; } @@ -319,7 +318,7 @@ void LensShadingCorrection::prepare(IPAContext &context, if (diff0 < threshold || diff1 < threshold) { const Components &set = diff0 < diff1 ? set0 : set1; LOG(RkISP1Lsc, Debug) << "using LSC table for " << set.ct; - copyTable(config, set); + copyTable(lsc->lsc_config, set); lastCt_ = { ct, set.ct }; return; } @@ -331,7 +330,7 @@ void LensShadingCorrection::prepare(IPAContext &context, LOG(RkISP1Lsc, Debug) << "ct is " << ct << ", interpolating between " << ct0 << " and " << ct1; - interpolateTable(config, set0, set1, ct); + interpolateTable(lsc->lsc_config, set0, set1, ct); lastCt_ = { ct, ct }; } diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h index 5baf5927..690bf267 100644 --- a/src/ipa/rkisp1/algorithms/lsc.h +++ b/src/ipa/rkisp1/algorithms/lsc.h @@ -25,7 +25,7 @@ public: int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; + rkisp1_ext_params_block_header *hdr) override; private: struct Components { @@ -36,7 +36,7 @@ private: std::vector b; }; - void setParameters(rkisp1_params_cfg *params); + void setParameters(rkisp1_ext_params_lsc_config *lsc); void copyTable(rkisp1_cif_isp_lsc_config &config, const Components &set0); void interpolateTable(rkisp1_cif_isp_lsc_config &config, const Components &set0, const Components &set1, diff --git a/src/ipa/rkisp1/module.h b/src/ipa/rkisp1/module.h index 16c3e43e..89d5338b 100644 --- a/src/ipa/rkisp1/module.h +++ b/src/ipa/rkisp1/module.h @@ -20,7 +20,7 @@ namespace libcamera { namespace ipa::rkisp1 { using Module = ipa::Module; + rkisp1_ext_params_block_header, rkisp1_stat_buffer>; } /* namespace ipa::rkisp1 */ diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 6687c91e..05e5ed26 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -325,16 +325,40 @@ void IPARkISP1::queueRequest(const uint32_t frame, const ControlList &controls) void IPARkISP1::fillParamsBuffer(const uint32_t frame, const uint32_t bufferId) { IPAFrameContext &frameContext = context_.frameContexts.get(frame); + rkisp1_ext_params_block_header *block; + size_t totalSize = 0; - rkisp1_params_cfg *params = - reinterpret_cast( - mappedBuffers_.at(bufferId).planes()[0].data()); + rkisp1_ext_params_cfg *params = + reinterpret_cast( + mappedBuffers_.at(bufferId).planes()[0].data()); /* Prepare parameters buffer. */ memset(params, 0, sizeof(*params)); - for (auto const &algo : algorithms()) - algo->prepare(context_, frame, frameContext, params); + params->version = RKISP1_EXT_PARAM_BUFFER_V1; + + block = reinterpret_cast(params->data); + for (auto const &algo : algorithms()) { + + algo->prepare(context_, frame, frameContext, block); + + /* + * Each algorithm could add multiple parameter blocks, each of + * which will have its own embedded header struct with the size + * of that block. We need to iterate through them, sum all of + * the block sizes and advance the 'block' pointer to the next + * empty one. + */ + while (totalSize < RKISP1_EXT_PARAMS_MAX_SIZE && block->size) { + totalSize += block->size; + block = reinterpret_cast + (params->data + totalSize); + } + + ASSERT(totalSize <= RKISP1_EXT_PARAMS_MAX_SIZE); + } + + params->total_size = totalSize; paramsBufferReady.emit(frame); } diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 4cbf105d..1ec210e4 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -800,7 +800,7 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) } V4L2DeviceFormat paramFormat; - paramFormat.fourcc = V4L2PixelFormat(V4L2_META_FMT_RK_ISP1_PARAMS); + paramFormat.fourcc = V4L2PixelFormat(V4L2_META_FMT_RK_ISP1_EXT_PARAMS); ret = param_->setFormat(¶mFormat); if (ret) return ret; -- cgit v1.2.1