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