1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for Intel Camera Imaging ISP subsystem.
4  * Copyright (c) 2015, Intel Corporation.
5  */
6 
7 #include "type_support.h"
8 #include "ia_css_bnlm.host.h"
9 
10 #ifndef IA_CSS_NO_DEBUG
11 #include "ia_css_debug.h" /* ia_css_debug_dtrace() */
12 #endif
13 #include <assert_support.h>
14 
15 #define BNLM_DIV_LUT_SIZE	(12)
16 static const s32 div_lut_nearests[BNLM_DIV_LUT_SIZE] = {
17 	0, 454, 948, 1484, 2070, 2710, 3412, 4184, 5035, 5978, 7025, 8191
18 };
19 
20 static const s32 div_lut_slopes[BNLM_DIV_LUT_SIZE] = {
21 	-7760, -6960, -6216, -5536, -4912, -4344, -3832, -3360, -2936, -2552, -2208, -2208
22     };
23 
24 static const s32 div_lut_intercepts[BNLM_DIV_LUT_SIZE] = {
25 	8184, 7752, 7336, 6928, 6536, 6152, 5776, 5416, 5064, 4728, 4408, 4408
26 };
27 
28 /* Encodes a look-up table from BNLM public parameters to vmem parameters.
29  * Input:
30  *	lut	:	bnlm_lut struct containing encoded vmem parameters look-up table
31  *	lut_thr	:	array containing threshold values for lut
32  *	lut_val	:	array containing output values related to lut_thr
33  *	lut_size:	Size of lut_val array
34  */
35 static inline void
bnlm_lut_encode(struct bnlm_lut * lut,const int32_t * lut_thr,const s32 * lut_val,const uint32_t lut_size)36 bnlm_lut_encode(struct bnlm_lut *lut, const int32_t *lut_thr,
37 		const s32 *lut_val, const uint32_t lut_size)
38 {
39 	u32 blk, i;
40 	const u32 block_size = 16;
41 	const u32 total_blocks = ISP_VEC_NELEMS / block_size;
42 
43 	/* Create VMEM LUTs from the threshold and value arrays.
44 	 *
45 	 * Min size of the LUT is 2 entries.
46 	 *
47 	 * Max size of the LUT is 16 entries, so that the LUT can fit into a
48 	 * single group of 16 elements inside a vector.
49 	 * Then these elements are copied into other groups inside the same
50 	 * vector. If the LUT size is less than 16, then remaining elements are
51 	 * set to 0.
52 	 */
53 	assert((lut_size >= 2) && (lut_size <= block_size));
54 	/* array lut_thr has (lut_size-1) entries */
55 	for (i = 0; i < lut_size - 2; i++) {
56 		/* Check if the lut_thr is monotonically increasing */
57 		assert(lut_thr[i] <= lut_thr[i + 1]);
58 	}
59 
60 	/* Initialize */
61 	for (i = 0; i < total_blocks * block_size; i++) {
62 		lut->thr[0][i] = 0;
63 		lut->val[0][i] = 0;
64 	}
65 
66 	/* Copy all data */
67 	for (i = 0; i < lut_size - 1; i++) {
68 		lut->thr[0][i] = lut_thr[i];
69 		lut->val[0][i] = lut_val[i];
70 	}
71 	lut->val[0][i] = lut_val[i]; /* val has one more element than thr */
72 
73 	/* Copy data from first block to all blocks */
74 	for (blk = 1; blk < total_blocks; blk++) {
75 		u32 blk_offset = blk * block_size;
76 
77 		for (i = 1; i < lut_size; i++) {
78 			lut->thr[0][blk_offset + i] = lut->thr[0][i];
79 			lut->val[0][blk_offset + i] = lut->val[0][i];
80 		}
81 	}
82 }
83 
84 /*
85  * - Encodes BNLM public parameters into VMEM parameters
86  * - Generates VMEM parameters which will needed internally ISP
87  */
88 void
ia_css_bnlm_vmem_encode(struct bnlm_vmem_params * to,const struct ia_css_bnlm_config * from,size_t size)89 ia_css_bnlm_vmem_encode(
90     struct bnlm_vmem_params *to,
91     const struct ia_css_bnlm_config *from,
92     size_t size)
93 {
94 	int i;
95 	(void)size;
96 
97 	/* Initialize LUTs in VMEM parameters */
98 	bnlm_lut_encode(&to->mu_root_lut, from->mu_root_lut_thr, from->mu_root_lut_val,
99 			16);
100 	bnlm_lut_encode(&to->sad_norm_lut, from->sad_norm_lut_thr,
101 			from->sad_norm_lut_val, 16);
102 	bnlm_lut_encode(&to->sig_detail_lut, from->sig_detail_lut_thr,
103 			from->sig_detail_lut_val, 16);
104 	bnlm_lut_encode(&to->sig_rad_lut, from->sig_rad_lut_thr, from->sig_rad_lut_val,
105 			16);
106 	bnlm_lut_encode(&to->rad_pow_lut, from->rad_pow_lut_thr, from->rad_pow_lut_val,
107 			16);
108 	bnlm_lut_encode(&to->nl_0_lut, from->nl_0_lut_thr, from->nl_0_lut_val, 16);
109 	bnlm_lut_encode(&to->nl_1_lut, from->nl_1_lut_thr, from->nl_1_lut_val, 16);
110 	bnlm_lut_encode(&to->nl_2_lut, from->nl_2_lut_thr, from->nl_2_lut_val, 16);
111 	bnlm_lut_encode(&to->nl_3_lut, from->nl_3_lut_thr, from->nl_3_lut_val, 16);
112 
113 	/* Initialize arrays in VMEM parameters */
114 	memset(to->nl_th, 0, sizeof(to->nl_th));
115 	to->nl_th[0][0] = from->nl_th[0];
116 	to->nl_th[0][1] = from->nl_th[1];
117 	to->nl_th[0][2] = from->nl_th[2];
118 
119 	memset(to->match_quality_max_idx, 0, sizeof(to->match_quality_max_idx));
120 	to->match_quality_max_idx[0][0] = from->match_quality_max_idx[0];
121 	to->match_quality_max_idx[0][1] = from->match_quality_max_idx[1];
122 	to->match_quality_max_idx[0][2] = from->match_quality_max_idx[2];
123 	to->match_quality_max_idx[0][3] = from->match_quality_max_idx[3];
124 
125 	bnlm_lut_encode(&to->div_lut, div_lut_nearests, div_lut_slopes,
126 			BNLM_DIV_LUT_SIZE);
127 	memset(to->div_lut_intercepts, 0, sizeof(to->div_lut_intercepts));
128 	for (i = 0; i < BNLM_DIV_LUT_SIZE; i++) {
129 		to->div_lut_intercepts[0][i] = div_lut_intercepts[i];
130 	}
131 
132 	memset(to->power_of_2, 0, sizeof(to->power_of_2));
133 	for (i = 0; i < (ISP_VEC_ELEMBITS - 1); i++) {
134 		to->power_of_2[0][i] = 1 << i;
135 	}
136 }
137 
138 /* - Encodes BNLM public parameters into DMEM parameters */
139 void
ia_css_bnlm_encode(struct bnlm_dmem_params * to,const struct ia_css_bnlm_config * from,size_t size)140 ia_css_bnlm_encode(
141     struct bnlm_dmem_params *to,
142     const struct ia_css_bnlm_config *from,
143     size_t size)
144 {
145 	(void)size;
146 	to->rad_enable = from->rad_enable;
147 	to->rad_x_origin = from->rad_x_origin;
148 	to->rad_y_origin = from->rad_y_origin;
149 	to->avg_min_th = from->avg_min_th;
150 	to->max_min_th = from->max_min_th;
151 
152 	to->exp_coeff_a = from->exp_coeff_a;
153 	to->exp_coeff_b = from->exp_coeff_b;
154 	to->exp_coeff_c = from->exp_coeff_c;
155 	to->exp_exponent = from->exp_exponent;
156 }
157 
158 /* Prints debug traces for BNLM public parameters */
159 void
ia_css_bnlm_debug_trace(const struct ia_css_bnlm_config * config,unsigned int level)160 ia_css_bnlm_debug_trace(
161     const struct ia_css_bnlm_config *config,
162     unsigned int level)
163 {
164 	if (!config)
165 		return;
166 
167 #ifndef IA_CSS_NO_DEBUG
168 	ia_css_debug_dtrace(level, "BNLM:\n");
169 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_enable", config->rad_enable);
170 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_x_origin",
171 			    config->rad_x_origin);
172 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rad_y_origin",
173 			    config->rad_y_origin);
174 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "avg_min_th", config->avg_min_th);
175 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "max_min_th", config->max_min_th);
176 
177 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_a",
178 			    config->exp_coeff_a);
179 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_b",
180 			    config->exp_coeff_b);
181 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_coeff_c",
182 			    config->exp_coeff_c);
183 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "exp_exponent",
184 			    config->exp_exponent);
185 
186 	/* ToDo: print traces for LUTs */
187 #endif /* IA_CSS_NO_DEBUG */
188 }
189