diff options
author | Kieran Bingham <kieran.bingham@ideasonboard.com> | 2021-05-10 23:18:59 +0530 |
---|---|---|
committer | Umang Jain <umang.jain@ideasonboard.com> | 2021-06-28 17:54:08 +0530 |
commit | 809edb381ccdd367e2b425dd5f186322968de015 (patch) | |
tree | 01ecea298616a12e21f33cc3867fb044958daf3a /aic | |
parent | c1c0f554051200ea051e5e31ee286e5f5e83c744 (diff) |
aic: Add IPU3 parameter encoder
The Parameter Encoder is imported from the ChromeOS implementation, with
some small changes to fit style and support building independantly.
The parameter encoders have assertions in them to check that the
required input data is valid. ispAwbFrEncode() is currently disabled
due to failing assertions around grid widths.
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
Diffstat (limited to 'aic')
-rw-r--r-- | aic/kbl_aic.h | 22 | ||||
-rw-r--r-- | aic/meson.build | 5 | ||||
-rw-r--r-- | aic/parameter_encoder.cpp | 1253 | ||||
-rw-r--r-- | aic/parameter_encoder.h | 28 |
4 files changed, 1308 insertions, 0 deletions
diff --git a/aic/kbl_aic.h b/aic/kbl_aic.h new file mode 100644 index 0000000..acefd5f --- /dev/null +++ b/aic/kbl_aic.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Wrapper to be able to include KBL_AIC implementation without reducing our + * compiler warnings and error levels on our own code. + */ + +#ifndef IPA_IPU3_AIC_KBL_AIC_H +#define IPA_IPU3_AIC_KBL_AIC_H + +/* + * Bring in AIC headers with compiler warnings disabled on those includes. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#pragma GCC diagnostic ignored "-Wextra-semi" + +#include <ia_imaging/KBL_AIC.h> + +#pragma GCC diagnostic pop + +#endif /* IPA_IPU3_AIC_H */ diff --git a/aic/meson.build b/aic/meson.build new file mode 100644 index 0000000..c3a8201 --- /dev/null +++ b/aic/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: CC0-1.0 + +ipu3_ipa_files += files([ + 'parameter_encoder.cpp', +]) diff --git a/aic/parameter_encoder.cpp b/aic/parameter_encoder.cpp new file mode 100644 index 0000000..a3ca310 --- /dev/null +++ b/aic/parameter_encoder.cpp @@ -0,0 +1,1253 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (C) 2017 Intel Corporation. + * + * ParameterEncoder.cpp: Encode AIC parameters to IPU3 kernel interface + * + * This implementation is highly derived from ChromeOS: + * platform2/camera/hal/intel/ipu3/psl/ipu3/workers/IPU3AicToFwEncoder.cpp + */ + +#include "parameter_encoder.h" + +#include <algorithm> +#include <assert.h> +#include <string.h> + +namespace libcamera::ipa::ipu3::aic { + +/* Auto White Balance */ +#define AWB_FR_MAX_GRID_CELLS_IN_ONE_SET 32 +#define AWB_FR_GRID_DIM_MASK 0x3F + +/* Auto Exposure */ +#define AE_NUM_OF_WEIGHT_ELEMS 96 + +/* Auto Focus */ +#define AF_MAX_GRID_CELLS_IN_ONE_SET 32 + +/* Linearization Vmem */ +#define SH_CSS_BAYER_BITS 11 +#define LIN_MAX_VALUE (1 << SH_CSS_BAYER_BITS) + +/* Bayer Shading Correction */ +#define SHD_MAX_CELLS_PER_SET 146 +#define SHD_MAX_CFG_SETS IPU3_UAPI_SHD_MAX_CFG_SETS + +/* Iefd */ +#define XY_2_RESET_MASK ((1 << 24) - 1) + +/* Chroma Noise Reduction */ +#define DALPHA_MAX 256 + +/* Advanced Noise reduction */ +#define SQRT_LUT \ + { \ + 724, 768, 810, 849, 887, \ + 923, 958, 991, 1024, 1056, \ + 1086, 1116, 1145, 1173, 1201, \ + 1228, 1254, 1280, 1305, 1330, \ + 1355, 1379, 1402, 1425, 1448 \ + } +#define X_SQR_RESET_MAX (0xffffff) +#define Y_SQR_RESET_MAX X_SQR_RESET_MAX +#define R_NORM_FACTOR_MAX (0x1f) +#define RAD_GAIN_SCALE_FACTOR (0xff) +#define COLOR_REG_W_MASK 0xfff +#define COLOR_BETA_MASK 0x7ff +#define COLOR_ALPHA_MASK 0x1ff + +/* Extreme Noise Reduction version 3 */ +#define XNR_FILTER_SIZE 9 +#define ISP_VEC_ELEMBITS 12 +#define IA_CSS_XNR3_SIGMA_SCALE (1 << 10) +#define XNR_ALPHA_SCALE_LOG2 5 +#define XNR_CORING_SCALE_LOG2 (ISP_VEC_ELEMBITS - 1) +#define XNR_BLENDING_SCALE_LOG2 (ISP_VEC_ELEMBITS - 1) +#define XNR_MIN_SIGMA (IA_CSS_XNR3_SIGMA_SCALE / 100) +#define XNR_MAX_ALPHA ((1 << (ISP_VEC_ELEMBITS - 1)) - 1) +#define XNR_ALPHA_SCALE_FACTOR (1 << XNR_ALPHA_SCALE_LOG2) +#define XNR_CORING_SCALE_FACTOR (1 << XNR_CORING_SCALE_LOG2) +#define XNR_BLENDING_SCALE_FACTOR (1 << XNR_BLENDING_SCALE_LOG2) + +/* Extreme Noise Reduction version 3 Vmem */ +#define ISP_VEC_NELEMS 64 +#define XNR3_LOOK_UP_TABLE_POINTS 16 + +static const int16_t x[XNR3_LOOK_UP_TABLE_POINTS] = { + 1024, 1164, 1320, 1492, 1680, 1884, 2108, 2352, + 2616, 2900, 3208, 3540, 3896, 4276, 4684, 5120 +}; + +static const int16_t a[XNR3_LOOK_UP_TABLE_POINTS] = { + -7213, -5580, -4371, -3421, -2722, -2159, -6950, -5585, + -4529, -3697, -3010, -2485, -2070, -1727, -1428, 0 +}; + +static const int16_t b[XNR3_LOOK_UP_TABLE_POINTS] = { + 4096, 3603, 3178, 2811, 2497, 2226, 1990, 1783, + 1603, 1446, 1307, 1185, 1077, 981, 895, 819 +}; + +static const int16_t c[XNR3_LOOK_UP_TABLE_POINTS] = { + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* Temporal Noise Reduction v3 */ +#define TNR3_NUM_POINTS (TNR3_NUM_SEGMENTS + 1) +#define TNR3_KNEE_POINTS (TNR3_NUM_SEGMENTS - 1) +#define TNR3_ISP_SCALE (1 << (ISP_VEC_ELEMBITS - 1)) +#define TNR3_RND_OFFSET (TNR3_ISP_SCALE >> 1) +#define TNR3_MAX_VALUE (TNR3_ISP_SCALE - 1) +#define TNR3_MIN_VALUE -(TNR3_ISP_SCALE) +#define HOST_SCALING 0 + +/* Imported directly from CommonUtilMacros.h */ +#ifndef MEMCPY_S +#define MEMCPY_S(dest, dmax, src, smax) memcpy((dest), (src), std::min((size_t)(dmax), (size_t)(smax))) +#endif +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define CLEAR(x) memset(&(x), 0, sizeof(x)) +#define clamp(a, min_val, max_val) MIN(MAX((a), (min_val)), (max_val)) + +/* AWB Filter Response */ +static void ispAwbFrEncode(aic_config *config, ipu3_uapi_params *params) +{ + unsigned int coeff_sum = 0, nf_val = 1; + + params->acc_param.awb_fr.bayer_coeff[0] = config->awb_fr_2500_config.awb_fr.bayer_coeffs.A1; + params->acc_param.awb_fr.bayer_coeff[1] = config->awb_fr_2500_config.awb_fr.bayer_coeffs.A2; + params->acc_param.awb_fr.bayer_coeff[2] = config->awb_fr_2500_config.awb_fr.bayer_coeffs.A3; + params->acc_param.awb_fr.bayer_coeff[3] = config->awb_fr_2500_config.awb_fr.bayer_coeffs.A4; + params->acc_param.awb_fr.bayer_coeff[4] = config->awb_fr_2500_config.awb_fr.bayer_coeffs.A5; + params->acc_param.awb_fr.bayer_coeff[5] = config->awb_fr_2500_config.awb_fr.bayer_coeffs.A6; + params->acc_param.awb_fr.bayer_sign = config->awb_fr_2500_config.awb_fr.bayer_coeffs.sign_vec; + + coeff_sum += config->awb_fr_2500_config.awb_fr.bayer_coeffs.A1; + coeff_sum += config->awb_fr_2500_config.awb_fr.bayer_coeffs.A2; + coeff_sum += config->awb_fr_2500_config.awb_fr.bayer_coeffs.A3; + coeff_sum += config->awb_fr_2500_config.awb_fr.bayer_coeffs.A4; + coeff_sum += config->awb_fr_2500_config.awb_fr.bayer_coeffs.A5; + coeff_sum += config->awb_fr_2500_config.awb_fr.bayer_coeffs.A6; + + while (coeff_sum >> nf_val) { + ++nf_val; + } + + --nf_val; + + if (nf_val < 7 || nf_val > 12) + params->acc_param.awb_fr.bayer_nf = 7; + else + params->acc_param.awb_fr.bayer_nf = nf_val; + + params->acc_param.awb_fr.grid_cfg.width = config->awb_fr_2500_config.awb_fr.grid.grid_width & AWB_FR_GRID_DIM_MASK; + params->acc_param.awb_fr.grid_cfg.height = config->awb_fr_2500_config.awb_fr.grid.grid_height & AWB_FR_GRID_DIM_MASK; + params->acc_param.awb_fr.grid_cfg.block_width_log2 = config->awb_fr_2500_config.awb_fr.grid.block_width & 0x7; + params->acc_param.awb_fr.grid_cfg.block_height_log2 = config->awb_fr_2500_config.awb_fr.grid.block_height & 0x7; + + assert(config->awb_fr_2500_config.awb_fr.grid.grid_width); + params->acc_param.awb_fr.grid_cfg.height_per_slice = + (unsigned char)(AWB_FR_MAX_GRID_CELLS_IN_ONE_SET / config->awb_fr_2500_config.awb_fr.grid.grid_width); + params->acc_param.awb_fr.grid_cfg.x_start = config->awb_fr_2500_config.awb_fr.grid.x_start & 0xFFF; + params->acc_param.awb_fr.grid_cfg.y_start = (config->awb_fr_2500_config.awb_fr.grid.y_start & 0xFFF) | IPU3_UAPI_GRID_Y_START_EN; + + params->use.acc_awb_fr = 1; +} + +/* Auto Exposure */ +static void ispAeEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.ae.grid_cfg.ae_en = 1; + + params->acc_param.ae.grid_cfg.block_height_log2 = config->ae_2500_config.ae.ae_grid_config.block_height; + params->acc_param.ae.grid_cfg.block_width_log2 = config->ae_2500_config.ae.ae_grid_config.block_width; + params->acc_param.ae.grid_cfg.width = config->ae_2500_config.ae.ae_grid_config.grid_width; + params->acc_param.ae.grid_cfg.height = config->ae_2500_config.ae.ae_grid_config.grid_height; + params->acc_param.ae.grid_cfg.x_start = config->ae_2500_config.ae.ae_grid_config.x_start; + params->acc_param.ae.grid_cfg.y_start = config->ae_2500_config.ae.ae_grid_config.y_start; + + for (int elem_index = 0; elem_index < AE_NUM_OF_WEIGHT_ELEMS; elem_index++) { + params->acc_param.ae.weights[elem_index].cell0 = config->ae_2500_config.ae.ae_weights.val[8 * elem_index]; + params->acc_param.ae.weights[elem_index].cell1 = config->ae_2500_config.ae.ae_weights.val[8 * elem_index + 1]; + params->acc_param.ae.weights[elem_index].cell2 = config->ae_2500_config.ae.ae_weights.val[8 * elem_index + 2]; + params->acc_param.ae.weights[elem_index].cell3 = config->ae_2500_config.ae.ae_weights.val[8 * elem_index + 3]; + params->acc_param.ae.weights[elem_index].cell4 = config->ae_2500_config.ae.ae_weights.val[8 * elem_index + 4]; + params->acc_param.ae.weights[elem_index].cell5 = config->ae_2500_config.ae.ae_weights.val[8 * elem_index + 5]; + params->acc_param.ae.weights[elem_index].cell6 = config->ae_2500_config.ae.ae_weights.val[8 * elem_index + 6]; + params->acc_param.ae.weights[elem_index].cell7 = config->ae_2500_config.ae.ae_weights.val[8 * elem_index + 7]; + } + + params->acc_param.ae.ae_ccm.gain_gr = config->ae_2500_config.ae.ae_ccm.wb_coeffs.gain_GR; + params->acc_param.ae.ae_ccm.gain_r = config->ae_2500_config.ae.ae_ccm.wb_coeffs.gain_R; + params->acc_param.ae.ae_ccm.gain_b = config->ae_2500_config.ae.ae_ccm.wb_coeffs.gain_B; + params->acc_param.ae.ae_ccm.gain_gb = config->ae_2500_config.ae.ae_ccm.wb_coeffs.gain_GB; + + MEMCPY_S(params->acc_param.ae.ae_ccm.mat, sizeof(params->acc_param.ae.ae_ccm.mat), + config->ae_2500_config.ae.ae_ccm.mat_coeffs.coeffs, sizeof(config->ae_2500_config.ae.ae_ccm.mat_coeffs.coeffs)); + + params->use.acc_ae = 1; +} + +/* Auto White Balance */ +static void ispAwbEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.awb.config.grid.block_height_log2 = (__u16)config->awb_2500_config.awb.grid.grid_block_height; + params->acc_param.awb.config.grid.block_width_log2 = (__u16)config->awb_2500_config.awb.grid.grid_block_width; + params->acc_param.awb.config.grid.height = config->awb_2500_config.awb.grid.grid_height; + params->acc_param.awb.config.grid.width = config->awb_2500_config.awb.grid.grid_width; + params->acc_param.awb.config.grid.x_start = config->awb_2500_config.awb.grid.grid_x_start; + params->acc_param.awb.config.grid.y_start = config->awb_2500_config.awb.grid.grid_y_start; + + params->acc_param.awb.config.rgbs_thr_b = config->awb_2500_config.awb.rgbs_B_threshold | IPU3_UAPI_AWB_RGBS_THR_B_EN | IPU3_UAPI_AWB_RGBS_THR_B_INCL_SAT; + params->acc_param.awb.config.rgbs_thr_gb = config->awb_2500_config.awb.rgbs_Gb_threshold; + params->acc_param.awb.config.rgbs_thr_gr = config->awb_2500_config.awb.rgbs_Gr_threshold; + params->acc_param.awb.config.rgbs_thr_r = config->awb_2500_config.awb.rgbs_R_threshold; + + params->use.acc_awb = 1; +} + +/* Auto Focus */ +static void ispAfEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.af.filter_config.y1_coeff_0.a1 = config->af_2500_config.af.y1_coeffs.A1; + params->acc_param.af.filter_config.y1_coeff_0.a2 = config->af_2500_config.af.y1_coeffs.A2; + params->acc_param.af.filter_config.y1_coeff_0.a3 = config->af_2500_config.af.y1_coeffs.A3; + params->acc_param.af.filter_config.y1_coeff_0.a4 = config->af_2500_config.af.y1_coeffs.A4; + params->acc_param.af.filter_config.y1_coeff_1.a5 = config->af_2500_config.af.y1_coeffs.A5; + params->acc_param.af.filter_config.y1_coeff_1.a6 = config->af_2500_config.af.y1_coeffs.A6; + params->acc_param.af.filter_config.y1_coeff_1.a7 = config->af_2500_config.af.y1_coeffs.A7; + params->acc_param.af.filter_config.y1_coeff_1.a8 = config->af_2500_config.af.y1_coeffs.A8; + params->acc_param.af.filter_config.y1_coeff_2.a9 = config->af_2500_config.af.y1_coeffs.A9; + params->acc_param.af.filter_config.y1_coeff_2.a10 = config->af_2500_config.af.y1_coeffs.A10; + params->acc_param.af.filter_config.y1_coeff_2.a11 = config->af_2500_config.af.y1_coeffs.A11; + params->acc_param.af.filter_config.y1_coeff_2.a12 = config->af_2500_config.af.y1_coeffs.A12; + params->acc_param.af.filter_config.y1_sign_vec = config->af_2500_config.af.y1_coeffs.sign_vec; + + params->acc_param.af.filter_config.y2_coeff_0.a1 = config->af_2500_config.af.y2_coeffs.A1; + params->acc_param.af.filter_config.y2_coeff_0.a2 = config->af_2500_config.af.y2_coeffs.A2; + params->acc_param.af.filter_config.y2_coeff_0.a3 = config->af_2500_config.af.y2_coeffs.A3; + params->acc_param.af.filter_config.y2_coeff_0.a4 = config->af_2500_config.af.y2_coeffs.A4; + params->acc_param.af.filter_config.y2_coeff_1.a5 = config->af_2500_config.af.y2_coeffs.A5; + params->acc_param.af.filter_config.y2_coeff_1.a6 = config->af_2500_config.af.y2_coeffs.A6; + params->acc_param.af.filter_config.y2_coeff_1.a7 = config->af_2500_config.af.y2_coeffs.A7; + params->acc_param.af.filter_config.y2_coeff_1.a8 = config->af_2500_config.af.y2_coeffs.A8; + params->acc_param.af.filter_config.y2_coeff_2.a9 = config->af_2500_config.af.y2_coeffs.A9; + params->acc_param.af.filter_config.y2_coeff_2.a10 = config->af_2500_config.af.y2_coeffs.A10; + params->acc_param.af.filter_config.y2_coeff_2.a11 = config->af_2500_config.af.y2_coeffs.A11; + params->acc_param.af.filter_config.y2_coeff_2.a12 = config->af_2500_config.af.y2_coeffs.A12; + params->acc_param.af.filter_config.y2_sign_vec = config->af_2500_config.af.y2_coeffs.sign_vec; + + params->acc_param.af.filter_config.y_calc.y_gen_rate_gr = config->af_2500_config.af.y_calc.y_gen_rate_gr; + params->acc_param.af.filter_config.y_calc.y_gen_rate_r = config->af_2500_config.af.y_calc.y_gen_rate_r; + params->acc_param.af.filter_config.y_calc.y_gen_rate_b = config->af_2500_config.af.y_calc.y_gen_rate_b; + params->acc_param.af.filter_config.y_calc.y_gen_rate_gb = config->af_2500_config.af.y_calc.y_gen_rate_gb; + + params->acc_param.af.filter_config.nf.y1_nf = config->af_2500_config.af.nf.y1_nf; + params->acc_param.af.filter_config.nf.y2_nf = config->af_2500_config.af.nf.y2_nf; + + params->acc_param.af.grid_cfg.width = config->af_2500_config.af.grid.grid_width; + params->acc_param.af.grid_cfg.height = config->af_2500_config.af.grid.grid_height; + params->acc_param.af.grid_cfg.block_width_log2 = config->af_2500_config.af.grid.block_width; + params->acc_param.af.grid_cfg.block_height_log2 = config->af_2500_config.af.grid.block_height; + + assert(config->af_2500_config.af.grid.grid_width); + params->acc_param.af.grid_cfg.height_per_slice = + (unsigned char)(AF_MAX_GRID_CELLS_IN_ONE_SET / config->af_2500_config.af.grid.grid_width); + params->acc_param.af.grid_cfg.x_start = config->af_2500_config.af.grid.x_start; + params->acc_param.af.grid_cfg.y_start = config->af_2500_config.af.grid.y_start | IPU3_UAPI_GRID_Y_START_EN; + + params->use.acc_af = 1; +} + +/* Linearization parameters */ +static void ispLinVmemEncode(aic_config *config, ipu3_uapi_params *params) +{ + for (unsigned int i = 0; i < LIN_SEGMENTS; i++) { + params->lin_vmem_params.lin_lutlow_gr[i] = MIN(LIN_MAX_VALUE - 1, config->lin_2500_config.curve_lut_GR[i]); + params->lin_vmem_params.lin_lutlow_r[i] = MIN(LIN_MAX_VALUE - 1, config->lin_2500_config.curve_lut_R[i]); + params->lin_vmem_params.lin_lutlow_b[i] = MIN(LIN_MAX_VALUE - 1, config->lin_2500_config.curve_lut_B[i]); + params->lin_vmem_params.lin_lutlow_gb[i] = MIN(LIN_MAX_VALUE - 1, config->lin_2500_config.curve_lut_GB[i]); + + params->lin_vmem_params.lin_lutdif_gr[i] = config->lin_2500_config.curve_lut_GR[i + 1] - config->lin_2500_config.curve_lut_GR[i]; + params->lin_vmem_params.lin_lutdif_r[i] = config->lin_2500_config.curve_lut_R[i + 1] - config->lin_2500_config.curve_lut_R[i]; + params->lin_vmem_params.lin_lutdif_b[i] = config->lin_2500_config.curve_lut_B[i + 1] - config->lin_2500_config.curve_lut_B[i]; + params->lin_vmem_params.lin_lutdif_gb[i] = config->lin_2500_config.curve_lut_GB[i + 1] - config->lin_2500_config.curve_lut_GB[i]; + } + + params->use.lin_vmem_params = 1; +} + +/* Gamma configuration */ +static void ispGammaCtrlEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.gamma.gc_ctrl.enable = config->rgbpp_2500_config.gamma.enable; + MEMCPY_S(params->acc_param.gamma.gc_lut.lut, sizeof(params->acc_param.gamma.gc_lut.lut), + config->rgbpp_2500_config.gamma.lut_entries, sizeof(config->rgbpp_2500_config.gamma.lut_entries)); + + params->use.acc_gamma = 1; +} + +/* Color correction matrix */ +static void ispCcmEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.ccm.coeff_m11 = config->rgbpp_2500_config.ccm.matrix_coeffs.m11; + params->acc_param.ccm.coeff_m12 = config->rgbpp_2500_config.ccm.matrix_coeffs.m12; + params->acc_param.ccm.coeff_m13 = config->rgbpp_2500_config.ccm.matrix_coeffs.m13; + params->acc_param.ccm.coeff_o_r = config->rgbpp_2500_config.ccm.offsets.R; + params->acc_param.ccm.coeff_m21 = config->rgbpp_2500_config.ccm.matrix_coeffs.m21; + params->acc_param.ccm.coeff_m22 = config->rgbpp_2500_config.ccm.matrix_coeffs.m22; + params->acc_param.ccm.coeff_m23 = config->rgbpp_2500_config.ccm.matrix_coeffs.m23; + params->acc_param.ccm.coeff_o_g = config->rgbpp_2500_config.ccm.offsets.G; + params->acc_param.ccm.coeff_m31 = config->rgbpp_2500_config.ccm.matrix_coeffs.m31; + params->acc_param.ccm.coeff_m32 = config->rgbpp_2500_config.ccm.matrix_coeffs.m32; + params->acc_param.ccm.coeff_m33 = config->rgbpp_2500_config.ccm.matrix_coeffs.m33; + params->acc_param.ccm.coeff_o_b = config->rgbpp_2500_config.ccm.offsets.B; + + params->use.acc_ccm = 1; +} + +/* Color Space Conversion Matrix */ +static void ispCscEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.csc.coeff_c11 = config->rgbpp_2500_config.csc.mat.c11; + params->acc_param.csc.coeff_c12 = config->rgbpp_2500_config.csc.mat.c12; + params->acc_param.csc.coeff_c13 = config->rgbpp_2500_config.csc.mat.c13; + params->acc_param.csc.coeff_b1 = config->rgbpp_2500_config.csc.offset.b1; + params->acc_param.csc.coeff_c21 = config->rgbpp_2500_config.csc.mat.c21; + params->acc_param.csc.coeff_c22 = config->rgbpp_2500_config.csc.mat.c22; + params->acc_param.csc.coeff_c23 = config->rgbpp_2500_config.csc.mat.c23; + params->acc_param.csc.coeff_b2 = config->rgbpp_2500_config.csc.offset.b2; + params->acc_param.csc.coeff_c31 = config->rgbpp_2500_config.csc.mat.c31; + params->acc_param.csc.coeff_c32 = config->rgbpp_2500_config.csc.mat.c32; + params->acc_param.csc.coeff_c33 = config->rgbpp_2500_config.csc.mat.c33; + params->acc_param.csc.coeff_b3 = config->rgbpp_2500_config.csc.offset.b3; + + params->use.acc_csc = 1; +} + +/* Color Down Sample */ +static void ispCdsEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.cds.ds_c00 = (__u32)config->rgbpp_2500_config.cds.coeffs.c00; + params->acc_param.cds.ds_c01 = (__u32)config->rgbpp_2500_config.cds.coeffs.c01; + params->acc_param.cds.ds_c02 = (__u32)config->rgbpp_2500_config.cds.coeffs.c02; + params->acc_param.cds.ds_c03 = (__u32)config->rgbpp_2500_config.cds.coeffs.c03; + params->acc_param.cds.ds_c10 = (__u32)config->rgbpp_2500_config.cds.coeffs.c10; + params->acc_param.cds.ds_c11 = (__u32)config->rgbpp_2500_config.cds.coeffs.c11; + params->acc_param.cds.ds_c12 = (__u32)config->rgbpp_2500_config.cds.coeffs.c12; + params->acc_param.cds.ds_c13 = (__u32)config->rgbpp_2500_config.cds.coeffs.c13; + params->acc_param.cds.ds_nf = (__u32)config->rgbpp_2500_config.cds.nf; + + params->acc_param.cds.uv_bin_output = 0; + params->acc_param.cds.csc_en = 1; + + params->use.acc_cds = 1; +} + +/* De-mosaic */ +static void ispDmEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.dm.dm_en = 1; + params->acc_param.dm.ch_ar_en = config->dm_2500_config.dm.ch_ar_en; + params->acc_param.dm.fcc_en = config->dm_2500_config.dm.fcc_en; + params->acc_param.dm.gamma_sc = config->dm_2500_config.dm.gamma_sc; + params->acc_param.dm.lc_ctrl = config->dm_2500_config.dm.lc_ctrl; + params->acc_param.dm.cr_param1 = config->dm_2500_config.dm.cr_param1; + params->acc_param.dm.cr_param2 = config->dm_2500_config.dm.cr_param2; + params->acc_param.dm.coring_param = config->dm_2500_config.dm.coring_param; + + params->use.acc_dm = 1; +} + +/* Lens shading correction */ +static void ispShdEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.shd.shd.grid.width = config->shd_2500_config.shd.grid.grid_width; + params->acc_param.shd.shd.grid.height = config->shd_2500_config.shd.grid.grid_height; + params->acc_param.shd.shd.grid.block_width_log2 = config->shd_2500_config.shd.grid.block_width; + params->acc_param.shd.shd.grid.block_height_log2 = config->shd_2500_config.shd.grid.block_height; + + assert(config->shd_2500_config.shd.grid.grid_width); + params->acc_param.shd.shd.grid.grid_height_per_slice = + (unsigned char)(SHD_MAX_CELLS_PER_SET / config->shd_2500_config.shd.grid.grid_width); + params->acc_param.shd.shd.grid.x_start = config->shd_2500_config.shd.grid.x_start; + params->acc_param.shd.shd.grid.y_start = config->shd_2500_config.shd.grid.y_start; + + params->acc_param.shd.shd.general.shd_enable = config->shd_2500_config.shd.general.shd_enable; + params->acc_param.shd.shd.general.gain_factor = config->shd_2500_config.shd.general.gain_factor; + params->acc_param.shd.shd.general.init_set_vrt_offst_ul = + (-(signed int)config->shd_2500_config.shd.grid.y_start >> (signed int)config->shd_2500_config.shd.grid.block_height) % (signed int)params->acc_param.shd.shd.grid.grid_height_per_slice; + + params->acc_param.shd.shd.black_level.bl_r = config->shd_2500_config.shd.black_level.bl_R; + params->acc_param.shd.shd.black_level.bl_gr = config->shd_2500_config.shd.black_level.bl_Gr | (config->shd_2500_config.shd.black_level.normalization_shift << IPU3_UAPI_SHD_BLGR_NF_SHIFT); + params->acc_param.shd.shd.black_level.bl_gb = config->shd_2500_config.shd.black_level.bl_Gb; + params->acc_param.shd.shd.black_level.bl_b = config->shd_2500_config.shd.black_level.bl_B; + + unsigned int set_grid_limit = + config->shd_2500_config.shd.grid.grid_width * params->acc_param.shd.shd.grid.grid_height_per_slice; + unsigned int public_grid_limit = + config->shd_2500_config.shd.grid.grid_width * config->shd_2500_config.shd.grid.grid_height; + unsigned int set_index, set_grid_index, public_grid_index = 0; + + for (set_index = 0; set_index < SHD_MAX_CFG_SETS; set_index++) { + for (set_grid_index = 0; + set_grid_index < set_grid_limit && public_grid_index < public_grid_limit; + set_grid_index++, public_grid_index++) { + params->acc_param.shd.shd_lut.sets[set_index].r_and_gr[set_grid_index].r = + config->shd_2500_config.shd.luts.R[public_grid_index]; + params->acc_param.shd.shd_lut.sets[set_index].r_and_gr[set_grid_index].gr = + config->shd_2500_config.shd.luts.Gr[public_grid_index]; + params->acc_param.shd.shd_lut.sets[set_index].gb_and_b[set_grid_index].gb = + config->shd_2500_config.shd.luts.Gb[public_grid_index]; + params->acc_param.shd.shd_lut.sets[set_index].gb_and_b[set_grid_index].b = + config->shd_2500_config.shd.luts.B[public_grid_index]; + } + } + + params->use.acc_shd = 1; +} + +/* Image Enhancement Filter and Denoise */ +static void ispIefdEncode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->acc_param.iefd); + + params->acc_param.iefd.control.iefd_en = config->yuvp1_c0_2500_config.iefd.control.iefd_en ? 1 : 0; + params->acc_param.iefd.control.rad_en = config->yuvp1_c0_2500_config.iefd.control.iefd_radial_en ? 1 : 0; + params->acc_param.iefd.control.denoise_en = config->yuvp1_c0_2500_config.iefd.control.iefd_denoise_en ? 1 : 0; + params->acc_param.iefd.control.direct_smooth_en = config->yuvp1_c0_2500_config.iefd.control.iefd_dir_en ? 1 : 0; + + params->acc_param.iefd.control.vssnlm_en = 1; + + params->acc_param.iefd.units.cu_1.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_1.x[0]; + params->acc_param.iefd.units.cu_1.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_1.x[1]; + params->acc_param.iefd.units.cu_1.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_1.a[0]; + params->acc_param.iefd.units.cu_1.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_1.b[0]; + + params->acc_param.iefd.units.cu_ed.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.x[0]; + params->acc_param.iefd.units.cu_ed.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.x[1]; + params->acc_param.iefd.units.cu_ed.x2 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.x[2]; + params->acc_param.iefd.units.cu_ed.x3 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.x[3]; + params->acc_param.iefd.units.cu_ed.x4 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.x[4]; + params->acc_param.iefd.units.cu_ed.x5 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.x[5]; + + params->acc_param.iefd.units.cu_ed.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.a[0]; + params->acc_param.iefd.units.cu_ed.a12 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.a[1]; + params->acc_param.iefd.units.cu_ed.a23 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.a[2]; + params->acc_param.iefd.units.cu_ed.a34 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.a[3]; + params->acc_param.iefd.units.cu_ed.a45 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.a[4]; + + params->acc_param.iefd.units.cu_ed.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.b[0]; + params->acc_param.iefd.units.cu_ed.b12 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.b[1]; + params->acc_param.iefd.units.cu_ed.b23 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.b[2]; + params->acc_param.iefd.units.cu_ed.b34 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.b[3]; + params->acc_param.iefd.units.cu_ed.b45 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_ed.b[4]; + + params->acc_param.iefd.units.cu_3.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_3.x[0]; + params->acc_param.iefd.units.cu_3.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_3.x[1]; + params->acc_param.iefd.units.cu_3.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_3.a[0]; + params->acc_param.iefd.units.cu_3.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_3.b[0]; + + params->acc_param.iefd.units.cu_5.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_5.x[0]; + params->acc_param.iefd.units.cu_5.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_5.x[1]; + params->acc_param.iefd.units.cu_5.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_5.a[0]; + params->acc_param.iefd.units.cu_5.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_5.b[0]; + + params->acc_param.iefd.units.cu_6.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.x[0]; + params->acc_param.iefd.units.cu_6.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.x[1]; + params->acc_param.iefd.units.cu_6.x2 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.x[2]; + params->acc_param.iefd.units.cu_6.x3 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.x[3]; + params->acc_param.iefd.units.cu_6.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.a[0]; + params->acc_param.iefd.units.cu_6.a12 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.a[1]; + params->acc_param.iefd.units.cu_6.a23 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.a[2]; + params->acc_param.iefd.units.cu_6.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.b[0]; + params->acc_param.iefd.units.cu_6.b12 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.b[1]; + params->acc_param.iefd.units.cu_6.b23 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_6.b[2]; + + params->acc_param.iefd.units.cu_7.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_7.x[0]; + params->acc_param.iefd.units.cu_7.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_7.x[1]; + params->acc_param.iefd.units.cu_7.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_7.a[0]; + params->acc_param.iefd.units.cu_7.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_7.b[0]; + + params->acc_param.iefd.units.cu_unsharp.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.x[0]; + params->acc_param.iefd.units.cu_unsharp.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.x[1]; + params->acc_param.iefd.units.cu_unsharp.x2 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.x[2]; + params->acc_param.iefd.units.cu_unsharp.x3 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.x[3]; + params->acc_param.iefd.units.cu_unsharp.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.a[0]; + params->acc_param.iefd.units.cu_unsharp.a12 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.a[1]; + params->acc_param.iefd.units.cu_unsharp.a23 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.a[2]; + params->acc_param.iefd.units.cu_unsharp.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.b[0]; + params->acc_param.iefd.units.cu_unsharp.b12 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.b[1]; + params->acc_param.iefd.units.cu_unsharp.b23 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_unsharp.b[2]; + + params->acc_param.iefd.units.cu_radial.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.x[0]; + params->acc_param.iefd.units.cu_radial.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.x[1]; + params->acc_param.iefd.units.cu_radial.x2 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.x[2]; + params->acc_param.iefd.units.cu_radial.x3 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.x[3]; + params->acc_param.iefd.units.cu_radial.x4 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.x[4]; + params->acc_param.iefd.units.cu_radial.x5 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.x[5]; + params->acc_param.iefd.units.cu_radial.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.a[0]; + params->acc_param.iefd.units.cu_radial.a12 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.a[1]; + params->acc_param.iefd.units.cu_radial.a23 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.a[2]; + params->acc_param.iefd.units.cu_radial.a34 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.a[3]; + params->acc_param.iefd.units.cu_radial.a45 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.a[4]; + params->acc_param.iefd.units.cu_radial.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.b[0]; + params->acc_param.iefd.units.cu_radial.b12 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.b[1]; + params->acc_param.iefd.units.cu_radial.b23 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.b[2]; + params->acc_param.iefd.units.cu_radial.b34 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.b[3]; + params->acc_param.iefd.units.cu_radial.b45 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_radial.b[4]; + + params->acc_param.iefd.units.cu_vssnlm.x0 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_vssnlm.x[0]; + params->acc_param.iefd.units.cu_vssnlm.x1 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_vssnlm.x[1]; + params->acc_param.iefd.units.cu_vssnlm.a01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_vssnlm.a[0]; + params->acc_param.iefd.units.cu_vssnlm.b01 = config->yuvp1_c0_2500_config.iefd.cfg_units.cu_vssnlm.b[0]; + + params->acc_param.iefd.config.clamp_stitch = config->yuvp1_c0_2500_config.iefd.config.clamp_stitch; + params->acc_param.iefd.config.direct_metric_update = config->yuvp1_c0_2500_config.iefd.config.direct_metric_update; + params->acc_param.iefd.config.horver_diag_coeff = config->yuvp1_c0_2500_config.iefd.config.horver_diag_coeff; + params->acc_param.iefd.config.ed_horver_diag_coeff = config->yuvp1_c0_2500_config.iefd.config.ed_horver_diag_coeff; + + params->acc_param.iefd.sharp.cfg.nega_lmt_txt = config->yuvp1_c0_2500_config.iefd.sharp.cfg.nega_lmt_txt; + params->acc_param.iefd.sharp.cfg.posi_lmt_txt = config->yuvp1_c0_2500_config.iefd.sharp.cfg.posi_lmt_txt; + params->acc_param.iefd.sharp.cfg.nega_lmt_dir = config->yuvp1_c0_2500_config.iefd.sharp.cfg.nega_lmt_dir; + params->acc_param.iefd.sharp.cfg.posi_lmt_dir = config->yuvp1_c0_2500_config.iefd.sharp.cfg.posi_lmt_dir; + + params->acc_param.iefd.sharp.far_w.dir_shrp = config->yuvp1_c0_2500_config.iefd.sharp.far_w.dir_shrp; + params->acc_param.iefd.sharp.far_w.dir_dns = config->yuvp1_c0_2500_config.iefd.sharp.far_w.dir_dns; + params->acc_param.iefd.sharp.far_w.ndir_dns_powr = config->yuvp1_c0_2500_config.iefd.sharp.far_w.ndir_dns_powr; + params->acc_param.iefd.sharp.unshrp_cfg.unsharp_weight = config->yuvp1_c0_2500_config.iefd.sharp.unshrp_cfg.unsharp_weight; + params->acc_param.iefd.sharp.unshrp_cfg.unsharp_amount = config->yuvp1_c0_2500_config.iefd.sharp.unshrp_cfg.unsharp_amount; + + params->acc_param.iefd.unsharp.unsharp_coef0.c00 = config->yuvp1_c0_2500_config.iefd.unsharp.unsharp_coef0.c00; + params->acc_param.iefd.unsharp.unsharp_coef0.c01 = config->yuvp1_c0_2500_config.iefd.unsharp.unsharp_coef0.c01; + params->acc_param.iefd.unsharp.unsharp_coef0.c02 = config->yuvp1_c0_2500_config.iefd.unsharp.unsharp_coef0.c02; + params->acc_param.iefd.unsharp.unsharp_coef1.c11 = config->yuvp1_c0_2500_config.iefd.unsharp.unsharp_coef1.c11; + params->acc_param.iefd.unsharp.unsharp_coef1.c12 = config->yuvp1_c0_2500_config.iefd.unsharp.unsharp_coef1.c12; + params->acc_param.iefd.unsharp.unsharp_coef1.c22 = config->yuvp1_c0_2500_config.iefd.unsharp.unsharp_coef1.c22; + + params->acc_param.iefd.rad.reset_xy.x = config->yuvp1_c0_2500_config.iefd.rad.reset.x; + params->acc_param.iefd.rad.reset_xy.y = config->yuvp1_c0_2500_config.iefd.rad.reset.y; + params->acc_param.iefd.rad.reset_x2.x2 = (config->yuvp1_c0_2500_config.iefd.rad.reset.x * + config->yuvp1_c0_2500_config.iefd.rad.reset.x) & + XY_2_RESET_MASK; + params->acc_param.iefd.rad.reset_y2.y2 = (config->yuvp1_c0_2500_config.iefd.rad.reset.y * + config->yuvp1_c0_2500_config.iefd.rad.reset.y) & + XY_2_RESET_MASK; + + params->acc_param.iefd.rad.cfg.rad_nf = config->yuvp1_c0_2500_config.iefd.rad.cfg.rad_nf; + params->acc_param.iefd.rad.cfg.rad_inv_r2 = config->yuvp1_c0_2500_config.iefd.rad.cfg.rad_inv_r2; + params->acc_param.iefd.rad.rad_far_w.rad_dir_far_sharp_w = config->yuvp1_c0_2500_config.iefd.rad.rad_far_w.rad_dir_far_sharp_w; + params->acc_param.iefd.rad.rad_far_w.rad_dir_far_dns_w = config->yuvp1_c0_2500_config.iefd.rad.rad_far_w.rad_dir_far_dns_w; + params->acc_param.iefd.rad.rad_far_w.rad_ndir_far_dns_power = config->yuvp1_c0_2500_config.iefd.rad.rad_far_w.rad_ndir_far_dns_power; + + params->acc_param.iefd.rad.cu_cfg0.cu6_pow = config->yuvp1_c0_2500_config.iefd.rad.cu_cfg0.cu6_pow; + params->acc_param.iefd.rad.cu_cfg0.cu_unsharp_pow = config->yuvp1_c0_2500_config.iefd.rad.cu_cfg0.cu_unsharp_pow; + params->acc_param.iefd.rad.cu_cfg0.rad_cu6_pow = config->yuvp1_c0_2500_config.iefd.rad.cu_cfg0.rad_cu6_pow; + params->acc_param.iefd.rad.cu_cfg0.rad_cu_unsharp_pow = config->yuvp1_c0_2500_config.iefd.rad.cu_cfg0.rad_cu_unsharp_pow; + + params->acc_param.iefd.rad.cu_cfg1.rad_cu6_x1 = config->yuvp1_c0_2500_config.iefd.rad.cu_cfg1.rad_cu6_x1; + params->acc_param.iefd.rad.cu_cfg1.rad_cu_unsharp_x1 = config->yuvp1_c0_2500_config.iefd.rad.cu_cfg1.rad_cu_unsharp_x1; + + if (params->acc_param.iefd.control.vssnlm_en) { + params->acc_param.iefd.vsslnm.vss_lut_x.vs_x0 = config->yuvp1_c0_2500_config.iefd.vsslnm.vss_lut_x.vs_x0; + params->acc_param.iefd.vsslnm.vss_lut_x.vs_x1 = config->yuvp1_c0_2500_config.iefd.vsslnm.vss_lut_x.vs_x1; + params->acc_param.iefd.vsslnm.vss_lut_x.vs_x2 = config->yuvp1_c0_2500_config.iefd.vsslnm.vss_lut_x.vs_x2; + + params->acc_param.iefd.vsslnm.vss_lut_y.vs_y1 = config->yuvp1_c0_2500_config.iefd.vsslnm.vss_lut_y.vs_y1; + params->acc_param.iefd.vsslnm.vss_lut_y.vs_y2 = config->yuvp1_c0_2500_config.iefd.vsslnm.vss_lut_y.vs_y2; + params->acc_param.iefd.vsslnm.vss_lut_y.vs_y3 = config->yuvp1_c0_2500_config.iefd.vsslnm.vss_lut_y.vs_y3; + } + + params->use.acc_iefd = 1; +} + +/* Y down scaler */ +static void ispYdsEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.yds.c00 = config->yuvp1_2500_config.yds.c00; + params->acc_param.yds.c01 = config->yuvp1_2500_config.yds.c01; + params->acc_param.yds.c02 = config->yuvp1_2500_config.yds.c02; + params->acc_param.yds.c03 = config->yuvp1_2500_config.yds.c03; + params->acc_param.yds.c10 = config->yuvp1_2500_config.yds.c10; + params->acc_param.yds.c11 = config->yuvp1_2500_config.yds.c11; + params->acc_param.yds.c12 = config->yuvp1_2500_config.yds.c12; + params->acc_param.yds.c13 = config->yuvp1_2500_config.yds.c13; + params->acc_param.yds.norm_factor = config->yuvp1_2500_config.yds.norm_factor; + params->acc_param.yds.bin_output = config->yuvp1_2500_config.yds.bin_output; + + params->use.acc_yds = 1; +} + +/* Y down scaler */ +static void ispYdsC0Encode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.yds_c0.c00 = config->yuvp1_c0_2500_config.yds_c0.c00; + params->acc_param.yds_c0.c01 = config->yuvp1_c0_2500_config.yds_c0.c01; + params->acc_param.yds_c0.c02 = config->yuvp1_c0_2500_config.yds_c0.c02; + params->acc_param.yds_c0.c03 = config->yuvp1_c0_2500_config.yds_c0.c03; + params->acc_param.yds_c0.c10 = config->yuvp1_c0_2500_config.yds_c0.c10; + params->acc_param.yds_c0.c11 = config->yuvp1_c0_2500_config.yds_c0.c11; + params->acc_param.yds_c0.c12 = config->yuvp1_c0_2500_config.yds_c0.c12; + params->acc_param.yds_c0.c13 = config->yuvp1_c0_2500_config.yds_c0.c13; + params->acc_param.yds_c0.norm_factor = config->yuvp1_c0_2500_config.yds_c0.norm_factor; + params->acc_param.yds_c0.bin_output = config->yuvp1_c0_2500_config.yds_c0.bin_output; + + params->use.acc_yds_c0 = 1; +} + +/* Y channel down scaler */ +static void ispYds2Encode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.yds2.c00 = config->yuvp2_2500_config.yds2.c00; + params->acc_param.yds2.c01 = config->yuvp2_2500_config.yds2.c01; + params->acc_param.yds2.c02 = config->yuvp2_2500_config.yds2.c02; + params->acc_param.yds2.c03 = config->yuvp2_2500_config.yds2.c03; + params->acc_param.yds2.c10 = config->yuvp2_2500_config.yds2.c10; + params->acc_param.yds2.c11 = config->yuvp2_2500_config.yds2.c11; + params->acc_param.yds2.c12 = config->yuvp2_2500_config.yds2.c12; + params->acc_param.yds2.c13 = config->yuvp2_2500_config.yds2.c13; + params->acc_param.yds2.norm_factor = config->yuvp2_2500_config.yds2.norm_factor; + params->acc_param.yds2.bin_output = config->yuvp2_2500_config.yds2.bin_output; + + params->use.acc_yds2 = 1; +} + +/* Chroma noise reduction */ +static void ispChnrEncode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->acc_param.chnr); + + params->acc_param.chnr.coring.u = config->yuvp1_2500_config.chnr.coring.u; + params->acc_param.chnr.coring.v = config->yuvp1_2500_config.chnr.coring.v; + + params->acc_param.chnr.sense_gain.vy = config->yuvp1_2500_config.chnr.sense_gain.vy; + params->acc_param.chnr.sense_gain.vu = config->yuvp1_2500_config.chnr.sense_gain.vu; + params->acc_param.chnr.sense_gain.vv = config->yuvp1_2500_config.chnr.sense_gain.vv; + params->acc_param.chnr.sense_gain.hy = config->yuvp1_2500_config.chnr.sense_gain.hy; + params->acc_param.chnr.sense_gain.hu = config->yuvp1_2500_config.chnr.sense_gain.hu; + params->acc_param.chnr.sense_gain.hv = config->yuvp1_2500_config.chnr.sense_gain.hv; + + params->acc_param.chnr.iir_fir.fir_0h = config->yuvp1_2500_config.chnr.iir_fir.fir_0h; + params->acc_param.chnr.iir_fir.fir_1h = config->yuvp1_2500_config.chnr.iir_fir.fir_1h; + params->acc_param.chnr.iir_fir.fir_2h = config->yuvp1_2500_config.chnr.iir_fir.fir_2h; + params->acc_param.chnr.iir_fir.dalpha_clip_val = DALPHA_MAX - config->yuvp1_2500_config.chnr.iir_fir.iir_min_prev; + + params->use.acc_chnr = 1; +} + +/* Chroma noise reduction */ +static void ispChnrC0Encode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->acc_param.chnr_c0); + + params->acc_param.chnr_c0.coring.u = config->yuvp1_c0_2500_config.chnr_c0.coring.u; + params->acc_param.chnr_c0.coring.v = config->yuvp1_c0_2500_config.chnr_c0.coring.v; + + params->acc_param.chnr_c0.sense_gain.vy = config->yuvp1_c0_2500_config.chnr_c0.sense_gain.vy; + params->acc_param.chnr_c0.sense_gain.vu = config->yuvp1_c0_2500_config.chnr_c0.sense_gain.vu; + params->acc_param.chnr_c0.sense_gain.vv = config->yuvp1_c0_2500_config.chnr_c0.sense_gain.vv; + params->acc_param.chnr_c0.sense_gain.hy = config->yuvp1_c0_2500_config.chnr_c0.sense_gain.hy; + params->acc_param.chnr_c0.sense_gain.hu = config->yuvp1_c0_2500_config.chnr_c0.sense_gain.hu; + params->acc_param.chnr_c0.sense_gain.hv = config->yuvp1_c0_2500_config.chnr_c0.sense_gain.hv; + + params->acc_param.chnr_c0.iir_fir.fir_0h = config->yuvp1_c0_2500_config.chnr_c0.iir_fir.fir_0h; + params->acc_param.chnr_c0.iir_fir.fir_1h = config->yuvp1_c0_2500_config.chnr_c0.iir_fir.fir_1h; + params->acc_param.chnr_c0.iir_fir.fir_2h = config->yuvp1_c0_2500_config.chnr_c0.iir_fir.fir_2h; + params->acc_param.chnr_c0.iir_fir.dalpha_clip_val = DALPHA_MAX - config->yuvp1_c0_2500_config.chnr_c0.iir_fir.iir_min_prev; + + params->use.acc_chnr_c0 = 1; +} + +/* Y Edge enhancement and noise reduction */ +static void ispYEeNrEncode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->acc_param.y_ee_nr); + + params->acc_param.y_ee_nr.lpf.enable = config->yuvp1_2500_config.y_ee_nr.lpf.y_ee_nr_en; + params->acc_param.y_ee_nr.lpf.a_diag = config->yuvp1_2500_config.y_ee_nr.lpf.a_diag; + params->acc_param.y_ee_nr.lpf.a_cent = config->yuvp1_2500_config.y_ee_nr.lpf.a_cent; + params->acc_param.y_ee_nr.lpf.a_periph = config->yuvp1_2500_config.y_ee_nr.lpf.a_periph; + + params->acc_param.y_ee_nr.sense.edge_sense_0 = config->yuvp1_2500_config.y_ee_nr.sense.edge_sense_0; + params->acc_param.y_ee_nr.sense.delta_edge_sense = config->yuvp1_2500_config.y_ee_nr.sense.delta_edge_sense; + params->acc_param.y_ee_nr.sense.corner_sense_0 = config->yuvp1_2500_config.y_ee_nr.sense.corner_sense_0; + params->acc_param.y_ee_nr.sense.delta_corner_sense = config->yuvp1_2500_config.y_ee_nr.sense.delta_corner_sense; + + params->acc_param.y_ee_nr.gain.gain_pos_0 = config->yuvp1_2500_config.y_ee_nr.gain.gain_pos_0; + params->acc_param.y_ee_nr.gain.delta_gain_posi = config->yuvp1_2500_config.y_ee_nr.gain.delta_gain_posi; + params->acc_param.y_ee_nr.gain.gain_neg_0 = config->yuvp1_2500_config.y_ee_nr.gain.gain_neg_0; + params->acc_param.y_ee_nr.gain.delta_gain_neg = config->yuvp1_2500_config.y_ee_nr.gain.delta_gain_neg; + + params->acc_param.y_ee_nr.clip.clip_pos_0 = config->yuvp1_2500_config.y_ee_nr.clip.clip_pos_0; + params->acc_param.y_ee_nr.clip.delta_clip_posi = config->yuvp1_2500_config.y_ee_nr.clip.delta_clip_posi; + params->acc_param.y_ee_nr.clip.clip_neg_0 = config->yuvp1_2500_config.y_ee_nr.clip.clip_neg_0; + params->acc_param.y_ee_nr.clip.delta_clip_neg = config->yuvp1_2500_config.y_ee_nr.clip.delta_clip_neg; + + params->acc_param.y_ee_nr.frng.gain_exp = config->yuvp1_2500_config.y_ee_nr.frng.gain_exp; + params->acc_param.y_ee_nr.frng.min_edge = config->yuvp1_2500_config.y_ee_nr.frng.min_edge; + params->acc_param.y_ee_nr.frng.lin_seg_param = config->yuvp1_2500_config.y_ee_nr.frng.lin_seg_param; + params->acc_param.y_ee_nr.frng.t1 = config->yuvp1_2500_config.y_ee_nr.frng.t1; + params->acc_param.y_ee_nr.frng.t2 = config->yuvp1_2500_config.y_ee_nr.frng.t2; + + params->acc_param.y_ee_nr.diag.diag_disc_g = config->yuvp1_2500_config.y_ee_nr.diag.diag_disc_g; + params->acc_param.y_ee_nr.diag.hvw_hor = config->yuvp1_2500_config.y_ee_nr.diag.hvw_hor; + params->acc_param.y_ee_nr.diag.dw_hor = config->yuvp1_2500_config.y_ee_nr.diag.dw_hor; + params->acc_param.y_ee_nr.diag.hvw_diag = config->yuvp1_2500_config.y_ee_nr.diag.hvw_diag; + params->acc_param.y_ee_nr.diag.dw_diag = config->yuvp1_2500_config.y_ee_nr.diag.dw_diag; + + params->acc_param.y_ee_nr.fc_coring.pos_0 = config->yuvp1_2500_config.y_ee_nr.fc_coring.pos_0; + params->acc_param.y_ee_nr.fc_coring.pos_delta = config->yuvp1_2500_config.y_ee_nr.fc_coring.pos_delta; + params->acc_param.y_ee_nr.fc_coring.neg_0 = config->yuvp1_2500_config.y_ee_nr.fc_coring.neg_0; + params->acc_param.y_ee_nr.fc_coring.neg_delta = config->yuvp1_2500_config.y_ee_nr.fc_coring.neg_delta; + + params->use.acc_y_ee_nr = 1; +} + +/* Total Color Correction */ +static void ispTccEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->acc_param.tcc.gen_control.en = 1; + params->acc_param.tcc.gen_control.blend_shift = config->yuvp2_2500_config.tcc.gen_control.blend_shift; + params->acc_param.tcc.gen_control.delta = config->yuvp2_2500_config.tcc.gen_control.delta; + params->acc_param.tcc.gen_control.gamma = config->yuvp2_2500_config.tcc.gen_control.gamma; + params->acc_param.tcc.gen_control.gain_according_to_y_only = config->yuvp2_2500_config.tcc.gen_control.gain_according_to_y_only; + + MEMCPY_S(params->acc_param.tcc.macc_table.entries, + sizeof(params->acc_param.tcc.macc_table.entries), + config->yuvp2_2500_config.tcc.macc_table.entries, + sizeof(config->yuvp2_2500_config.tcc.macc_table.entries)); + + MEMCPY_S(params->acc_param.tcc.inv_y_lut.entries, + sizeof(params->acc_param.tcc.inv_y_lut.entries), + config->yuvp2_2500_config.tcc.inv_y_lut.entries, + sizeof(config->yuvp2_2500_config.tcc.inv_y_lut.entries)); + + MEMCPY_S(params->acc_param.tcc.gain_pcwl.entries, + sizeof(params->acc_param.tcc.gain_pcwl.entries), + config->yuvp2_2500_config.tcc.gain_pcwl.entries, + sizeof(config->yuvp2_2500_config.tcc.gain_pcwl.entries)); + + MEMCPY_S(params->acc_param.tcc.r_sqr_lut.entries, + sizeof(params->acc_param.tcc.r_sqr_lut.entries), + config->yuvp2_2500_config.tcc.r_sqr_lut.entries, + sizeof(config->yuvp2_2500_config.tcc.r_sqr_lut.entries)); + + params->use.acc_tcc = 1; +} + +static void copyAlpha(ipu3_uapi_anr_alpha *to, alpha_t *from) +{ + to->gr = from->Alpha_Gr & COLOR_ALPHA_MASK; + to->r = from->Alpha_R & COLOR_ALPHA_MASK; + to->b = from->Alpha_B & COLOR_ALPHA_MASK; + to->gb = from->Alpha_Gb & COLOR_ALPHA_MASK; + to->dc_gr = from->Alpha_DC_Gr & COLOR_ALPHA_MASK; + to->dc_r = from->Alpha_DC_R & COLOR_ALPHA_MASK; + to->dc_b = from->Alpha_DC_B & COLOR_ALPHA_MASK; + to->dc_gb = from->Alpha_DC_Gb & COLOR_ALPHA_MASK; +} + +static void copyBeta(ipu3_uapi_anr_beta *to, beta_t *from) +{ + to->beta_gr = from->Beta_Gr & COLOR_BETA_MASK; + to->beta_r = from->Beta_R & COLOR_BETA_MASK; + to->beta_b = from->Beta_B & COLOR_BETA_MASK; + to->beta_gb = from->Beta_Gb & COLOR_BETA_MASK; +} + +static void copyColoreRg(ipu3_uapi_anr_plane_color *to, plain_color_w_matrix_t *from) +{ + for (int i = 0; i < W_MATRIX_SIZE; i++) { + to->reg_w_gr[i] = from->Gr[i] & COLOR_REG_W_MASK; + to->reg_w_r[i] = from->R[i] & COLOR_REG_W_MASK; + to->reg_w_b[i] = from->B[i] & COLOR_REG_W_MASK; + to->reg_w_gb[i] = from->Gb[i] & COLOR_REG_W_MASK; + } +} + +/* Advanced Noise Reduction */ +static void ispAnrEncode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->acc_param.anr); + + short sqrt_lut[] = SQRT_LUT; + + params->acc_param.anr.transform.enable = 1; + params->acc_param.anr.transform.adaptive_treshhold_en = config->anr_2500_config.anr.transform.ADAPTIVE_TRESHHOLD_EN & 0x1; + copyAlpha(¶ms->acc_param.anr.transform.alpha[0], &config->anr_2500_config.anr.transform.plane_0.alpha); + copyAlpha(¶ms->acc_param.anr.transform.alpha[1], &config->anr_2500_config.anr.transform.plane_1.alpha); + copyAlpha(¶ms->acc_param.anr.transform.alpha[2], &config->anr_2500_config.anr.transform.plane_2.alpha); + + copyBeta(¶ms->acc_param.anr.transform.beta[0], &config->anr_2500_config.anr.transform.plane_0.beta); + copyBeta(¶ms->acc_param.anr.transform.beta[1], &config->anr_2500_config.anr.transform.plane_1.beta); + copyBeta(¶ms->acc_param.anr.transform.beta[2], &config->anr_2500_config.anr.transform.plane_2.beta); + + copyColoreRg(¶ms->acc_param.anr.transform.color[0], &config->anr_2500_config.anr.transform.plane_0.color_reg_w); + copyColoreRg(¶ms->acc_param.anr.transform.color[1], &config->anr_2500_config.anr.transform.plane_1.color_reg_w); + copyColoreRg(¶ms->acc_param.anr.transform.color[2], &config->anr_2500_config.anr.transform.plane_2.color_reg_w); + + MEMCPY_S(params->acc_param.anr.transform.sqrt_lut, + sizeof(params->acc_param.anr.transform.sqrt_lut), + &sqrt_lut, + sizeof(sqrt_lut)); + + params->acc_param.anr.transform.xreset = config->anr_2500_config.anr.transform.CALC.Xreset; + params->acc_param.anr.transform.yreset = config->anr_2500_config.anr.transform.CALC.Yreset; + + params->acc_param.anr.transform.x_sqr_reset = config->anr_2500_config.anr.transform.CALC.X_sqr_reset; + if (config->anr_2500_config.anr.transform.CALC.X_sqr_reset & ~(X_SQR_RESET_MAX)) { + params->acc_param.anr.transform.x_sqr_reset = X_SQR_RESET_MAX; + } + + params->acc_param.anr.transform.r_normfactor = config->anr_2500_config.anr.transform.CALC.R_NormFactor; + if (config->anr_2500_config.anr.transform.CALC.R_NormFactor & ~(R_NORM_FACTOR_MAX)) { + params->acc_param.anr.transform.r_normfactor = R_NORM_FACTOR_MAX; + } + + params->acc_param.anr.transform.y_sqr_reset = config->anr_2500_config.anr.transform.CALC.Y_sqr_reset; + if (config->anr_2500_config.anr.transform.CALC.Y_sqr_reset & ~(Y_SQR_RESET_MAX)) { + params->acc_param.anr.transform.y_sqr_reset = Y_SQR_RESET_MAX; + } + + params->acc_param.anr.transform.gain_scale = config->anr_2500_config.anr.transform.CALC.radial_gain_scale_factor; + if (config->anr_2500_config.anr.transform.CALC.radial_gain_scale_factor & ~(RAD_GAIN_SCALE_FACTOR)) { + params->acc_param.anr.transform.gain_scale = RAD_GAIN_SCALE_FACTOR; + } + params->acc_param.anr.stitch.anr_stitch_en = 1; + + for (int i = 0, j = 0; i < IPU3_UAPI_ANR_PYRAMID_SIZE; ++i) { + params->acc_param.anr.stitch.pyramid[i].entry0 = config->anr_2500_config.anr.stitch.pyramid_reg[j++]; + + if (i < IPU3_UAPI_ANR_PYRAMID_SIZE - 1) { + params->acc_param.anr.stitch.pyramid[i].entry1 = config->anr_2500_config.anr.stitch.pyramid_reg[j++]; + params->acc_param.anr.stitch.pyramid[i].entry2 = config->anr_2500_config.anr.stitch.pyramid_reg[j++]; + } + } + + params->use.acc_anr = 1; +} + +/* Bayer noise reduction */ +static void ispBnrEncode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->acc_param.bnr); + + params->acc_param.bnr.wb_gains.gr = config->bnr_2500_config.bnr.wb_gains.gr; + params->acc_param.bnr.wb_gains.r = config->bnr_2500_config.bnr.wb_gains.r; + params->acc_param.bnr.wb_gains.b = config->bnr_2500_config.bnr.wb_gains.b; + params->acc_param.bnr.wb_gains.gb = config->bnr_2500_config.bnr.wb_gains.gb; + + params->acc_param.bnr.wb_gains_thr.gr = (unsigned char)config->bnr_2500_config.bnr.wb_gains_thr.gr; + params->acc_param.bnr.wb_gains_thr.r = (unsigned char)config->bnr_2500_config.bnr.wb_gains_thr.r; + params->acc_param.bnr.wb_gains_thr.b = (unsigned char)config->bnr_2500_config.bnr.wb_gains_thr.b; + params->acc_param.bnr.wb_gains_thr.gb = (unsigned char)config->bnr_2500_config.bnr.wb_gains_thr.gb; + + params->acc_param.bnr.thr_coeffs.cf = config->bnr_2500_config.bnr.thr_coeffs.cf; + params->acc_param.bnr.thr_coeffs.cg = config->bnr_2500_config.bnr.thr_coeffs.cg; + params->acc_param.bnr.thr_coeffs.ci = config->bnr_2500_config.bnr.thr_coeffs.ci; + params->acc_param.bnr.thr_coeffs.r_nf = config->bnr_2500_config.bnr.thr_coeffs.r_nf; + + params->acc_param.bnr.thr_ctrl_shd.gr = config->bnr_2500_config.bnr.thr_ctrl_shd.gr; + params->acc_param.bnr.thr_ctrl_shd.r = config->bnr_2500_config.bnr.thr_ctrl_shd.r; + params->acc_param.bnr.thr_ctrl_shd.b = config->bnr_2500_config.bnr.thr_ctrl_shd.b; + params->acc_param.bnr.thr_ctrl_shd.gb = config->bnr_2500_config.bnr.thr_ctrl_shd.gb; + + params->acc_param.bnr.opt_center.x_reset = config->bnr_2500_config.bnr.opt_center.x_reset; + params->acc_param.bnr.opt_center.y_reset = config->bnr_2500_config.bnr.opt_center.y_reset; + + params->acc_param.bnr.opt_center_sqr.x_sqr_reset = config->bnr_2500_config.bnr.opt_center.x_sqr_reset; + params->acc_param.bnr.opt_center_sqr.y_sqr_reset = config->bnr_2500_config.bnr.opt_center.y_sqr_reset; + + MEMCPY_S(params->acc_param.bnr.lut.values, + sizeof(params->acc_param.bnr.lut.values), + config->bnr_2500_config.bnr.lut.values, + sizeof(config->bnr_2500_config.bnr.lut.values)); + + params->acc_param.bnr.bp_ctrl.bp_thr_gain = config->bnr_2500_config.bnr.bp_ctrl.bp_thr_gain; + params->acc_param.bnr.bp_ctrl.defect_mode = config->bnr_2500_config.bnr.bp_ctrl.defect_mode; + params->acc_param.bnr.bp_ctrl.bp_gain = config->bnr_2500_config.bnr.bp_ctrl.bp_gain; + params->acc_param.bnr.bp_ctrl.w0_coeff = config->bnr_2500_config.bnr.bp_ctrl.w0_coeff; + params->acc_param.bnr.bp_ctrl.w1_coeff = config->bnr_2500_config.bnr.bp_ctrl.w1_coeff; + + params->acc_param.bnr.dn_detect_ctrl.alpha = config->bnr_2500_config.bnr.dn_detect_ctrl.alpha; + params->acc_param.bnr.dn_detect_ctrl.beta = config->bnr_2500_config.bnr.dn_detect_ctrl.beta; + params->acc_param.bnr.dn_detect_ctrl.gamma = config->bnr_2500_config.bnr.dn_detect_ctrl.gamma; + params->acc_param.bnr.dn_detect_ctrl.max_inf = config->bnr_2500_config.bnr.dn_detect_ctrl.max_inf; + params->acc_param.bnr.dn_detect_ctrl.gd_enable = config->bnr_2500_config.bnr.dn_detect_ctrl.gd_en; + params->acc_param.bnr.dn_detect_ctrl.bpc_enable = config->bnr_2500_config.bnr.dn_detect_ctrl.bpc_en; + params->acc_param.bnr.dn_detect_ctrl.bnr_enable = config->bnr_2500_config.bnr.dn_detect_ctrl.bnr_en; + params->acc_param.bnr.dn_detect_ctrl.ff_enable = 1; + + params->use.acc_bnr = 1; +} + +static void ispOBGEncode(aic_config *config, ipu3_uapi_params *params) +{ + params->obgrid_param.gr = config->obgrid_2500_config.table_GR[0]; + params->obgrid_param.r = config->obgrid_2500_config.table_R[0]; + params->obgrid_param.b = config->obgrid_2500_config.table_B[0]; + params->obgrid_param.gb = config->obgrid_2500_config.table_GB[0]; + + params->use.obgrid = 1; + params->use.obgrid_param = 1; +} + +/* Green disparity between Gr and Gb channel */ +static void ispBnrGreenDisparityEncode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->acc_param.green_disparity); + + params->acc_param.green_disparity.gd_red = config->bnr_2500_config.green_disparity.GD_Red; + params->acc_param.green_disparity.gd_green = config->bnr_2500_config.green_disparity.GD_Green; + params->acc_param.green_disparity.gd_blue = config->bnr_2500_config.green_disparity.GD_Blue; + params->acc_param.green_disparity.gd_black = config->bnr_2500_config.green_disparity.GD_Black; + params->acc_param.green_disparity.gd_shading = config->bnr_2500_config.green_disparity.GD_Shading; + params->acc_param.green_disparity.gd_support = config->bnr_2500_config.green_disparity.GD_Support; + params->acc_param.green_disparity.gd_clip = config->bnr_2500_config.green_disparity.GD_Clip; + params->acc_param.green_disparity.gd_central_weight = config->bnr_2500_config.green_disparity.GD_Central_Weight; + + params->use.acc_green_disparity = 1; +} + +static unsigned int ceil_pow2(unsigned int p) +{ + if (p == 0) { + return 1; + } else if ((!((p) & ((p)-1)))) { + return p; + } else { + unsigned int v = p; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return (v + 1); + } +} + +static int32_t compute_alpha(int sigma) +{ + int32_t alpha; +#if defined(XNR_ATE_ROUNDING_BUG) + int32_t alpha_unscaled; +#else + int offset = sigma / 2; +#endif + if (sigma < XNR_MIN_SIGMA) { + alpha = XNR_MAX_ALPHA; + } else { +#if defined(XNR_ATE_ROUNDING_BUG) + /* The scale factor for alpha must be the same as on the ISP, + * For sigma, it must match the public interface. The code + * below mimics the rounding and unintended loss of precision + * of the ATE reference code. It computes an unscaled alpha, + * rounds down, and then scales it to get the required fixed + * point representation. It would have been more precise to + * round after scaling. */ + alpha_unscaled = IA_CSS_XNR3_SIGMA_SCALE / sigma; + alpha = alpha_unscaled * XNR_ALPHA_SCALE_FACTOR; +#else + alpha = ((IA_CSS_XNR3_SIGMA_SCALE * XNR_ALPHA_SCALE_FACTOR) + offset) / sigma; +#endif + if (alpha > XNR_MAX_ALPHA) { + alpha = XNR_MAX_ALPHA; + } + } + + return alpha; +} + +static int32_t compute_coring(int coring) +{ + int32_t isp_coring; + int32_t isp_scale = XNR_CORING_SCALE_FACTOR; + int32_t host_scale = IA_CSS_XNR3_CORING_SCALE; + int32_t offset = host_scale / 2; /* fixed-point 0.5 */ + + /* Convert from public host-side scale factor to isp-side scale + * factor. Clip to [0, isp_scale-1). */ + isp_coring = ((coring * isp_scale) + offset) / host_scale; + + return MIN(MAX(isp_coring, 0), isp_scale - 1); +} + +static int32_t compute_blending(int strength) +{ + int32_t isp_strength; + int32_t isp_scale = XNR_BLENDING_SCALE_FACTOR; + int32_t host_scale = IA_CSS_XNR3_BLENDING_SCALE; + int32_t offset = host_scale / 2; /* fixed-point 0.5 */ + + /* Convert from public host-side scale factor to isp-side scale + * factor. The blending factor is positive on the host side, but + * negative on the ISP side because +1.0 cannot be represented + * exactly as s0.11 fixed point, but -1.0 can. */ + isp_strength = -(((strength * isp_scale) + offset) / host_scale); + + return MAX(MIN(isp_strength, 0), -XNR_BLENDING_SCALE_FACTOR); +} + +static void ispXnr3Encode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->xnr3_dmem_params); + + struct ipu3_uapi_isp_xnr3_params *to = ¶ms->xnr3_dmem_params; + const struct ia_css_xnr3_config *from = &config->xnr_2500_config; + + int kernel_size = XNR_FILTER_SIZE; + /* The adjust factor is the next power of 2 w.r.t. the kernel size */ + int adjust_factor = ceil_pow2(kernel_size); + int32_t max_diff = (1 << (ISP_VEC_ELEMBITS - 1)) - 1; + int32_t min_diff = -(1 << (ISP_VEC_ELEMBITS - 1)); + + int32_t alpha_y0 = compute_alpha(from->sigma.y0); + int32_t alpha_y1 = compute_alpha(from->sigma.y1); + int32_t alpha_u0 = compute_alpha(from->sigma.u0); + int32_t alpha_u1 = compute_alpha(from->sigma.u1); + int32_t alpha_v0 = compute_alpha(from->sigma.v0); + int32_t alpha_v1 = compute_alpha(from->sigma.v1); + int32_t alpha_ydiff = (alpha_y1 - alpha_y0) * adjust_factor / kernel_size; + int32_t alpha_udiff = (alpha_u1 - alpha_u0) * adjust_factor / kernel_size; + int32_t alpha_vdiff = (alpha_v1 - alpha_v0) * adjust_factor / kernel_size; + + int32_t coring_u0 = compute_coring(from->coring.u0); + int32_t coring_u1 = compute_coring(from->coring.u1); + int32_t coring_v0 = compute_coring(from->coring.v0); + int32_t coring_v1 = compute_coring(from->coring.v1); + int32_t coring_udiff = (coring_u1 - coring_u0) * adjust_factor / kernel_size; + int32_t coring_vdiff = (coring_v1 - coring_v0) * adjust_factor / kernel_size; + + int32_t blending = compute_blending(from->blending.strength); + + /* alpha's are represented in qN.5 format */ + to->alpha.y0 = alpha_y0; + to->alpha.u0 = alpha_u0; + to->alpha.v0 = alpha_v0; + to->alpha.ydiff = MIN(MAX(alpha_ydiff, min_diff), max_diff); + to->alpha.udiff = MIN(MAX(alpha_udiff, min_diff), max_diff); + to->alpha.vdiff = MIN(MAX(alpha_vdiff, min_diff), max_diff); + + /* coring parameters are expressed in q1.NN format */ + to->coring.u0 = coring_u0; + to->coring.v0 = coring_v0; + to->coring.udiff = MIN(MAX(coring_udiff, min_diff), max_diff); + to->coring.vdiff = MIN(MAX(coring_vdiff, min_diff), max_diff); + + /* blending strength is expressed in q1.NN format */ + to->blending.strength = blending; + + params->use.xnr3_dmem_params = 1; +} + +static void ispXnr3VmemEncode([[maybe_unused]] aic_config *config, ipu3_uapi_params *params) +{ + struct ipu3_uapi_isp_xnr3_vmem_params *to = ¶ms->xnr3_vmem_params; + CLEAR(params->xnr3_vmem_params); + + unsigned i, j, base; + const unsigned total_blocks = 4; + const unsigned shuffle_block = 16; + + /* Init */ + for (i = 0; i < ISP_VEC_NELEMS; i++) { + to->x[i] = 0; + to->a[i] = 0; + to->b[i] = 0; + to->c[i] = 0; + } + + /* Constraints on "x": + * - values should be greater or equal to 0. + * - values should be ascending. + */ + assert(x[0] >= 0); + + for (j = 1; j < XNR3_LOOK_UP_TABLE_POINTS; j++) { + assert(x[j] >= 0); + assert(x[j] > x[j - 1]); + } + + /* The implementation of the calulating 1/x is based on the availability + * of the OP_vec_shuffle16 operation. + * A 64 element vector is split up in 4 blocks of 16 element. Each array + * is copied to a vector 4 times, (starting at 0, 16, 32 and 48). All + * array elements are copied or initialised as described in the KFS. The + * remaining elements of a vector are set to 0. + */ + /* TODO: guard this code with above assumptions */ + for (i = 0; i < total_blocks; i++) { + base = shuffle_block * i; + + for (j = 0; j < XNR3_LOOK_UP_TABLE_POINTS; j++) { + to->x[base + j] = x[j]; + to->a[base + j] = a[j]; + to->b[base + j] = b[j]; + to->c[base + j] = c[j]; + } + } + + params->use.xnr3_vmem_params = 1; +} + +static int qrmul(int number1, int number2) +{ + int result; + int offset = TNR3_RND_OFFSET; + int prod = number1 * number2; + + if (prod >= 0) + result = prod + offset; + else + result = prod - offset; + + return (result / TNR3_ISP_SCALE); +} + +static void ispTnr3VmemEncode(aic_config *config, ipu3_uapi_params *params) +{ + int i, j = 0; + int xdiff, scale_factor; + int knee_point[TNR3_NUM_POINTS]; + int slopeu_y[TNR3_NUM_SEGMENTS]; + int slopeu_u[TNR3_NUM_SEGMENTS]; + int slopeu_v[TNR3_NUM_SEGMENTS]; + int normalised_ydiff[TNR3_NUM_SEGMENTS]; + int normalised_udiff[TNR3_NUM_SEGMENTS]; + int normalised_vdiff[TNR3_NUM_SEGMENTS]; + int yintercept_y[TNR3_NUM_SEGMENTS]; + int yintercept_u[TNR3_NUM_SEGMENTS]; + int yintercept_v[TNR3_NUM_SEGMENTS]; + + knee_point[0] = 0; + knee_point[TNR3_NUM_POINTS - 1] = TNR3_MAX_VALUE; + + for (i = 0; i < TNR3_KNEE_POINTS; i++) { + knee_point[1 + i] = config->tnr3_2500_config.knee_y[i]; + } + + for (i = 0; i < TNR3_NUM_SEGMENTS; i++) { + /* Calculating slope for Y, U and V. Slope is (y2 - y1)/(x2 - x1). + * This division results in a loss of the normalisation coefficient + * which causes unacceptable loss in precision. In order to + * overcome that, we multiple the ydiff (y2 - y1) by the + * normalisation coefficient once again + */ + normalised_ydiff[i] = (config->tnr3_2500_config.sigma_y[i + 1] - config->tnr3_2500_config.sigma_y[i]) * TNR3_ISP_SCALE; + normalised_udiff[i] = (config->tnr3_2500_config.sigma_u[i + 1] - config->tnr3_2500_config.sigma_u[i]) * TNR3_ISP_SCALE; + normalised_vdiff[i] = (config->tnr3_2500_config.sigma_v[i + 1] - config->tnr3_2500_config.sigma_v[i]) * TNR3_ISP_SCALE; + + /* Calculation of xdiff (x2 - x1) */ + xdiff = knee_point[i + 1] - knee_point[i]; + + if (xdiff == 0) { /* Zero length segment */ + slopeu_y[i] = 0; + slopeu_u[i] = 0; + slopeu_v[i] = 0; + } else { + /* Slope(normalised) = ydiff(normalised)/xdiff. As the slope + * should be normalised to ISP_VEC_ELEMBITS, it should be + * clipped at the minimum and maximum allowable values. + */ + slopeu_y[i] = clamp((normalised_ydiff[i] / xdiff), TNR3_MIN_VALUE, TNR3_MAX_VALUE); + slopeu_u[i] = clamp((normalised_udiff[i] / xdiff), TNR3_MIN_VALUE, TNR3_MAX_VALUE); + slopeu_v[i] = clamp((normalised_vdiff[i] / xdiff), TNR3_MIN_VALUE, TNR3_MAX_VALUE); + } + /* Calculate Y axis (standard deviation) intercept using the formula + * Y1 - m*X1 for each linear segment per plane. To mimic the method + * followed in ATE, this calculation is done after clipping the + * slope value post normalisation. As the input points are + * already normalised, there is no need for clipping the + * Y-intercepts. + * TODO: ATE does nearest even rounding whereas we do nearest + * rounding. We need to modify the ATE code to work with integer + * values so that similar rounding mechanisms can be implemented + * on both sides + */ + yintercept_y[i] = config->tnr3_2500_config.sigma_y[i] - qrmul(slopeu_y[i], knee_point[i]); + yintercept_u[i] = config->tnr3_2500_config.sigma_u[i] - qrmul(slopeu_u[i], knee_point[i]); + yintercept_v[i] = config->tnr3_2500_config.sigma_v[i] - qrmul(slopeu_v[i], knee_point[i]); + } + +#if HOST_SCALING + scale_factor = 2; +#else + scale_factor = 1; +#endif + for (i = 0; i < TNR3_NUM_SEGMENTS; i++) { + j = (TNR3_NUM_SEGMENTS - 1) - i; + /* Slope */ + /* TODO: Should the scaling be done on Host or ISP ?? */ + params->tnr3_vmem_params.slope[j] = clamp(slopeu_y[i] * scale_factor, TNR3_MIN_VALUE, TNR3_MAX_VALUE); + params->tnr3_vmem_params.slope[j + TNR3_NUM_SEGMENTS] = clamp(slopeu_u[i] * scale_factor, TNR3_MIN_VALUE, TNR3_MAX_VALUE); + params->tnr3_vmem_params.slope[j + 2 * TNR3_NUM_SEGMENTS] = clamp(slopeu_v[i] * scale_factor, TNR3_MIN_VALUE, TNR3_MAX_VALUE); + /* Y intercept */ + /* TODO: Should the scaling be done on HOST or ISP ?? */ + params->tnr3_vmem_params.sigma[j] = clamp(yintercept_y[i] * scale_factor, TNR3_MIN_VALUE, TNR3_MAX_VALUE); + params->tnr3_vmem_params.sigma[j + TNR3_NUM_SEGMENTS] = clamp(yintercept_u[i] * scale_factor, TNR3_MIN_VALUE, TNR3_MAX_VALUE); + params->tnr3_vmem_params.sigma[j + 2 * TNR3_NUM_SEGMENTS] = clamp(yintercept_v[i] * scale_factor, TNR3_MIN_VALUE, TNR3_MAX_VALUE); + } + + params->use.tnr3_vmem_params = 1; +} + +static void ispTnr3DmemEncode(aic_config *config, ipu3_uapi_params *params) +{ + CLEAR(params->tnr3_dmem_params); + + params->tnr3_dmem_params.knee_y1 = config->tnr3_2500_config.knee_y[0]; + params->tnr3_dmem_params.knee_y2 = config->tnr3_2500_config.knee_y[1]; + params->tnr3_dmem_params.maxfb_y = config->tnr3_2500_config.maxfb_y; + params->tnr3_dmem_params.maxfb_u = config->tnr3_2500_config.maxfb_u; + params->tnr3_dmem_params.maxfb_v = config->tnr3_2500_config.maxfb_v; + params->tnr3_dmem_params.round_adj_y = config->tnr3_2500_config.round_adj_y; + params->tnr3_dmem_params.round_adj_u = config->tnr3_2500_config.round_adj_u; + params->tnr3_dmem_params.round_adj_v = config->tnr3_2500_config.round_adj_v; + params->tnr3_dmem_params.ref_buf_select = config->tnr3_2500_config.ref_buf_select; + + params->use.tnr3_dmem_params = 1; +} + +void ParameterEncoder::encode(aic_config *config, ipu3_uapi_params *params) +{ + /* todo: The ispAwbFrEncode generates an assertion failure. + * + * Disable it for now, but keep it in the code to prevent adding + * a compiler warning. + */ + if (0) + ispAwbFrEncode(config, params); + + ispAeEncode(config, params); + ispAwbEncode(config, params); + ispAfEncode(config, params); + ispLinVmemEncode(config, params); + ispGammaCtrlEncode(config, params); + ispCcmEncode(config, params); + ispCscEncode(config, params); + ispCdsEncode(config, params); + ispDmEncode(config, params); + ispShdEncode(config, params); + ispIefdEncode(config, params); + ispYdsEncode(config, params); + ispYdsC0Encode(config, params); + ispYds2Encode(config, params); + ispChnrEncode(config, params); + ispChnrC0Encode(config, params); + ispYEeNrEncode(config, params); + ispTccEncode(config, params); + ispAnrEncode(config, params); + ispBnrEncode(config, params); + ispOBGEncode(config, params); + ispBnrGreenDisparityEncode(config, params); + ispXnr3Encode(config, params); + ispXnr3VmemEncode(config, params); + ispTnr3VmemEncode(config, params); + ispTnr3DmemEncode(config, params); + + return; +} + +} /* namespace libcamera::ipa::ipu3::aic */ diff --git a/aic/parameter_encoder.h b/aic/parameter_encoder.h new file mode 100644 index 0000000..08d3573 --- /dev/null +++ b/aic/parameter_encoder.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (C) 2017 Intel Corporation. + * + * ParameterEncoder.h: Encode AIC parameters to IPU3 kernel interface + * + * This implementation is highly derived from ChromeOS: + * platform2/camera/hal/intel/ipu3/psl/ipu3/workers/IPU3AicToFwEncoder.h + */ + +#include <ia_imaging/ia_aiq.h> +#include <linux/intel-ipu3.h> + +/* We wrap the AIC headers to disable compiler warnings */ +#include "kbl_aic.h" + +#ifndef IPA_IPU3_PARAMETER_ENCODER +#define IPA_IPU3_PARAMETER_ENCODER + +namespace libcamera::ipa::ipu3::aic { + +namespace ParameterEncoder { +void encode(aic_config *config, ipu3_uapi_params *params); +} + +} /* namespace libcamera::ipa::ipu3::aic */ + +#endif /* IPA_IPU3_PARAMETER_ENCODER */ |