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