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