| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Support for Intel Camera Imaging ISP subsystem. |
| * Copyright (c) 2015, Intel Corporation. |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms and conditions of the GNU General Public License, |
| * version 2, as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| */ |
| |
| #include "type_support.h" |
| #include "ia_css_bnlm.host.h" |
| |
| #ifndef IA_CSS_NO_DEBUG |
| #include "ia_css_debug.h" /* ia_css_debug_dtrace() */ |
| #endif |
| #include <assert_support.h> |
| |
| #define BNLM_DIV_LUT_SIZE (12) |
| static const s32 div_lut_nearests[BNLM_DIV_LUT_SIZE] = { |
| 0, 454, 948, 1484, 2070, 2710, 3412, 4184, 5035, 5978, 7025, 8191 |
| }; |
| |
| static const s32 div_lut_slopes[BNLM_DIV_LUT_SIZE] = { |
| -7760, -6960, -6216, -5536, -4912, -4344, -3832, -3360, -2936, -2552, -2208, -2208 |
| }; |
| |
| static const s32 div_lut_intercepts[BNLM_DIV_LUT_SIZE] = { |
| 8184, 7752, 7336, 6928, 6536, 6152, 5776, 5416, 5064, 4728, 4408, 4408 |
| }; |
| |
| /* Encodes a look-up table from BNLM public parameters to vmem parameters. |
| * Input: |
| * lut : bnlm_lut struct containing encoded vmem parameters look-up table |
| * lut_thr : array containing threshold values for lut |
| * lut_val : array containing output values related to lut_thr |
| * lut_size: Size of lut_val array |
| */ |
| static inline void |
| bnlm_lut_encode(struct bnlm_lut *lut, const int32_t *lut_thr, |
| const s32 *lut_val, const uint32_t lut_size) |
| { |
| u32 blk, i; |
| const u32 block_size = 16; |
| const u32 total_blocks = ISP_VEC_NELEMS / block_size; |
| |
| /* Create VMEM LUTs from the threshold and value arrays. |
| * |
| * Min size of the LUT is 2 entries. |
| * |
| * Max size of the LUT is 16 entries, so that the LUT can fit into a |
| * single group of 16 elements inside a vector. |
| * Then these elements are copied into other groups inside the same |
| * vector. If the LUT size is less than 16, then remaining elements are |
| * set to 0. |
| */ |
| assert((lut_size >= 2) && (lut_size <= block_size)); |
| /* array lut_thr has (lut_size-1) entries */ |
| for (i = 0; i < lut_size - 2; i++) { |
| /* Check if the lut_thr is monotonically increasing */ |
| assert(lut_thr[i] <= lut_thr[i + 1]); |
| } |
| |
| /* Initialize */ |
| for (i = 0; i < total_blocks * block_size; i++) { |
| lut->thr[0][i] = 0; |
| lut->val[0][i] = 0; |
| } |
| |
| /* Copy all data */ |
| for (i = 0; i < lut_size - 1; i++) { |
| lut->thr[0][i] = lut_thr[i]; |
| lut->val[0][i] = lut_val[i]; |
| } |
| lut->val[0][i] = lut_val[i]; /* val has one more element than thr */ |
| |
| /* Copy data from first block to all blocks */ |
| for (blk = 1; blk < total_blocks; blk++) { |
| u32 blk_offset = blk * block_size; |
| |
| for (i = 1; i < lut_size; i++) { |
| lut->thr[0][blk_offset + i] = lut->thr[0][i]; |
| lut->val[0][blk_offset + i] = lut->val[0][i]; |
| } |
| } |
| } |
| |
| /* |
| * - Encodes BNLM public parameters into VMEM parameters |
| * - Generates VMEM parameters which will needed internally ISP |
| */ |
| void |
| ia_css_bnlm_vmem_encode( |
| struct bnlm_vmem_params *to, |
| const struct ia_css_bnlm_config *from, |
| size_t size) |
| { |
| int i; |
| (void)size; |
| |
| /* Initialize LUTs in VMEM parameters */ |
| bnlm_lut_encode(&to->mu_root_lut, from->mu_root_lut_thr, from->mu_root_lut_val, |
| 16); |
| bnlm_lut_encode(&to->sad_norm_lut, from->sad_norm_lut_thr, |
| from->sad_norm_lut_val, 16); |
| bnlm_lut_encode(&to->sig_detail_lut, from->sig_detail_lut_thr, |
| from->sig_detail_lut_val, 16); |
| bnlm_lut_encode(&to->sig_rad_lut, from->sig_rad_lut_thr, from->sig_rad_lut_val, |
| 16); |
| bnlm_lut_encode(&to->rad_pow_lut, from->rad_pow_lut_thr, from->rad_pow_lut_val, |
| 16); |
| bnlm_lut_encode(&to->nl_0_lut, from->nl_0_lut_thr, from->nl_0_lut_val, 16); |
| bnlm_lut_encode(&to->nl_1_lut, from->nl_1_lut_thr, from->nl_1_lut_val, 16); |
| bnlm_lut_encode(&to->nl_2_lut, from->nl_2_lut_thr, from->nl_2_lut_val, 16); |
| bnlm_lut_encode(&to->nl_3_lut, from->nl_3_lut_thr, from->nl_3_lut_val, 16); |
| |
| /* Initialize arrays in VMEM parameters */ |
| memset(to->nl_th, 0, sizeof(to->nl_th)); |
| to->nl_th[0][0] = from->nl_th[0]; |
| to->nl_th[0][1] = from->nl_th[1]; |
| to->nl_th[0][2] = from->nl_th[2]; |
| |
| memset(to->match_quality_max_idx, 0, sizeof(to->match_quality_max_idx)); |
| to->match_quality_max_idx[0][0] = from->match_quality_max_idx[0]; |
| to->match_quality_max_idx[0][1] = from->match_quality_max_idx[1]; |
| to->match_quality_max_idx[0][2] = from->match_quality_max_idx[2]; |
| to->match_quality_max_idx[0][3] = from->match_quality_max_idx[3]; |
| |
| bnlm_lut_encode(&to->div_lut, div_lut_nearests, div_lut_slopes, |
| BNLM_DIV_LUT_SIZE); |
| memset(to->div_lut_intercepts, 0, sizeof(to->div_lut_intercepts)); |
| for (i = 0; i < BNLM_DIV_LUT_SIZE; i++) { |
| to->div_lut_intercepts[0][i] = div_lut_intercepts[i]; |
| } |
| |
| memset(to->power_of_2, 0, sizeof(to->power_of_2)); |
| for (i = 0; i < (ISP_VEC_ELEMBITS - 1); i++) { |
| to->power_of_2[0][i] = 1 << i; |
| } |
| } |
| |
| /* - Encodes BNLM public parameters into DMEM parameters */ |
| void |
| ia_css_bnlm_encode( |
| struct bnlm_dmem_params *to, |
| const struct ia_css_bnlm_config *from, |
| size_t size) |
| { |
| (void)size; |
| to->rad_enable = from->rad_enable; |
| to->rad_x_origin = from->rad_x_origin; |
| to->rad_y_origin = from->rad_y_origin; |
| to->avg_min_th = from->avg_min_th; |
| to->max_min_th = from->max_min_th; |
| |
| to->exp_coeff_a = from->exp_coeff_a; |
| to->exp_coeff_b = from->exp_coeff_b; |
| to->exp_coeff_c = from->exp_coeff_c; |
| to->exp_exponent = from->exp_exponent; |
| } |
| |
| /* Prints debug traces for BNLM public parameters */ |
| void |
| ia_css_bnlm_debug_trace( |
| const struct ia_css_bnlm_config *config, |
| unsigned int level) |
| { |
| if (!config) |
| return; |
| |
| #ifndef IA_CSS_NO_DEBUG |
| ia_css_debug_dtrace(level, "BNLM:\n"); |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_enable", config->rad_enable); |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_x_origin", |
| config->rad_x_origin); |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_y_origin", |
| config->rad_y_origin); |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "avg_min_th", config->avg_min_th); |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "max_min_th", config->max_min_th); |
| |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_a", |
| config->exp_coeff_a); |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_b", |
| config->exp_coeff_b); |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_c", |
| config->exp_coeff_c); |
| ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_exponent", |
| config->exp_exponent); |
| |
| /* ToDo: print traces for LUTs */ |
| #endif /* IA_CSS_NO_DEBUG */ |
| } |