GNU Linux-libre 4.14.302-gnu1
[releases.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / isp / kernels / xnr / xnr_3.0 / ia_css_xnr3.host.c
1 /*
2  * Support for Intel Camera Imaging ISP subsystem.
3  * Copyright (c) 2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14
15 #include "type_support.h"
16 #include "math_support.h"
17 #include "sh_css_defs.h"
18 #include "ia_css_types.h"
19 #ifdef ISP2401
20 #include "assert_support.h"
21 #endif
22 #include "ia_css_xnr3.host.h"
23
24 /* Maximum value for alpha on ISP interface */
25 #define XNR_MAX_ALPHA  ((1 << (ISP_VEC_ELEMBITS - 1)) - 1)
26
27 /* Minimum value for sigma on host interface. Lower values translate to
28  * max_alpha.
29  */
30 #define XNR_MIN_SIGMA  (IA_CSS_XNR3_SIGMA_SCALE / 100)
31
32 /*
33 #ifdef ISP2401
34  * division look-up table
35  * Refers to XNR3.0.5
36  */
37 #define XNR3_LOOK_UP_TABLE_POINTS 16
38
39 static const int16_t x[XNR3_LOOK_UP_TABLE_POINTS] = {
40 1024, 1164, 1320, 1492, 1680, 1884, 2108, 2352,
41 2616, 2900, 3208, 3540, 3896, 4276, 4684, 5120};
42
43 static const int16_t a[XNR3_LOOK_UP_TABLE_POINTS] = {
44 -7213, -5580, -4371, -3421, -2722, -2159, -6950, -5585,
45 -4529, -3697, -3010, -2485, -2070, -1727, -1428, 0};
46
47 static const int16_t 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 static const int16_t c[XNR3_LOOK_UP_TABLE_POINTS] = {
52 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
53
54 /*
55 #endif
56  * Default kernel parameters. In general, default is bypass mode or as close
57  * to the ineffective values as possible. Due to the chroma down+upsampling,
58  * perfect bypass mode is not possible for xnr3 filter itself. Instead, the
59  * 'blending' parameter is used to create a bypass.
60  */
61 const struct ia_css_xnr3_config default_xnr3_config = {
62         /* sigma */
63         { 0, 0, 0, 0, 0, 0 },
64         /* coring */
65         { 0, 0, 0, 0 },
66         /* blending */
67         { 0 }
68 };
69
70 /*
71  * Compute an alpha value for the ISP kernel from sigma value on the host
72  * parameter interface as: alpha_scale * 1/(sigma/sigma_scale)
73  */
74 static int32_t
75 compute_alpha(int sigma)
76 {
77         int32_t alpha;
78 #if defined(XNR_ATE_ROUNDING_BUG)
79         int32_t alpha_unscaled;
80 #else
81         int offset = sigma / 2;
82 #endif
83         if (sigma < XNR_MIN_SIGMA) {
84                 alpha = XNR_MAX_ALPHA;
85         } else {
86 #if defined(XNR_ATE_ROUNDING_BUG)
87                 /* The scale factor for alpha must be the same as on the ISP,
88                  * For sigma, it must match the public interface. The code
89                  * below mimics the rounding and unintended loss of precision
90                  * of the ATE reference code. It computes an unscaled alpha,
91                  * rounds down, and then scales it to get the required fixed
92                  * point representation. It would have been more precise to
93                  * round after scaling. */
94                 alpha_unscaled = IA_CSS_XNR3_SIGMA_SCALE / sigma;
95                 alpha = alpha_unscaled * XNR_ALPHA_SCALE_FACTOR;
96 #else
97                 alpha = ((IA_CSS_XNR3_SIGMA_SCALE * XNR_ALPHA_SCALE_FACTOR) + offset)/ sigma;
98 #endif
99
100                 if (alpha > XNR_MAX_ALPHA)
101                         alpha = XNR_MAX_ALPHA;
102         }
103
104         return alpha;
105 }
106
107 /*
108  * Compute the scaled coring value for the ISP kernel from the value on the
109  * host parameter interface.
110  */
111 static int32_t
112 compute_coring(int coring)
113 {
114         int32_t isp_coring;
115         int32_t isp_scale = XNR_CORING_SCALE_FACTOR;
116         int32_t host_scale = IA_CSS_XNR3_CORING_SCALE;
117         int32_t offset = host_scale / 2; /* fixed-point 0.5 */
118
119         /* Convert from public host-side scale factor to isp-side scale
120          * factor. Clip to [0, isp_scale-1).
121          */
122         isp_coring = ((coring * isp_scale) + offset) / host_scale;
123         return min(max(isp_coring, 0), isp_scale - 1);
124 }
125
126 /*
127  * Compute the scaled blending strength for the ISP kernel from the value on
128  * the host parameter interface.
129  */
130 static int32_t
131 compute_blending(int strength)
132 {
133         int32_t isp_strength;
134         int32_t isp_scale = XNR_BLENDING_SCALE_FACTOR;
135         int32_t host_scale = IA_CSS_XNR3_BLENDING_SCALE;
136         int32_t offset = host_scale / 2; /* fixed-point 0.5 */
137
138         /* Convert from public host-side scale factor to isp-side scale
139          * factor. The blending factor is positive on the host side, but
140          * negative on the ISP side because +1.0 cannot be represented
141          * exactly as s0.11 fixed point, but -1.0 can.
142          */
143         isp_strength = -(((strength * isp_scale) + offset) / host_scale);
144         return max(min(isp_strength, 0), -XNR_BLENDING_SCALE_FACTOR);
145 }
146
147 void
148 ia_css_xnr3_encode(
149         struct sh_css_isp_xnr3_params *to,
150         const struct ia_css_xnr3_config *from,
151         unsigned size)
152 {
153         int kernel_size = XNR_FILTER_SIZE;
154         /* The adjust factor is the next power of 2
155            w.r.t. the kernel size*/
156         int adjust_factor = ceil_pow2(kernel_size);
157         int32_t max_diff = (1 << (ISP_VEC_ELEMBITS - 1)) - 1;
158         int32_t min_diff = -(1 << (ISP_VEC_ELEMBITS - 1));
159
160         int32_t alpha_y0 = compute_alpha(from->sigma.y0);
161         int32_t alpha_y1 = compute_alpha(from->sigma.y1);
162         int32_t alpha_u0 = compute_alpha(from->sigma.u0);
163         int32_t alpha_u1 = compute_alpha(from->sigma.u1);
164         int32_t alpha_v0 = compute_alpha(from->sigma.v0);
165         int32_t alpha_v1 = compute_alpha(from->sigma.v1);
166         int32_t alpha_ydiff = (alpha_y1 - alpha_y0) * adjust_factor / kernel_size;
167         int32_t alpha_udiff = (alpha_u1 - alpha_u0) * adjust_factor / kernel_size;
168         int32_t alpha_vdiff = (alpha_v1 - alpha_v0) * adjust_factor / kernel_size;
169
170         int32_t coring_u0 = compute_coring(from->coring.u0);
171         int32_t coring_u1 = compute_coring(from->coring.u1);
172         int32_t coring_v0 = compute_coring(from->coring.v0);
173         int32_t coring_v1 = compute_coring(from->coring.v1);
174         int32_t coring_udiff = (coring_u1 - coring_u0) * adjust_factor / kernel_size;
175         int32_t coring_vdiff = (coring_v1 - coring_v0) * adjust_factor / kernel_size;
176
177         int32_t blending = compute_blending(from->blending.strength);
178
179         (void)size;
180
181         /* alpha's are represented in qN.5 format */
182         to->alpha.y0 = alpha_y0;
183         to->alpha.u0 = alpha_u0;
184         to->alpha.v0 = alpha_v0;
185         to->alpha.ydiff = min(max(alpha_ydiff, min_diff), max_diff);
186         to->alpha.udiff = min(max(alpha_udiff, min_diff), max_diff);
187         to->alpha.vdiff = min(max(alpha_vdiff, min_diff), max_diff);
188
189         /* coring parameters are expressed in q1.NN format */
190         to->coring.u0 = coring_u0;
191         to->coring.v0 = coring_v0;
192         to->coring.udiff = min(max(coring_udiff, min_diff), max_diff);
193         to->coring.vdiff = min(max(coring_vdiff, min_diff), max_diff);
194
195         /* blending strength is expressed in q1.NN format */
196         to->blending.strength = blending;
197 }
198
199 #ifdef ISP2401
200 /* (void) = ia_css_xnr3_vmem_encode(*to, *from)
201  * -----------------------------------------------
202  * VMEM Encode Function to translate UV parameters from userspace into ISP space
203 */
204 void
205 ia_css_xnr3_vmem_encode(
206         struct sh_css_isp_xnr3_vmem_params *to,
207         const struct ia_css_xnr3_config *from,
208         unsigned size)
209 {
210         unsigned i, j, base;
211         const unsigned total_blocks = 4;
212         const unsigned shuffle_block = 16;
213
214         (void)from;
215         (void)size;
216
217         /* Init */
218         for (i = 0; i < ISP_VEC_NELEMS; i++) {
219                 to->x[0][i] = 0;
220                 to->a[0][i] = 0;
221                 to->b[0][i] = 0;
222                 to->c[0][i] = 0;
223         }
224
225         /* Constraints on "x":
226          * - values should be greater or equal to 0.
227          * - values should be ascending.
228          */
229         assert(x[0] >= 0);
230
231         for (j = 1; j < XNR3_LOOK_UP_TABLE_POINTS; j++) {
232                 assert(x[j] >= 0);
233                 assert(x[j] > x[j - 1]);
234
235         }
236
237         /* The implementation of the calulating 1/x is based on the availability
238          * of the OP_vec_shuffle16 operation.
239          * A 64 element vector is split up in 4 blocks of 16 element. Each array is copied to
240          * a vector 4 times, (starting at 0, 16, 32 and 48). All array elements are copied or
241          * initialised as described in the KFS. The remaining elements of a vector are set to 0.
242          */
243         /* TODO: guard this code with above assumptions */
244         for (i = 0; i < total_blocks; i++) {
245                 base = shuffle_block * i;
246
247                 for (j = 0; j < XNR3_LOOK_UP_TABLE_POINTS; j++) {
248                         to->x[0][base + j] = x[j];
249                         to->a[0][base + j] = a[j];
250                         to->b[0][base + j] = b[j];
251                         to->c[0][base + j] = c[j];
252                 }
253         }
254 }
255
256 #endif
257 /* Dummy Function added as the tool expects it*/
258 void
259 ia_css_xnr3_debug_dtrace(
260         const struct ia_css_xnr3_config *config,
261         unsigned level)
262 {
263         (void)config;
264         (void)level;
265 }