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