GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / isp / kernels / s3a / s3a_1.0 / ia_css_s3a.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 "ia_css_types.h"
16 #include "sh_css_defs.h"
17 #ifndef IA_CSS_NO_DEBUG
18 #include "ia_css_debug.h"
19 #endif
20 #include "sh_css_frac.h"
21 #include "assert_support.h"
22
23 #include "bh/bh_2/ia_css_bh.host.h"
24 #include "ia_css_s3a.host.h"
25
26 const struct ia_css_3a_config default_3a_config = {
27         25559,
28         32768,
29         7209,
30         65535,
31         0,
32         65535,
33         {-3344, -6104, -19143, 19143, 6104, 3344, 0},
34         {1027, 0, -9219, 16384, -9219, 1027, 0}
35 };
36
37 static unsigned int s3a_raw_bit_depth;
38
39 void
40 ia_css_s3a_configure(unsigned int raw_bit_depth)
41 {
42   s3a_raw_bit_depth = raw_bit_depth;
43 }
44
45 static void
46 ia_css_ae_encode(
47         struct sh_css_isp_ae_params *to,
48         const struct ia_css_3a_config *from,
49         unsigned size)
50 {
51         (void)size;
52         /* coefficients to calculate Y */
53         to->y_coef_r =
54             uDIGIT_FITTING(from->ae_y_coef_r, 16, SH_CSS_AE_YCOEF_SHIFT);
55         to->y_coef_g =
56             uDIGIT_FITTING(from->ae_y_coef_g, 16, SH_CSS_AE_YCOEF_SHIFT);
57         to->y_coef_b =
58             uDIGIT_FITTING(from->ae_y_coef_b, 16, SH_CSS_AE_YCOEF_SHIFT);
59 }
60
61 static void
62 ia_css_awb_encode(
63         struct sh_css_isp_awb_params *to,
64         const struct ia_css_3a_config *from,
65         unsigned size)
66 {
67         (void)size;
68         /* AWB level gate */
69         to->lg_high_raw =
70                 uDIGIT_FITTING(from->awb_lg_high_raw, 16, s3a_raw_bit_depth);
71         to->lg_low =
72                 uDIGIT_FITTING(from->awb_lg_low, 16, SH_CSS_BAYER_BITS);
73         to->lg_high =
74                 uDIGIT_FITTING(from->awb_lg_high, 16, SH_CSS_BAYER_BITS);
75 }
76
77 static void
78 ia_css_af_encode(
79         struct sh_css_isp_af_params *to,
80         const struct ia_css_3a_config *from,
81         unsigned size)
82 {
83         unsigned int i;
84         (void)size;
85
86         /* af fir coefficients */
87         for (i = 0; i < 7; ++i) {
88                 to->fir1[i] =
89                   sDIGIT_FITTING(from->af_fir1_coef[i], 15,
90                                  SH_CSS_AF_FIR_SHIFT);
91                 to->fir2[i] =
92                   sDIGIT_FITTING(from->af_fir2_coef[i], 15,
93                                  SH_CSS_AF_FIR_SHIFT);
94         }
95 }
96
97 void
98 ia_css_s3a_encode(
99         struct sh_css_isp_s3a_params *to,
100         const struct ia_css_3a_config *from,
101         unsigned size)
102 {
103         (void)size;
104
105         ia_css_ae_encode(&to->ae,   from, sizeof(to->ae));
106         ia_css_awb_encode(&to->awb, from, sizeof(to->awb));
107         ia_css_af_encode(&to->af,   from, sizeof(to->af));
108 }
109
110 #if 0
111 void
112 ia_css_process_s3a(
113         unsigned pipe_id,
114         const struct ia_css_pipeline_stage *stage,
115         struct ia_css_isp_parameters *params)
116 {
117         short dmem_offset = stage->binary->info->mem_offsets->dmem.s3a;
118
119         assert(params != NULL);
120
121         if (dmem_offset >= 0) {
122                 ia_css_s3a_encode((struct sh_css_isp_s3a_params *)
123                                 &stage->isp_mem_params[IA_CSS_ISP_DMEM0].address[dmem_offset],
124                                 &params->s3a_config);
125                 ia_css_bh_encode((struct sh_css_isp_bh_params *)
126                                 &stage->isp_mem_params[IA_CSS_ISP_DMEM0].address[dmem_offset],
127                                 &params->s3a_config);
128                 params->isp_params_changed = true;
129                 params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM0] = true;
130         }
131
132         params->isp_params_changed = true;
133 }
134 #endif
135
136 #ifndef IA_CSS_NO_DEBUG
137 void
138 ia_css_ae_dump(
139         const struct sh_css_isp_ae_params *ae,
140         unsigned level)
141 {
142         if (!ae) return;
143         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
144                         "ae_y_coef_r", ae->y_coef_r);
145         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
146                         "ae_y_coef_g", ae->y_coef_g);
147         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
148                         "ae_y_coef_b", ae->y_coef_b);
149 }
150
151 void
152 ia_css_awb_dump(
153         const struct sh_css_isp_awb_params *awb,
154         unsigned level)
155 {
156         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
157                         "awb_lg_high_raw", awb->lg_high_raw);
158         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
159                         "awb_lg_low", awb->lg_low);
160         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
161                         "awb_lg_high", awb->lg_high);
162 }
163
164 void
165 ia_css_af_dump(
166         const struct sh_css_isp_af_params *af,
167         unsigned level)
168 {
169         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
170                         "af_fir1[0]", af->fir1[0]);
171         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
172                         "af_fir1[1]", af->fir1[1]);
173         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
174                         "af_fir1[2]", af->fir1[2]);
175         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
176                         "af_fir1[3]", af->fir1[3]);
177         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
178                         "af_fir1[4]", af->fir1[4]);
179         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
180                         "af_fir1[5]", af->fir1[5]);
181         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
182                         "af_fir1[6]", af->fir1[6]);
183         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
184                         "af_fir2[0]", af->fir2[0]);
185         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
186                         "af_fir2[1]", af->fir2[1]);
187         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
188                         "af_fir2[2]", af->fir2[2]);
189         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
190                         "af_fir2[3]", af->fir2[3]);
191         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
192                         "af_fir2[4]", af->fir2[4]);
193         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
194                         "af_fir2[5]", af->fir2[5]);
195         ia_css_debug_dtrace(level, "\t%-32s = %d\n",
196                         "af_fir2[6]", af->fir2[6]);
197 }
198
199 void
200 ia_css_s3a_dump(
201         const struct sh_css_isp_s3a_params *s3a,
202         unsigned level)
203 {
204         ia_css_debug_dtrace(level, "S3A Support:\n");
205         ia_css_ae_dump  (&s3a->ae, level);
206         ia_css_awb_dump (&s3a->awb, level);
207         ia_css_af_dump  (&s3a->af, level);
208 }
209
210 void
211 ia_css_s3a_debug_dtrace(
212         const struct ia_css_3a_config *config,
213         unsigned level)
214 {
215         ia_css_debug_dtrace(level,
216                 "config.ae_y_coef_r=%d, config.ae_y_coef_g=%d, "
217                 "config.ae_y_coef_b=%d, config.awb_lg_high_raw=%d, "
218                 "config.awb_lg_low=%d, config.awb_lg_high=%d\n",
219                 config->ae_y_coef_r, config->ae_y_coef_g,
220                 config->ae_y_coef_b, config->awb_lg_high_raw,
221                 config->awb_lg_low, config->awb_lg_high);
222 }
223 #endif
224
225 void
226 ia_css_s3a_hmem_decode(
227         struct ia_css_3a_statistics *host_stats,
228         const struct ia_css_bh_table *hmem_buf)
229 {
230 #if defined(HAS_NO_HMEM)
231         (void)host_stats;
232         (void)hmem_buf;
233 #else
234         struct ia_css_3a_rgby_output    *out_ptr;
235         int                     i;
236
237         /* pixel counts(BQ) for 3A area */
238         int count_for_3a;
239         int sum_r, diff;
240
241         assert(host_stats != NULL);
242         assert(host_stats->rgby_data != NULL);
243         assert(hmem_buf != NULL);
244
245         count_for_3a = host_stats->grid.width * host_stats->grid.height
246             * host_stats->grid.bqs_per_grid_cell
247             * host_stats->grid.bqs_per_grid_cell;
248
249         out_ptr = host_stats->rgby_data;
250
251         ia_css_bh_hmem_decode(out_ptr, hmem_buf);
252
253         /* Calculate sum of histogram of R,
254            which should not be less than count_for_3a */
255         sum_r = 0;
256         for (i = 0; i < HMEM_UNIT_SIZE; i++) {
257                 sum_r += out_ptr[i].r;
258         }
259         if (sum_r < count_for_3a) {
260                 /* histogram is invalid */
261                 return;
262         }
263
264         /* Verify for sum of histogram of R/G/B/Y */
265 #if 0
266         {
267                 int sum_g = 0;
268                 int sum_b = 0;
269                 int sum_y = 0;
270                 for (i = 0; i < HMEM_UNIT_SIZE; i++) {
271                         sum_g += out_ptr[i].g;
272                         sum_b += out_ptr[i].b;
273                         sum_y += out_ptr[i].y;
274                 }
275                 if (sum_g != sum_r || sum_b != sum_r || sum_y != sum_r) {
276                         /* histogram is invalid */
277                         return;
278                 }
279         }
280 #endif
281
282         /*
283          * Limit the histogram area only to 3A area.
284          * In DSP, the histogram of 0 is incremented for pixels
285          * which are outside of 3A area. That amount should be subtracted here.
286          *   hist[0] = hist[0] - ((sum of all hist[]) - (pixel count for 3A area))
287          */
288         diff = sum_r - count_for_3a;
289         out_ptr[0].r -= diff;
290         out_ptr[0].g -= diff;
291         out_ptr[0].b -= diff;
292         out_ptr[0].y -= diff;
293 #endif
294 }
295
296 void
297 ia_css_s3a_dmem_decode(
298         struct ia_css_3a_statistics *host_stats,
299         const struct ia_css_3a_output *isp_stats)
300 {
301         int isp_width, host_width, height, i;
302         struct ia_css_3a_output *host_ptr;
303
304         assert(host_stats != NULL);
305         assert(host_stats->data != NULL);
306         assert(isp_stats != NULL);
307
308         isp_width  = host_stats->grid.aligned_width;
309         host_width = host_stats->grid.width;
310         height     = host_stats->grid.height;
311         host_ptr   = host_stats->data;
312
313         /* Getting 3A statistics from DMEM does not involve any
314          * transformation (like the VMEM version), we just copy the data
315          * using a different output width. */
316         for (i = 0; i < height; i++) {
317                 memcpy(host_ptr, isp_stats, host_width * sizeof(*host_ptr));
318                 isp_stats += isp_width;
319                 host_ptr += host_width;
320         }
321 }
322
323 /* MW: this is an ISP function */
324 STORAGE_CLASS_INLINE int
325 merge_hi_lo_14(unsigned short hi, unsigned short lo)
326 {
327         int val = (int) ((((unsigned int) hi << 14) & 0xfffc000) |
328                         ((unsigned int) lo & 0x3fff));
329         return val;
330 }
331
332 void
333 ia_css_s3a_vmem_decode(
334         struct ia_css_3a_statistics *host_stats,
335         const uint16_t *isp_stats_hi,
336         const uint16_t *isp_stats_lo)
337 {
338         int out_width, out_height, chunk, rest, kmax, y, x, k, elm_start, elm, ofs;
339         const uint16_t *hi, *lo;
340         struct ia_css_3a_output *output;
341
342         assert(host_stats!= NULL);
343         assert(host_stats->data != NULL);
344         assert(isp_stats_hi != NULL);
345         assert(isp_stats_lo != NULL);
346
347         output = host_stats->data;
348         out_width  = host_stats->grid.width;
349         out_height = host_stats->grid.height;
350         hi = isp_stats_hi;
351         lo = isp_stats_lo;
352
353         chunk = ISP_VEC_NELEMS >> host_stats->grid.deci_factor_log2;
354         chunk = max(chunk, 1);
355
356         for (y = 0; y < out_height; y++) {
357                 elm_start = y * ISP_S3ATBL_HI_LO_STRIDE;
358                 rest = out_width;
359                 x = 0;
360                 while (x < out_width) {
361                         kmax = (rest > chunk) ? chunk : rest;
362                         ofs = y * out_width + x;
363                         elm = elm_start + x * sizeof(*output) / sizeof(int32_t);
364                         for (k = 0; k < kmax; k++, elm++) {
365                                 output[ofs + k].ae_y    = merge_hi_lo_14(
366                                     hi[elm + chunk * 0], lo[elm + chunk * 0]);
367                                 output[ofs + k].awb_cnt = merge_hi_lo_14(
368                                     hi[elm + chunk * 1], lo[elm + chunk * 1]);
369                                 output[ofs + k].awb_gr  = merge_hi_lo_14(
370                                     hi[elm + chunk * 2], lo[elm + chunk * 2]);
371                                 output[ofs + k].awb_r   = merge_hi_lo_14(
372                                     hi[elm + chunk * 3], lo[elm + chunk * 3]);
373                                 output[ofs + k].awb_b   = merge_hi_lo_14(
374                                     hi[elm + chunk * 4], lo[elm + chunk * 4]);
375                                 output[ofs + k].awb_gb  = merge_hi_lo_14(
376                                     hi[elm + chunk * 5], lo[elm + chunk * 5]);
377                                 output[ofs + k].af_hpf1 = merge_hi_lo_14(
378                                     hi[elm + chunk * 6], lo[elm + chunk * 6]);
379                                 output[ofs + k].af_hpf2 = merge_hi_lo_14(
380                                     hi[elm + chunk * 7], lo[elm + chunk * 7]);
381                         }
382                         x += chunk;
383                         rest -= chunk;
384                 }
385         }
386 }