xref: /linux/drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8.host.c (revision f3c450f5f13221798de7acbe667d55fbadc63b94)
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 #ifndef IA_CSS_NO_DEBUG
8 #include "ia_css_debug.h"
9 #endif
10 
11 #include "type_support.h"
12 #include "assert_support.h"
13 #include "math_support.h" /* for min and max */
14 
15 #include "ia_css_eed1_8.host.h"
16 
17 /* WARNING1: Number of inv points should be less or equal to 16,
18  * due to implementation limitation. See kernel design document
19  * for more details.
20  * WARNING2: Do not modify the number of inv points without correcting
21  * the EED1_8 kernel implementation assumptions.
22  */
23 #define NUMBER_OF_CHGRINV_POINTS 15
24 #define NUMBER_OF_TCINV_POINTS 9
25 #define NUMBER_OF_FCINV_POINTS 9
26 
27 static const s16 chgrinv_x[NUMBER_OF_CHGRINV_POINTS] = {
28 	0, 16, 64, 144, 272, 448, 672, 976,
29 	1376, 1888, 2528, 3312, 4256, 5376, 6688
30 };
31 
32 static const s16 chgrinv_a[NUMBER_OF_CHGRINV_POINTS] = {
33 	-7171, -256, -29, -3456, -1071, -475, -189, -102,
34 	    -48, -38, -10, -9, -7, -6, 0
35     };
36 
37 static const s16 chgrinv_b[NUMBER_OF_CHGRINV_POINTS] = {
38 	8191, 1021, 256, 114, 60, 37, 24, 17,
39 	12, 9, 6, 5, 4, 3, 2
40 };
41 
42 static const s16 chgrinv_c[NUMBER_OF_CHGRINV_POINTS] = {
43 	1, 1, 1, 0, 0, 0, 0, 0,
44 	0, 0, 0, 0, 0, 0, 0
45 };
46 
47 static const s16 tcinv_x[NUMBER_OF_TCINV_POINTS] = {
48 	0, 4, 11, 23, 42, 68, 102, 148, 205
49 };
50 
51 static const s16 tcinv_a[NUMBER_OF_TCINV_POINTS] = {
52 	-6364, -631, -126, -34, -13, -6, -4452, -2156, 0
53     };
54 
55 static const s16 tcinv_b[NUMBER_OF_TCINV_POINTS] = {
56 	8191, 1828, 726, 352, 197, 121, 80, 55, 40
57 };
58 
59 static const s16 tcinv_c[NUMBER_OF_TCINV_POINTS] = {
60 	1, 1, 1, 1, 1, 1, 0, 0, 0
61 };
62 
63 static const s16 fcinv_x[NUMBER_OF_FCINV_POINTS] = {
64 	0, 80, 216, 456, 824, 1344, 2040, 2952, 4096
65 };
66 
67 static const s16 fcinv_a[NUMBER_OF_FCINV_POINTS] = {
68 	-5244, -486, -86, -2849, -961, -400, -180, -86, 0
69     };
70 
71 static const s16 fcinv_b[NUMBER_OF_FCINV_POINTS] = {
72 	8191, 1637, 607, 287, 159, 98, 64, 44, 32
73 };
74 
75 static const s16 fcinv_c[NUMBER_OF_FCINV_POINTS] = {
76 	1, 1, 1, 0, 0, 0, 0, 0, 0
77 };
78 
79 void
80 ia_css_eed1_8_vmem_encode(
81     struct eed1_8_vmem_params *to,
82     const struct ia_css_eed1_8_config *from,
83     size_t size)
84 {
85 	unsigned int i, j, base;
86 	const unsigned int total_blocks = 4;
87 	const unsigned int shuffle_block = 16;
88 
89 	(void)size;
90 
91 	/* Init */
92 	for (i = 0; i < ISP_VEC_NELEMS; i++) {
93 		to->e_dew_enh_x[0][i] = 0;
94 		to->e_dew_enh_y[0][i] = 0;
95 		to->e_dew_enh_a[0][i] = 0;
96 		to->e_dew_enh_f[0][i] = 0;
97 		to->chgrinv_x[0][i] = 0;
98 		to->chgrinv_a[0][i] = 0;
99 		to->chgrinv_b[0][i] = 0;
100 		to->chgrinv_c[0][i] = 0;
101 		to->tcinv_x[0][i] = 0;
102 		to->tcinv_a[0][i] = 0;
103 		to->tcinv_b[0][i] = 0;
104 		to->tcinv_c[0][i] = 0;
105 		to->fcinv_x[0][i] = 0;
106 		to->fcinv_a[0][i] = 0;
107 		to->fcinv_b[0][i] = 0;
108 		to->fcinv_c[0][i] = 0;
109 	}
110 
111 	/* Constraints on dew_enhance_seg_x and dew_enhance_seg_y:
112 	 * - values should be greater or equal to 0.
113 	 * - values should be ascending.
114 	 * - value of index zero is equal to 0.
115 	 */
116 
117 	/* Checking constraints: */
118 	/* TODO: investigate if an assert is the right way to report that
119 	 * the constraints are violated.
120 	 */
121 	for (j = 0; j < IA_CSS_NUMBER_OF_DEW_ENHANCE_SEGMENTS; j++) {
122 		assert(from->dew_enhance_seg_x[j] > -1);
123 		assert(from->dew_enhance_seg_y[j] > -1);
124 	}
125 
126 	for (j = 1; j < IA_CSS_NUMBER_OF_DEW_ENHANCE_SEGMENTS; j++) {
127 		assert(from->dew_enhance_seg_x[j] > from->dew_enhance_seg_x[j - 1]);
128 		assert(from->dew_enhance_seg_y[j] > from->dew_enhance_seg_y[j - 1]);
129 	}
130 
131 	assert(from->dew_enhance_seg_x[0] == 0);
132 	assert(from->dew_enhance_seg_y[0] == 0);
133 
134 	/* Constraints on chgrinv_x, tcinv_x and fcinv_x:
135 	 * - values should be greater or equal to 0.
136 	 * - values should be ascending.
137 	 * - value of index zero is equal to 0.
138 	 */
139 	assert(chgrinv_x[0] == 0);
140 	assert(tcinv_x[0] == 0);
141 	assert(fcinv_x[0] == 0);
142 
143 	for (j = 1; j < NUMBER_OF_CHGRINV_POINTS; j++)
144 		assert(chgrinv_x[j] > chgrinv_x[j - 1]);
145 
146 	for (j = 1; j < NUMBER_OF_TCINV_POINTS; j++)
147 		assert(tcinv_x[j] > tcinv_x[j - 1]);
148 
149 	for (j = 1; j < NUMBER_OF_FCINV_POINTS; j++)
150 		assert(fcinv_x[j] > fcinv_x[j - 1]);
151 
152 	/* The implementation of the calculating 1/x is based on the availability
153 	 * of the OP_vec_shuffle16 operation.
154 	 * A 64 element vector is split up in 4 blocks of 16 element. Each array is copied to
155 	 * a vector 4 times, (starting at 0, 16, 32 and 48). All array elements are copied or
156 	 * initialised as described in the KFS. The remaining elements of a vector are set to 0.
157 	 */
158 	/* TODO: guard this code with above assumptions */
159 	for (i = 0; i < total_blocks; i++) {
160 		base = shuffle_block * i;
161 
162 		for (j = 0; j < IA_CSS_NUMBER_OF_DEW_ENHANCE_SEGMENTS; j++) {
163 			to->e_dew_enh_x[0][base + j] = clamp(from->dew_enhance_seg_x[j],
164 							     0, 8191);
165 			to->e_dew_enh_y[0][base + j] = clamp(from->dew_enhance_seg_y[j],
166 							     -8192, 8191);
167 		}
168 
169 		for (j = 0; j < (IA_CSS_NUMBER_OF_DEW_ENHANCE_SEGMENTS - 1); j++) {
170 			to->e_dew_enh_a[0][base + j] = clamp(from->dew_enhance_seg_slope[j],
171 							     -8192, 8191);
172 			/* Convert dew_enhance_seg_exp to flag:
173 			 * 0 -> 0
174 			 * 1...13 -> 1
175 			 */
176 			to->e_dew_enh_f[0][base + j] = clamp(from->dew_enhance_seg_exp[j],
177 							     0, 13) > 0;
178 		}
179 
180 		/* Hard-coded to 0, in order to be able to handle out of
181 		 * range input in the same way as the other segments.
182 		 * See KFS for more details.
183 		 */
184 		to->e_dew_enh_a[0][base + (IA_CSS_NUMBER_OF_DEW_ENHANCE_SEGMENTS - 1)] = 0;
185 		to->e_dew_enh_f[0][base + (IA_CSS_NUMBER_OF_DEW_ENHANCE_SEGMENTS - 1)] = 0;
186 
187 		for (j = 0; j < NUMBER_OF_CHGRINV_POINTS; j++) {
188 			to->chgrinv_x[0][base + j] = chgrinv_x[j];
189 			to->chgrinv_a[0][base + j] = chgrinv_a[j];
190 			to->chgrinv_b[0][base + j] = chgrinv_b[j];
191 			to->chgrinv_c[0][base + j] = chgrinv_c[j];
192 		}
193 
194 		for (j = 0; j < NUMBER_OF_TCINV_POINTS; j++) {
195 			to->tcinv_x[0][base + j] = tcinv_x[j];
196 			to->tcinv_a[0][base + j] = tcinv_a[j];
197 			to->tcinv_b[0][base + j] = tcinv_b[j];
198 			to->tcinv_c[0][base + j] = tcinv_c[j];
199 		}
200 
201 		for (j = 0; j < NUMBER_OF_FCINV_POINTS; j++) {
202 			to->fcinv_x[0][base + j] = fcinv_x[j];
203 			to->fcinv_a[0][base + j] = fcinv_a[j];
204 			to->fcinv_b[0][base + j] = fcinv_b[j];
205 			to->fcinv_c[0][base + j] = fcinv_c[j];
206 		}
207 	}
208 }
209 
210 void
211 ia_css_eed1_8_encode(
212     struct eed1_8_dmem_params *to,
213     const struct ia_css_eed1_8_config *from,
214     size_t size)
215 {
216 	int i;
217 	int min_exp = 0;
218 
219 	(void)size;
220 
221 	to->rbzp_strength = from->rbzp_strength;
222 
223 	to->fcstrength = from->fcstrength;
224 	to->fcthres_0 = from->fcthres_0;
225 	to->fc_sat_coef = from->fc_sat_coef;
226 	to->fc_coring_prm = from->fc_coring_prm;
227 	to->fc_slope = from->fcthres_1 - from->fcthres_0;
228 
229 	to->aerel_thres0 = from->aerel_thres0;
230 	to->aerel_gain0 = from->aerel_gain0;
231 	to->aerel_thres_diff = from->aerel_thres1 - from->aerel_thres0;
232 	to->aerel_gain_diff = from->aerel_gain1 - from->aerel_gain0;
233 
234 	to->derel_thres0 = from->derel_thres0;
235 	to->derel_gain0 = from->derel_gain0;
236 	to->derel_thres_diff = (from->derel_thres1 - from->derel_thres0);
237 	to->derel_gain_diff = (from->derel_gain1 - from->derel_gain0);
238 
239 	to->coring_pos0 = from->coring_pos0;
240 	to->coring_pos_diff = (from->coring_pos1 - from->coring_pos0);
241 	to->coring_neg0 = from->coring_neg0;
242 	to->coring_neg_diff = (from->coring_neg1 - from->coring_neg0);
243 
244 	/* Note: (ISP_VEC_ELEMBITS -1)
245 	 * TODO: currently the testbench does not support to use
246 	 * ISP_VEC_ELEMBITS. Investigate how to fix this
247 	 */
248 	to->gain_exp = (13 - from->gain_exp);
249 	to->gain_pos0 = from->gain_pos0;
250 	to->gain_pos_diff = (from->gain_pos1 - from->gain_pos0);
251 	to->gain_neg0 = from->gain_neg0;
252 	to->gain_neg_diff = (from->gain_neg1 - from->gain_neg0);
253 
254 	to->margin_pos0 = from->pos_margin0;
255 	to->margin_pos_diff = (from->pos_margin1 - from->pos_margin0);
256 	to->margin_neg0 = from->neg_margin0;
257 	to->margin_neg_diff = (from->neg_margin1 - from->neg_margin0);
258 
259 	/* Encode DEWEnhance exp (e_dew_enh_asr) */
260 	for (i = 0; i < (IA_CSS_NUMBER_OF_DEW_ENHANCE_SEGMENTS - 1); i++)
261 		min_exp = max(min_exp, from->dew_enhance_seg_exp[i]);
262 
263 	to->e_dew_enh_asr = 13 - clamp(min_exp, 0, 13);
264 
265 	to->dedgew_max = from->dedgew_max;
266 }
267 
268 void
269 ia_css_init_eed1_8_state(
270     void *state,
271     size_t size)
272 {
273 	memset(state, 0, size);
274 }
275 
276 #ifndef IA_CSS_NO_DEBUG
277 void
278 ia_css_eed1_8_debug_dtrace(
279     const struct ia_css_eed1_8_config *eed,
280     unsigned int level)
281 {
282 	if (!eed)
283 		return;
284 
285 	ia_css_debug_dtrace(level, "Edge Enhancing Demosaic 1.8:\n");
286 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "rbzp_strength",
287 			    eed->rbzp_strength);
288 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "fcstrength", eed->fcstrength);
289 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "fcthres_0", eed->fcthres_0);
290 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "fcthres_1", eed->fcthres_1);
291 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "fc_sat_coef", eed->fc_sat_coef);
292 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "fc_coring_prm",
293 			    eed->fc_coring_prm);
294 
295 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "aerel_thres0", eed->aerel_thres0);
296 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "aerel_gain0", eed->aerel_gain0);
297 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "aerel_thres1", eed->aerel_thres1);
298 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "aerel_gain1", eed->aerel_gain1);
299 
300 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "derel_thres0", eed->derel_thres0);
301 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "derel_gain0", eed->derel_gain0);
302 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "derel_thres1", eed->derel_thres1);
303 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "derel_gain1", eed->derel_gain1);
304 
305 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "coring_pos0", eed->coring_pos0);
306 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "coring_pos1", eed->coring_pos1);
307 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "coring_neg0", eed->coring_neg0);
308 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "coring_neg1", eed->coring_neg1);
309 
310 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "gain_exp", eed->gain_exp);
311 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "gain_pos0", eed->gain_pos0);
312 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "gain_pos1", eed->gain_pos1);
313 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "gain_neg0", eed->gain_neg0);
314 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "gain_neg1", eed->gain_neg1);
315 
316 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "pos_margin0", eed->pos_margin0);
317 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "pos_margin1", eed->pos_margin1);
318 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "neg_margin0", eed->neg_margin0);
319 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "neg_margin1", eed->neg_margin1);
320 
321 	ia_css_debug_dtrace(level, "\t%-32s = %d\n", "dedgew_max", eed->dedgew_max);
322 }
323 #endif
324