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 #include "ia_css_types.h" 17 #include "sh_css_defs.h" 18 #include "assert_support.h" 19 20 #include "ia_css_ctc2.host.h" 21 22 #define INEFFECTIVE_VAL 4096 23 #define BASIC_VAL 819 24 25 /*Default configuration of parameters for Ctc2*/ 26 const struct ia_css_ctc2_config default_ctc2_config = { 27 INEFFECTIVE_VAL, INEFFECTIVE_VAL, INEFFECTIVE_VAL, 28 INEFFECTIVE_VAL, INEFFECTIVE_VAL, INEFFECTIVE_VAL, 29 BASIC_VAL * 2, BASIC_VAL * 4, BASIC_VAL * 6, 30 BASIC_VAL * 8, INEFFECTIVE_VAL, INEFFECTIVE_VAL, 31 BASIC_VAL >> 1, BASIC_VAL 32 }; 33 34 /* (dydx) = ctc2_slope(y1, y0, x1, x0) 35 * ----------------------------------------------- 36 * Calculation of the Slope of a Line = ((y1 - y0) >> 8)/(x1 - x0) 37 * 38 * Note: y1, y0 , x1 & x0 must lie within the range 0 <-> 8191 39 */ 40 static int ctc2_slope(int y1, int y0, int x1, int x0) 41 { 42 const int shift_val = 8; 43 const int max_slope = (1 << IA_CSS_CTC_COEF_SHIFT) - 1; 44 int dy = y1 - y0; 45 int dx = x1 - x0; 46 int rounding = (dx + 1) >> 1; 47 int dy_shift = dy << shift_val; 48 int slope, dydx; 49 50 /*Protection for parameter values, & avoiding zero divisions*/ 51 assert(y0 >= 0 && y0 <= max_slope); 52 assert(y1 >= 0 && y1 <= max_slope); 53 assert(x0 >= 0 && x0 <= max_slope); 54 assert(x1 > 0 && x1 <= max_slope); 55 assert(dx > 0); 56 57 if (dy < 0) 58 rounding = -rounding; 59 slope = (int)(dy_shift + rounding) / dx; 60 61 /*the slope must lie within the range 62 (-max_slope-1) >= (dydx) >= (max_slope) 63 */ 64 if (slope <= -max_slope - 1) { 65 dydx = -max_slope - 1; 66 } else if (slope >= max_slope) { 67 dydx = max_slope; 68 } else { 69 dydx = slope; 70 } 71 72 return dydx; 73 } 74 75 /* (void) = ia_css_ctc2_vmem_encode(*to, *from) 76 * ----------------------------------------------- 77 * VMEM Encode Function to translate Y parameters from userspace into ISP space 78 */ 79 void ia_css_ctc2_vmem_encode(struct ia_css_isp_ctc2_vmem_params *to, 80 const struct ia_css_ctc2_config *from, 81 size_t size) 82 { 83 unsigned int i, j; 84 const unsigned int shffl_blck = 4; 85 const unsigned int length_zeros = 11; 86 short dydx0, dydx1, dydx2, dydx3, dydx4; 87 88 (void)size; 89 /* 90 * Calculation of slopes of lines interconnecting 91 * 0.0 -> y_x1 -> y_x2 -> y _x3 -> y_x4 -> 1.0 92 */ 93 dydx0 = ctc2_slope(from->y_y1, from->y_y0, 94 from->y_x1, 0); 95 dydx1 = ctc2_slope(from->y_y2, from->y_y1, 96 from->y_x2, from->y_x1); 97 dydx2 = ctc2_slope(from->y_y3, from->y_y2, 98 from->y_x3, from->y_x2); 99 dydx3 = ctc2_slope(from->y_y4, from->y_y3, 100 from->y_x4, from->y_x3); 101 dydx4 = ctc2_slope(from->y_y5, from->y_y4, 102 SH_CSS_BAYER_MAXVAL, from->y_x4); 103 104 /*Fill 3 arrays with: 105 * - Luma input gain values y_y0, y_y1, y_y2, y_3, y_y4 106 * - Luma kneepoints 0, y_x1, y_x2, y_x3, y_x4 107 * - Calculated slopes dydx0, dyxd1, dydx2, dydx3, dydx4 108 * 109 * - Each 64-element array is divided in blocks of 16 elements: 110 * the 5 parameters + zeros in the remaining 11 positions 111 * - All blocks of the same array will contain the same data 112 */ 113 for (i = 0; i < shffl_blck; i++) { 114 to->y_x[0][(i << shffl_blck)] = 0; 115 to->y_x[0][(i << shffl_blck) + 1] = from->y_x1; 116 to->y_x[0][(i << shffl_blck) + 2] = from->y_x2; 117 to->y_x[0][(i << shffl_blck) + 3] = from->y_x3; 118 to->y_x[0][(i << shffl_blck) + 4] = from->y_x4; 119 120 to->y_y[0][(i << shffl_blck)] = from->y_y0; 121 to->y_y[0][(i << shffl_blck) + 1] = from->y_y1; 122 to->y_y[0][(i << shffl_blck) + 2] = from->y_y2; 123 to->y_y[0][(i << shffl_blck) + 3] = from->y_y3; 124 to->y_y[0][(i << shffl_blck) + 4] = from->y_y4; 125 126 to->e_y_slope[0][(i << shffl_blck)] = dydx0; 127 to->e_y_slope[0][(i << shffl_blck) + 1] = dydx1; 128 to->e_y_slope[0][(i << shffl_blck) + 2] = dydx2; 129 to->e_y_slope[0][(i << shffl_blck) + 3] = dydx3; 130 to->e_y_slope[0][(i << shffl_blck) + 4] = dydx4; 131 132 for (j = 0; j < length_zeros; j++) { 133 to->y_x[0][(i << shffl_blck) + 5 + j] = 0; 134 to->y_y[0][(i << shffl_blck) + 5 + j] = 0; 135 to->e_y_slope[0][(i << shffl_blck) + 5 + j] = 0; 136 } 137 } 138 } 139 140 /* (void) = ia_css_ctc2_encode(*to, *from) 141 * ----------------------------------------------- 142 * DMEM Encode Function to translate UV parameters from userspace into ISP space 143 */ 144 void ia_css_ctc2_encode(struct ia_css_isp_ctc2_dmem_params *to, 145 struct ia_css_ctc2_config *from, 146 size_t size) 147 { 148 (void)size; 149 150 to->uv_y0 = from->uv_y0; 151 to->uv_y1 = from->uv_y1; 152 to->uv_x0 = from->uv_x0; 153 to->uv_x1 = from->uv_x1; 154 155 /*Slope Calculation*/ 156 to->uv_dydx = ctc2_slope(from->uv_y1, from->uv_y0, 157 from->uv_x1, from->uv_x0); 158 } 159