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 "type_support.h" 17 #include "math_support.h" 18 #include "sh_css_defs.h" 19 #include "ia_css_types.h" 20 #include "assert_support.h" 21 #include "ia_css_xnr3.host.h" 22 23 /* Maximum value for alpha on ISP interface */ 24 #define XNR_MAX_ALPHA ((1 << (ISP_VEC_ELEMBITS - 1)) - 1) 25 26 /* Minimum value for sigma on host interface. Lower values translate to 27 * max_alpha. 28 */ 29 #define XNR_MIN_SIGMA (IA_CSS_XNR3_SIGMA_SCALE / 100) 30 31 /* 32 * division look-up table 33 * Refers to XNR3.0.5 34 */ 35 #define XNR3_LOOK_UP_TABLE_POINTS 16 36 37 static const s16 x[XNR3_LOOK_UP_TABLE_POINTS] = { 38 1024, 1164, 1320, 1492, 1680, 1884, 2108, 2352, 39 2616, 2900, 3208, 3540, 3896, 4276, 4684, 5120 40 }; 41 42 static const s16 a[XNR3_LOOK_UP_TABLE_POINTS] = { 43 -7213, -5580, -4371, -3421, -2722, -2159, -6950, -5585, 44 -4529, -3697, -3010, -2485, -2070, -1727, -1428, 0 45 }; 46 47 static const s16 b[XNR3_LOOK_UP_TABLE_POINTS] = { 48 4096, 3603, 3178, 2811, 2497, 2226, 1990, 1783, 49 1603, 1446, 1307, 1185, 1077, 981, 895, 819 50 }; 51 52 static const s16 c[XNR3_LOOK_UP_TABLE_POINTS] = { 53 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 54 }; 55 56 /* 57 * Default kernel parameters. In general, default is bypass mode or as close 58 * to the ineffective values as possible. Due to the chroma down+upsampling, 59 * perfect bypass mode is not possible for xnr3 filter itself. Instead, the 60 * 'blending' parameter is used to create a bypass. 61 */ 62 const struct ia_css_xnr3_config default_xnr3_config = { 63 /* sigma */ 64 { 0, 0, 0, 0, 0, 0 }, 65 /* coring */ 66 { 0, 0, 0, 0 }, 67 /* blending */ 68 { 0 } 69 }; 70 71 /* 72 * Compute an alpha value for the ISP kernel from sigma value on the host 73 * parameter interface as: alpha_scale * 1/(sigma/sigma_scale) 74 */ 75 static int32_t 76 compute_alpha(int sigma) 77 { 78 s32 alpha; 79 int offset = sigma / 2; 80 81 if (sigma < XNR_MIN_SIGMA) { 82 alpha = XNR_MAX_ALPHA; 83 } else { 84 alpha = ((IA_CSS_XNR3_SIGMA_SCALE * XNR_ALPHA_SCALE_FACTOR) + offset) / sigma; 85 86 if (alpha > XNR_MAX_ALPHA) 87 alpha = XNR_MAX_ALPHA; 88 } 89 90 return alpha; 91 } 92 93 /* 94 * Compute the scaled coring value for the ISP kernel from the value on the 95 * host parameter interface. 96 */ 97 static int32_t 98 compute_coring(int coring) 99 { 100 s32 isp_coring; 101 s32 isp_scale = XNR_CORING_SCALE_FACTOR; 102 s32 host_scale = IA_CSS_XNR3_CORING_SCALE; 103 s32 offset = host_scale / 2; /* fixed-point 0.5 */ 104 105 /* Convert from public host-side scale factor to isp-side scale 106 * factor. Clip to [0, isp_scale-1). 107 */ 108 isp_coring = ((coring * isp_scale) + offset) / host_scale; 109 return min(max(isp_coring, 0), isp_scale - 1); 110 } 111 112 /* 113 * Compute the scaled blending strength for the ISP kernel from the value on 114 * the host parameter interface. 115 */ 116 static int32_t 117 compute_blending(int strength) 118 { 119 s32 isp_strength; 120 s32 isp_scale = XNR_BLENDING_SCALE_FACTOR; 121 s32 host_scale = IA_CSS_XNR3_BLENDING_SCALE; 122 s32 offset = host_scale / 2; /* fixed-point 0.5 */ 123 124 /* Convert from public host-side scale factor to isp-side scale 125 * factor. The blending factor is positive on the host side, but 126 * negative on the ISP side because +1.0 cannot be represented 127 * exactly as s0.11 fixed point, but -1.0 can. 128 */ 129 isp_strength = -(((strength * isp_scale) + offset) / host_scale); 130 return MAX(MIN(isp_strength, 0), -isp_scale); 131 } 132 133 void 134 ia_css_xnr3_encode( 135 struct sh_css_isp_xnr3_params *to, 136 const struct ia_css_xnr3_config *from, 137 unsigned int size) 138 { 139 int kernel_size = XNR_FILTER_SIZE; 140 /* The adjust factor is the next power of 2 141 w.r.t. the kernel size*/ 142 int adjust_factor = ceil_pow2(kernel_size); 143 s32 max_diff = (1 << (ISP_VEC_ELEMBITS - 1)) - 1; 144 s32 min_diff = -(1 << (ISP_VEC_ELEMBITS - 1)); 145 146 s32 alpha_y0 = compute_alpha(from->sigma.y0); 147 s32 alpha_y1 = compute_alpha(from->sigma.y1); 148 s32 alpha_u0 = compute_alpha(from->sigma.u0); 149 s32 alpha_u1 = compute_alpha(from->sigma.u1); 150 s32 alpha_v0 = compute_alpha(from->sigma.v0); 151 s32 alpha_v1 = compute_alpha(from->sigma.v1); 152 s32 alpha_ydiff = (alpha_y1 - alpha_y0) * adjust_factor / kernel_size; 153 s32 alpha_udiff = (alpha_u1 - alpha_u0) * adjust_factor / kernel_size; 154 s32 alpha_vdiff = (alpha_v1 - alpha_v0) * adjust_factor / kernel_size; 155 156 s32 coring_u0 = compute_coring(from->coring.u0); 157 s32 coring_u1 = compute_coring(from->coring.u1); 158 s32 coring_v0 = compute_coring(from->coring.v0); 159 s32 coring_v1 = compute_coring(from->coring.v1); 160 s32 coring_udiff = (coring_u1 - coring_u0) * adjust_factor / kernel_size; 161 s32 coring_vdiff = (coring_v1 - coring_v0) * adjust_factor / kernel_size; 162 163 s32 blending = compute_blending(from->blending.strength); 164 165 (void)size; 166 167 /* alpha's are represented in qN.5 format */ 168 to->alpha.y0 = alpha_y0; 169 to->alpha.u0 = alpha_u0; 170 to->alpha.v0 = alpha_v0; 171 to->alpha.ydiff = min(max(alpha_ydiff, min_diff), max_diff); 172 to->alpha.udiff = min(max(alpha_udiff, min_diff), max_diff); 173 to->alpha.vdiff = min(max(alpha_vdiff, min_diff), max_diff); 174 175 /* coring parameters are expressed in q1.NN format */ 176 to->coring.u0 = coring_u0; 177 to->coring.v0 = coring_v0; 178 to->coring.udiff = min(max(coring_udiff, min_diff), max_diff); 179 to->coring.vdiff = min(max(coring_vdiff, min_diff), max_diff); 180 181 /* blending strength is expressed in q1.NN format */ 182 to->blending.strength = blending; 183 } 184 185 /* ISP2401 */ 186 /* (void) = ia_css_xnr3_vmem_encode(*to, *from) 187 * ----------------------------------------------- 188 * VMEM Encode Function to translate UV parameters from userspace into ISP space 189 */ 190 void 191 ia_css_xnr3_vmem_encode( 192 struct sh_css_isp_xnr3_vmem_params *to, 193 const struct ia_css_xnr3_config *from, 194 unsigned int size) 195 { 196 unsigned int i, j, base; 197 const unsigned int total_blocks = 4; 198 const unsigned int shuffle_block = 16; 199 200 (void)from; 201 (void)size; 202 203 /* Init */ 204 for (i = 0; i < ISP_VEC_NELEMS; i++) { 205 to->x[0][i] = 0; 206 to->a[0][i] = 0; 207 to->b[0][i] = 0; 208 to->c[0][i] = 0; 209 } 210 211 /* Constraints on "x": 212 * - values should be greater or equal to 0. 213 * - values should be ascending. 214 */ 215 assert(x[0] >= 0); 216 217 for (j = 1; j < XNR3_LOOK_UP_TABLE_POINTS; j++) { 218 assert(x[j] >= 0); 219 assert(x[j] > x[j - 1]); 220 } 221 222 /* The implementation of the calulating 1/x is based on the availability 223 * of the OP_vec_shuffle16 operation. 224 * A 64 element vector is split up in 4 blocks of 16 element. Each array is copied to 225 * a vector 4 times, (starting at 0, 16, 32 and 48). All array elements are copied or 226 * initialised as described in the KFS. The remaining elements of a vector are set to 0. 227 */ 228 /* TODO: guard this code with above assumptions */ 229 for (i = 0; i < total_blocks; i++) { 230 base = shuffle_block * i; 231 232 for (j = 0; j < XNR3_LOOK_UP_TABLE_POINTS; j++) { 233 to->x[0][base + j] = x[j]; 234 to->a[0][base + j] = a[j]; 235 to->b[0][base + j] = b[j]; 236 to->c[0][base + j] = c[j]; 237 } 238 } 239 } 240 241 /* Dummy Function added as the tool expects it*/ 242 void 243 ia_css_xnr3_debug_dtrace( 244 const struct ia_css_xnr3_config *config, 245 unsigned int level) 246 { 247 (void)config; 248 (void)level; 249 } 250