1*f5fbb83fSMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0
29d4fa1a1SMauro Carvalho Chehab /*
39d4fa1a1SMauro Carvalho Chehab  * Support for Intel Camera Imaging ISP subsystem.
49d4fa1a1SMauro Carvalho Chehab  * Copyright (c) 2015, Intel Corporation.
59d4fa1a1SMauro Carvalho Chehab  *
69d4fa1a1SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or modify it
79d4fa1a1SMauro Carvalho Chehab  * under the terms and conditions of the GNU General Public License,
89d4fa1a1SMauro Carvalho Chehab  * version 2, as published by the Free Software Foundation.
99d4fa1a1SMauro Carvalho Chehab  *
109d4fa1a1SMauro Carvalho Chehab  * This program is distributed in the hope it will be useful, but WITHOUT
119d4fa1a1SMauro Carvalho Chehab  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
129d4fa1a1SMauro Carvalho Chehab  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
139d4fa1a1SMauro Carvalho Chehab  * more details.
149d4fa1a1SMauro Carvalho Chehab  */
159d4fa1a1SMauro Carvalho Chehab 
169d4fa1a1SMauro Carvalho Chehab #include "type_support.h"
179d4fa1a1SMauro Carvalho Chehab #include "ia_css_bnlm.host.h"
189d4fa1a1SMauro Carvalho Chehab 
199d4fa1a1SMauro Carvalho Chehab #ifndef IA_CSS_NO_DEBUG
209d4fa1a1SMauro Carvalho Chehab #include "ia_css_debug.h" /* ia_css_debug_dtrace() */
219d4fa1a1SMauro Carvalho Chehab #endif
229d4fa1a1SMauro Carvalho Chehab #include <assert_support.h>
239d4fa1a1SMauro Carvalho Chehab 
249d4fa1a1SMauro Carvalho Chehab #define BNLM_DIV_LUT_SIZE	(12)
259d4fa1a1SMauro Carvalho Chehab static const s32 div_lut_nearests[BNLM_DIV_LUT_SIZE] = {
269d4fa1a1SMauro Carvalho Chehab 	0, 454, 948, 1484, 2070, 2710, 3412, 4184, 5035, 5978, 7025, 8191
279d4fa1a1SMauro Carvalho Chehab };
289d4fa1a1SMauro Carvalho Chehab 
299d4fa1a1SMauro Carvalho Chehab static const s32 div_lut_slopes[BNLM_DIV_LUT_SIZE] = {
309d4fa1a1SMauro Carvalho Chehab 	-7760, -6960, -6216, -5536, -4912, -4344, -3832, -3360, -2936, -2552, -2208, -2208
319d4fa1a1SMauro Carvalho Chehab     };
329d4fa1a1SMauro Carvalho Chehab 
339d4fa1a1SMauro Carvalho Chehab static const s32 div_lut_intercepts[BNLM_DIV_LUT_SIZE] = {
349d4fa1a1SMauro Carvalho Chehab 	8184, 7752, 7336, 6928, 6536, 6152, 5776, 5416, 5064, 4728, 4408, 4408
359d4fa1a1SMauro Carvalho Chehab };
369d4fa1a1SMauro Carvalho Chehab 
379d4fa1a1SMauro Carvalho Chehab /* Encodes a look-up table from BNLM public parameters to vmem parameters.
389d4fa1a1SMauro Carvalho Chehab  * Input:
399d4fa1a1SMauro Carvalho Chehab  *	lut	:	bnlm_lut struct containing encoded vmem parameters look-up table
409d4fa1a1SMauro Carvalho Chehab  *	lut_thr	:	array containing threshold values for lut
419d4fa1a1SMauro Carvalho Chehab  *	lut_val	:	array containing output values related to lut_thr
429d4fa1a1SMauro Carvalho Chehab  *	lut_size:	Size of lut_val array
439d4fa1a1SMauro Carvalho Chehab  */
449d4fa1a1SMauro Carvalho Chehab static inline void
bnlm_lut_encode(struct bnlm_lut * lut,const int32_t * lut_thr,const s32 * lut_val,const uint32_t lut_size)459d4fa1a1SMauro Carvalho Chehab bnlm_lut_encode(struct bnlm_lut *lut, const int32_t *lut_thr,
46abbd669dSMauro Carvalho Chehab 		const s32 *lut_val, const uint32_t lut_size)
479d4fa1a1SMauro Carvalho Chehab {
489d4fa1a1SMauro Carvalho Chehab 	u32 blk, i;
499d4fa1a1SMauro Carvalho Chehab 	const u32 block_size = 16;
509d4fa1a1SMauro Carvalho Chehab 	const u32 total_blocks = ISP_VEC_NELEMS / block_size;
519d4fa1a1SMauro Carvalho Chehab 
529d4fa1a1SMauro Carvalho Chehab 	/* Create VMEM LUTs from the threshold and value arrays.
539d4fa1a1SMauro Carvalho Chehab 	 *
549d4fa1a1SMauro Carvalho Chehab 	 * Min size of the LUT is 2 entries.
559d4fa1a1SMauro Carvalho Chehab 	 *
569d4fa1a1SMauro Carvalho Chehab 	 * Max size of the LUT is 16 entries, so that the LUT can fit into a
579d4fa1a1SMauro Carvalho Chehab 	 * single group of 16 elements inside a vector.
589d4fa1a1SMauro Carvalho Chehab 	 * Then these elements are copied into other groups inside the same
599d4fa1a1SMauro Carvalho Chehab 	 * vector. If the LUT size is less than 16, then remaining elements are
609d4fa1a1SMauro Carvalho Chehab 	 * set to 0.
619d4fa1a1SMauro Carvalho Chehab 	 */
629d4fa1a1SMauro Carvalho Chehab 	assert((lut_size >= 2) && (lut_size <= block_size));
639d4fa1a1SMauro Carvalho Chehab 	/* array lut_thr has (lut_size-1) entries */
649d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < lut_size - 2; i++) {
659d4fa1a1SMauro Carvalho Chehab 		/* Check if the lut_thr is monotonically increasing */
669d4fa1a1SMauro Carvalho Chehab 		assert(lut_thr[i] <= lut_thr[i + 1]);
679d4fa1a1SMauro Carvalho Chehab 	}
689d4fa1a1SMauro Carvalho Chehab 
699d4fa1a1SMauro Carvalho Chehab 	/* Initialize */
709d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < total_blocks * block_size; i++) {
719d4fa1a1SMauro Carvalho Chehab 		lut->thr[0][i] = 0;
729d4fa1a1SMauro Carvalho Chehab 		lut->val[0][i] = 0;
739d4fa1a1SMauro Carvalho Chehab 	}
749d4fa1a1SMauro Carvalho Chehab 
759d4fa1a1SMauro Carvalho Chehab 	/* Copy all data */
769d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < lut_size - 1; i++) {
779d4fa1a1SMauro Carvalho Chehab 		lut->thr[0][i] = lut_thr[i];
789d4fa1a1SMauro Carvalho Chehab 		lut->val[0][i] = lut_val[i];
799d4fa1a1SMauro Carvalho Chehab 	}
809d4fa1a1SMauro Carvalho Chehab 	lut->val[0][i] = lut_val[i]; /* val has one more element than thr */
819d4fa1a1SMauro Carvalho Chehab 
829d4fa1a1SMauro Carvalho Chehab 	/* Copy data from first block to all blocks */
839d4fa1a1SMauro Carvalho Chehab 	for (blk = 1; blk < total_blocks; blk++) {
849d4fa1a1SMauro Carvalho Chehab 		u32 blk_offset = blk * block_size;
859d4fa1a1SMauro Carvalho Chehab 
869d4fa1a1SMauro Carvalho Chehab 		for (i = 1; i < lut_size; i++) {
879d4fa1a1SMauro Carvalho Chehab 			lut->thr[0][blk_offset + i] = lut->thr[0][i];
889d4fa1a1SMauro Carvalho Chehab 			lut->val[0][blk_offset + i] = lut->val[0][i];
899d4fa1a1SMauro Carvalho Chehab 		}
909d4fa1a1SMauro Carvalho Chehab 	}
919d4fa1a1SMauro Carvalho Chehab }
929d4fa1a1SMauro Carvalho Chehab 
939d4fa1a1SMauro Carvalho Chehab /*
949d4fa1a1SMauro Carvalho Chehab  * - Encodes BNLM public parameters into VMEM parameters
959d4fa1a1SMauro Carvalho Chehab  * - Generates VMEM parameters which will needed internally ISP
969d4fa1a1SMauro Carvalho Chehab  */
979d4fa1a1SMauro Carvalho Chehab void
ia_css_bnlm_vmem_encode(struct bnlm_vmem_params * to,const struct ia_css_bnlm_config * from,size_t size)989d4fa1a1SMauro Carvalho Chehab ia_css_bnlm_vmem_encode(
999d4fa1a1SMauro Carvalho Chehab     struct bnlm_vmem_params *to,
1009d4fa1a1SMauro Carvalho Chehab     const struct ia_css_bnlm_config *from,
1019d4fa1a1SMauro Carvalho Chehab     size_t size)
1029d4fa1a1SMauro Carvalho Chehab {
1039d4fa1a1SMauro Carvalho Chehab 	int i;
1049d4fa1a1SMauro Carvalho Chehab 	(void)size;
1059d4fa1a1SMauro Carvalho Chehab 
1069d4fa1a1SMauro Carvalho Chehab 	/* Initialize LUTs in VMEM parameters */
1079d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->mu_root_lut, from->mu_root_lut_thr, from->mu_root_lut_val,
1089d4fa1a1SMauro Carvalho Chehab 			16);
1099d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->sad_norm_lut, from->sad_norm_lut_thr,
1109d4fa1a1SMauro Carvalho Chehab 			from->sad_norm_lut_val, 16);
1119d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->sig_detail_lut, from->sig_detail_lut_thr,
1129d4fa1a1SMauro Carvalho Chehab 			from->sig_detail_lut_val, 16);
1139d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->sig_rad_lut, from->sig_rad_lut_thr, from->sig_rad_lut_val,
1149d4fa1a1SMauro Carvalho Chehab 			16);
1159d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->rad_pow_lut, from->rad_pow_lut_thr, from->rad_pow_lut_val,
1169d4fa1a1SMauro Carvalho Chehab 			16);
1179d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->nl_0_lut, from->nl_0_lut_thr, from->nl_0_lut_val, 16);
1189d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->nl_1_lut, from->nl_1_lut_thr, from->nl_1_lut_val, 16);
1199d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->nl_2_lut, from->nl_2_lut_thr, from->nl_2_lut_val, 16);
1209d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->nl_3_lut, from->nl_3_lut_thr, from->nl_3_lut_val, 16);
1219d4fa1a1SMauro Carvalho Chehab 
1229d4fa1a1SMauro Carvalho Chehab 	/* Initialize arrays in VMEM parameters */
1239d4fa1a1SMauro Carvalho Chehab 	memset(to->nl_th, 0, sizeof(to->nl_th));
1249d4fa1a1SMauro Carvalho Chehab 	to->nl_th[0][0] = from->nl_th[0];
1259d4fa1a1SMauro Carvalho Chehab 	to->nl_th[0][1] = from->nl_th[1];
1269d4fa1a1SMauro Carvalho Chehab 	to->nl_th[0][2] = from->nl_th[2];
1279d4fa1a1SMauro Carvalho Chehab 
1289d4fa1a1SMauro Carvalho Chehab 	memset(to->match_quality_max_idx, 0, sizeof(to->match_quality_max_idx));
1299d4fa1a1SMauro Carvalho Chehab 	to->match_quality_max_idx[0][0] = from->match_quality_max_idx[0];
1309d4fa1a1SMauro Carvalho Chehab 	to->match_quality_max_idx[0][1] = from->match_quality_max_idx[1];
1319d4fa1a1SMauro Carvalho Chehab 	to->match_quality_max_idx[0][2] = from->match_quality_max_idx[2];
1329d4fa1a1SMauro Carvalho Chehab 	to->match_quality_max_idx[0][3] = from->match_quality_max_idx[3];
1339d4fa1a1SMauro Carvalho Chehab 
1349d4fa1a1SMauro Carvalho Chehab 	bnlm_lut_encode(&to->div_lut, div_lut_nearests, div_lut_slopes,
1359d4fa1a1SMauro Carvalho Chehab 			BNLM_DIV_LUT_SIZE);
1369d4fa1a1SMauro Carvalho Chehab 	memset(to->div_lut_intercepts, 0, sizeof(to->div_lut_intercepts));
1379d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < BNLM_DIV_LUT_SIZE; i++) {
1389d4fa1a1SMauro Carvalho Chehab 		to->div_lut_intercepts[0][i] = div_lut_intercepts[i];
1399d4fa1a1SMauro Carvalho Chehab 	}
1409d4fa1a1SMauro Carvalho Chehab 
1419d4fa1a1SMauro Carvalho Chehab 	memset(to->power_of_2, 0, sizeof(to->power_of_2));
1429d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < (ISP_VEC_ELEMBITS - 1); i++) {
1439d4fa1a1SMauro Carvalho Chehab 		to->power_of_2[0][i] = 1 << i;
1449d4fa1a1SMauro Carvalho Chehab 	}
1459d4fa1a1SMauro Carvalho Chehab }
1469d4fa1a1SMauro Carvalho Chehab 
1479d4fa1a1SMauro Carvalho Chehab /* - Encodes BNLM public parameters into DMEM parameters */
1489d4fa1a1SMauro Carvalho Chehab void
ia_css_bnlm_encode(struct bnlm_dmem_params * to,const struct ia_css_bnlm_config * from,size_t size)1499d4fa1a1SMauro Carvalho Chehab ia_css_bnlm_encode(
1509d4fa1a1SMauro Carvalho Chehab     struct bnlm_dmem_params *to,
1519d4fa1a1SMauro Carvalho Chehab     const struct ia_css_bnlm_config *from,
1529d4fa1a1SMauro Carvalho Chehab     size_t size)
1539d4fa1a1SMauro Carvalho Chehab {
1549d4fa1a1SMauro Carvalho Chehab 	(void)size;
1559d4fa1a1SMauro Carvalho Chehab 	to->rad_enable = from->rad_enable;
1569d4fa1a1SMauro Carvalho Chehab 	to->rad_x_origin = from->rad_x_origin;
1579d4fa1a1SMauro Carvalho Chehab 	to->rad_y_origin = from->rad_y_origin;
1589d4fa1a1SMauro Carvalho Chehab 	to->avg_min_th = from->avg_min_th;
1599d4fa1a1SMauro Carvalho Chehab 	to->max_min_th = from->max_min_th;
1609d4fa1a1SMauro Carvalho Chehab 
1619d4fa1a1SMauro Carvalho Chehab 	to->exp_coeff_a = from->exp_coeff_a;
1629d4fa1a1SMauro Carvalho Chehab 	to->exp_coeff_b = from->exp_coeff_b;
1639d4fa1a1SMauro Carvalho Chehab 	to->exp_coeff_c = from->exp_coeff_c;
1649d4fa1a1SMauro Carvalho Chehab 	to->exp_exponent = from->exp_exponent;
1659d4fa1a1SMauro Carvalho Chehab }
1669d4fa1a1SMauro Carvalho Chehab 
1679d4fa1a1SMauro Carvalho Chehab /* Prints debug traces for BNLM public parameters */
1689d4fa1a1SMauro Carvalho Chehab void
ia_css_bnlm_debug_trace(const struct ia_css_bnlm_config * config,unsigned int level)1699d4fa1a1SMauro Carvalho Chehab ia_css_bnlm_debug_trace(
1709d4fa1a1SMauro Carvalho Chehab     const struct ia_css_bnlm_config *config,
1719d4fa1a1SMauro Carvalho Chehab     unsigned int level)
1729d4fa1a1SMauro Carvalho Chehab {
1739d4fa1a1SMauro Carvalho Chehab 	if (!config)
1749d4fa1a1SMauro Carvalho Chehab 		return;
1759d4fa1a1SMauro Carvalho Chehab 
1769d4fa1a1SMauro Carvalho Chehab #ifndef IA_CSS_NO_DEBUG
1779d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "BNLM:\n");
1789d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_enable", config->rad_enable);
1799d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_x_origin",
1809d4fa1a1SMauro Carvalho Chehab 			    config->rad_x_origin);
1819d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_y_origin",
1829d4fa1a1SMauro Carvalho Chehab 			    config->rad_y_origin);
1839d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "avg_min_th", config->avg_min_th);
1849d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "max_min_th", config->max_min_th);
1859d4fa1a1SMauro Carvalho Chehab 
1869d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_a",
1879d4fa1a1SMauro Carvalho Chehab 			    config->exp_coeff_a);
1889d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_b",
1899d4fa1a1SMauro Carvalho Chehab 			    config->exp_coeff_b);
1909d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_c",
1919d4fa1a1SMauro Carvalho Chehab 			    config->exp_coeff_c);
1929d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_exponent",
1939d4fa1a1SMauro Carvalho Chehab 			    config->exp_exponent);
1949d4fa1a1SMauro Carvalho Chehab 
1959d4fa1a1SMauro Carvalho Chehab 	/* ToDo: print traces for LUTs */
1969d4fa1a1SMauro Carvalho Chehab #endif /* IA_CSS_NO_DEBUG */
1979d4fa1a1SMauro Carvalho Chehab }
198