Linux-libre 4.14.14-gnu
[librecmc/linux-libre.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / isp / kernels / sdis / sdis_1.0 / ia_css_sdis.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 "memory_access.h"
16 #include "assert_support.h"
17 #include "ia_css_debug.h"
18 #include "ia_css_sdis_types.h"
19 #include "sdis/common/ia_css_sdis_common.host.h"
20 #include "ia_css_sdis.host.h"
21
22 const struct ia_css_dvs_coefficients default_sdis_config = {
23         .grid = { 0, 0, 0, 0, 0, 0, 0, 0 },
24         .hor_coefs = NULL,
25         .ver_coefs = NULL
26 };
27
28 static void
29 fill_row(short *private, const short *public, unsigned width, unsigned padding)
30 {
31         assert((int)width >= 0);
32         assert((int)padding >= 0);
33         memcpy (private, public, width*sizeof(short));
34         memset (&private[width], 0, padding*sizeof(short));
35 }
36
37 void ia_css_sdis_horicoef_vmem_encode (
38         struct sh_css_isp_sdis_hori_coef_tbl *to,
39         const struct ia_css_dvs_coefficients *from,
40         unsigned size)
41 {
42         unsigned aligned_width = from->grid.aligned_width * from->grid.bqs_per_grid_cell;
43         unsigned width         = from->grid.num_hor_coefs;
44         int      padding       = aligned_width-width;
45         unsigned stride        = size/IA_CSS_DVS_NUM_COEF_TYPES/sizeof(short);
46         unsigned total_bytes   = aligned_width*IA_CSS_DVS_NUM_COEF_TYPES*sizeof(short);
47         short   *public        = from->hor_coefs;
48         short   *private       = (short*)to;
49         unsigned type;
50
51         /* Copy the table, add padding */
52         assert(padding >= 0);
53         assert(total_bytes <= size);
54         assert(size % (IA_CSS_DVS_NUM_COEF_TYPES*ISP_VEC_NELEMS*sizeof(short)) == 0);
55
56         for (type = 0; type < IA_CSS_DVS_NUM_COEF_TYPES; type++) {
57                 fill_row(&private[type*stride], &public[type*width], width, padding);
58         }
59 }
60
61 void ia_css_sdis_vertcoef_vmem_encode (
62         struct sh_css_isp_sdis_vert_coef_tbl *to,
63         const struct ia_css_dvs_coefficients *from,
64         unsigned size)
65 {
66         unsigned aligned_height = from->grid.aligned_height * from->grid.bqs_per_grid_cell;
67         unsigned height         = from->grid.num_ver_coefs;
68         int      padding        = aligned_height-height;
69         unsigned stride         = size/IA_CSS_DVS_NUM_COEF_TYPES/sizeof(short);
70         unsigned total_bytes    = aligned_height*IA_CSS_DVS_NUM_COEF_TYPES*sizeof(short);
71         short   *public         = from->ver_coefs;
72         short   *private        = (short*)to;
73         unsigned type;
74
75         /* Copy the table, add padding */
76         assert(padding >= 0);
77         assert(total_bytes <= size);
78         assert(size % (IA_CSS_DVS_NUM_COEF_TYPES*ISP_VEC_NELEMS*sizeof(short)) == 0);
79
80         for (type = 0; type < IA_CSS_DVS_NUM_COEF_TYPES; type++) {
81                 fill_row(&private[type*stride], &public[type*height], height, padding);
82         }
83 }
84
85 void ia_css_sdis_horiproj_encode (
86         struct sh_css_isp_sdis_hori_proj_tbl *to,
87         const struct ia_css_dvs_coefficients *from,
88         unsigned size)
89 {
90         (void)to;
91         (void)from;
92         (void)size;
93 }
94
95 void ia_css_sdis_vertproj_encode (
96         struct sh_css_isp_sdis_vert_proj_tbl *to,
97         const struct ia_css_dvs_coefficients *from,
98         unsigned size)
99 {
100         (void)to;
101         (void)from;
102         (void)size;
103 }
104
105 void ia_css_get_isp_dis_coefficients(
106         struct ia_css_stream *stream,
107         short *horizontal_coefficients,
108         short *vertical_coefficients)
109 {
110         struct ia_css_isp_parameters *params;
111         unsigned int hor_num_isp, ver_num_isp;
112         unsigned int hor_num_3a,  ver_num_3a;
113         int i;
114         struct ia_css_binary *dvs_binary;
115
116         IA_CSS_ENTER("void");
117
118         assert(horizontal_coefficients != NULL);
119         assert(vertical_coefficients != NULL);
120
121         params = stream->isp_params_configs;
122
123         /* Only video pipe supports DVS */
124         dvs_binary = ia_css_stream_get_dvs_binary(stream);
125         if (!dvs_binary)
126                 return;
127
128         hor_num_isp = dvs_binary->dis.coef.pad.width;
129         ver_num_isp = dvs_binary->dis.coef.pad.height;
130         hor_num_3a  = dvs_binary->dis.coef.dim.width;
131         ver_num_3a  = dvs_binary->dis.coef.dim.height;
132
133         for (i = 0; i < IA_CSS_DVS_NUM_COEF_TYPES; i++) {
134                 fill_row(&horizontal_coefficients[i*hor_num_isp],
135                          &params->dvs_coefs.hor_coefs[i*hor_num_3a], hor_num_3a, hor_num_isp-hor_num_3a);
136         }
137         for (i = 0; i < SH_CSS_DIS_VER_NUM_COEF_TYPES(dvs_binary); i++) {
138                 fill_row(&vertical_coefficients[i*ver_num_isp],
139                          &params->dvs_coefs.ver_coefs[i*ver_num_3a], ver_num_3a, ver_num_isp-ver_num_3a);
140         }
141
142         IA_CSS_LEAVE("void");
143 }
144
145 size_t
146 ia_css_sdis_hor_coef_tbl_bytes(
147         const struct ia_css_binary *binary)
148 {
149         if (binary->info->sp.pipeline.isp_pipe_version == 1)
150                 return sizeof(short) * IA_CSS_DVS_NUM_COEF_TYPES  * binary->dis.coef.pad.width;
151         else
152                 return sizeof(short) * IA_CSS_DVS2_NUM_COEF_TYPES * binary->dis.coef.pad.width;
153 }
154
155 size_t
156 ia_css_sdis_ver_coef_tbl_bytes(
157         const struct ia_css_binary *binary)
158 {
159         return sizeof(short) * SH_CSS_DIS_VER_NUM_COEF_TYPES(binary) * binary->dis.coef.pad.height;
160 }
161
162 void
163 ia_css_sdis_init_info(
164         struct ia_css_sdis_info *dis,
165         unsigned sc_3a_dis_width,
166         unsigned sc_3a_dis_padded_width,
167         unsigned sc_3a_dis_height,
168         unsigned isp_pipe_version,
169         unsigned enabled)
170 {
171         if (!enabled) {
172                 struct ia_css_sdis_info default_dis = IA_CSS_DEFAULT_SDIS_INFO;
173                 *dis = default_dis;
174                 return;
175         }
176
177         dis->deci_factor_log2 = SH_CSS_DIS_DECI_FACTOR_LOG2;
178
179         dis->grid.dim.width  =
180                         _ISP_BQS(sc_3a_dis_width) >> SH_CSS_DIS_DECI_FACTOR_LOG2;
181         dis->grid.dim.height =
182                         _ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2;
183         dis->grid.pad.width  =
184                         CEIL_SHIFT(_ISP_BQS(sc_3a_dis_padded_width), SH_CSS_DIS_DECI_FACTOR_LOG2);
185         dis->grid.pad.height =
186                         CEIL_SHIFT(_ISP_BQS(sc_3a_dis_height), SH_CSS_DIS_DECI_FACTOR_LOG2);
187
188         dis->coef.dim.width  =
189                         (_ISP_BQS(sc_3a_dis_width)  >> SH_CSS_DIS_DECI_FACTOR_LOG2) << SH_CSS_DIS_DECI_FACTOR_LOG2;
190         dis->coef.dim.height =
191                         (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2) << SH_CSS_DIS_DECI_FACTOR_LOG2;
192         dis->coef.pad.width  =
193                         __ISP_SDIS_HOR_COEF_NUM_VECS(sc_3a_dis_padded_width) * ISP_VEC_NELEMS;
194         dis->coef.pad.height =
195                         __ISP_SDIS_VER_COEF_NUM_VECS(sc_3a_dis_height) * ISP_VEC_NELEMS;
196         if (isp_pipe_version == 1) {
197                 dis->proj.dim.width  =
198                         _ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2;
199                 dis->proj.dim.height =
200                         _ISP_BQS(sc_3a_dis_width)  >> SH_CSS_DIS_DECI_FACTOR_LOG2;
201         } else {
202                 dis->proj.dim.width  =
203                         (_ISP_BQS(sc_3a_dis_width)  >> SH_CSS_DIS_DECI_FACTOR_LOG2) *
204                         (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2);
205                 dis->proj.dim.height =
206                         (_ISP_BQS(sc_3a_dis_width)  >> SH_CSS_DIS_DECI_FACTOR_LOG2) *
207                         (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2);
208         }
209         dis->proj.pad.width  =
210                         __ISP_SDIS_HOR_PROJ_NUM_ISP(sc_3a_dis_padded_width,
211                                 sc_3a_dis_height,
212                                 SH_CSS_DIS_DECI_FACTOR_LOG2,
213                                 isp_pipe_version);
214         dis->proj.pad.height =
215                         __ISP_SDIS_VER_PROJ_NUM_ISP(sc_3a_dis_padded_width,
216                                 SH_CSS_DIS_DECI_FACTOR_LOG2);
217 }
218
219 void ia_css_sdis_clear_coefficients(
220         struct ia_css_dvs_coefficients *dvs_coefs)
221 {
222         dvs_coefs->hor_coefs = NULL;
223         dvs_coefs->ver_coefs = NULL;
224 }
225
226 enum ia_css_err
227 ia_css_get_dvs_statistics(
228         struct ia_css_dvs_statistics           *host_stats,
229         const struct ia_css_isp_dvs_statistics *isp_stats)
230 {
231         struct ia_css_isp_dvs_statistics_map *map;
232         enum ia_css_err ret = IA_CSS_SUCCESS;
233
234         IA_CSS_ENTER("host_stats=%p, isp_stats=%p", host_stats, isp_stats);
235
236         assert(host_stats != NULL);
237         assert(isp_stats != NULL);
238
239         map = ia_css_isp_dvs_statistics_map_allocate(isp_stats, NULL);
240         if (map) {
241                 mmgr_load(isp_stats->data_ptr, map->data_ptr, isp_stats->size);
242                 ia_css_translate_dvs_statistics(host_stats, map);
243                 ia_css_isp_dvs_statistics_map_free(map);
244         } else {
245                 IA_CSS_ERROR("out of memory");
246                 ret = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
247         }
248
249         IA_CSS_LEAVE_ERR(ret);
250         return ret;
251 }
252
253 void
254 ia_css_translate_dvs_statistics(
255         struct ia_css_dvs_statistics               *host_stats,
256         const struct ia_css_isp_dvs_statistics_map *isp_stats)
257 {
258         unsigned int hor_num_isp, ver_num_isp, hor_num_dvs, ver_num_dvs, i;
259         int32_t *hor_ptr_dvs, *ver_ptr_dvs, *hor_ptr_isp, *ver_ptr_isp;
260
261         assert(host_stats != NULL);
262         assert(host_stats->hor_proj != NULL);
263         assert(host_stats->ver_proj != NULL);
264         assert(isp_stats != NULL);
265         assert(isp_stats->hor_proj != NULL);
266         assert(isp_stats->ver_proj != NULL);
267
268         IA_CSS_ENTER("hproj=%p, vproj=%p, haddr=%p, vaddr=%p",
269                      host_stats->hor_proj, host_stats->ver_proj,
270                      isp_stats->hor_proj, isp_stats->ver_proj);
271
272         hor_num_isp = host_stats->grid.aligned_height;
273         ver_num_isp = host_stats->grid.aligned_width;
274         hor_ptr_isp = isp_stats->hor_proj;
275         ver_ptr_isp = isp_stats->ver_proj;
276         hor_num_dvs = host_stats->grid.height;
277         ver_num_dvs = host_stats->grid.width;
278         hor_ptr_dvs = host_stats->hor_proj;
279         ver_ptr_dvs = host_stats->ver_proj;
280
281         for (i = 0; i < IA_CSS_DVS_NUM_COEF_TYPES; i++) {
282                 memcpy(hor_ptr_dvs, hor_ptr_isp, hor_num_dvs * sizeof(int32_t));
283                 hor_ptr_isp += hor_num_isp;
284                 hor_ptr_dvs += hor_num_dvs;
285
286                 memcpy(ver_ptr_dvs, ver_ptr_isp, ver_num_dvs * sizeof(int32_t));
287                 ver_ptr_isp += ver_num_isp;
288                 ver_ptr_dvs += ver_num_dvs;
289         }
290
291         IA_CSS_LEAVE("void");
292 }
293
294 struct ia_css_isp_dvs_statistics *
295 ia_css_isp_dvs_statistics_allocate(
296         const struct ia_css_dvs_grid_info *grid)
297 {
298         struct ia_css_isp_dvs_statistics *me;
299         int hor_size, ver_size;
300
301         assert(grid != NULL);
302
303         IA_CSS_ENTER("grid=%p", grid);
304
305         if (!grid->enable)
306                 return NULL;
307
308         me = sh_css_calloc(1,sizeof(*me));
309         if (!me)
310                 goto err;
311
312         hor_size = CEIL_MUL(sizeof(int) * IA_CSS_DVS_NUM_COEF_TYPES * grid->aligned_height,
313                             HIVE_ISP_DDR_WORD_BYTES);
314         ver_size = CEIL_MUL(sizeof(int) * IA_CSS_DVS_NUM_COEF_TYPES * grid->aligned_width,
315                             HIVE_ISP_DDR_WORD_BYTES);
316
317
318         me->size = hor_size + ver_size;
319         me->data_ptr = mmgr_malloc(me->size);
320         if (me->data_ptr == mmgr_NULL)
321                 goto err;
322         me->hor_size = hor_size;
323         me->hor_proj = me->data_ptr;
324         me->ver_size = ver_size;
325         me->ver_proj = me->data_ptr + hor_size;
326
327         IA_CSS_LEAVE("return=%p", me);
328
329         return me;
330 err:
331         ia_css_isp_dvs_statistics_free(me);
332
333         IA_CSS_LEAVE("return=%p", NULL);
334
335         return NULL;
336 }
337
338 struct ia_css_isp_dvs_statistics_map *
339 ia_css_isp_dvs_statistics_map_allocate(
340         const struct ia_css_isp_dvs_statistics *isp_stats,
341         void *data_ptr)
342 {
343         struct ia_css_isp_dvs_statistics_map *me;
344         /* Windows compiler does not like adding sizes to a void *
345          * so we use a local char * instead. */
346         char *base_ptr;
347
348         me = sh_css_malloc(sizeof(*me));
349         if (!me) {
350                 IA_CSS_LOG("cannot allocate memory");
351                 goto err;
352         }
353
354         me->data_ptr = data_ptr;
355         me->data_allocated = data_ptr == NULL;
356
357         if (!me->data_ptr) {
358                 me->data_ptr = sh_css_malloc(isp_stats->size);
359                 if (!me->data_ptr) {
360                         IA_CSS_LOG("cannot allocate memory");
361                         goto err;
362                 }
363         }
364         base_ptr = me->data_ptr;
365
366         me->size = isp_stats->size;
367         /* GCC complains when we assign a char * to a void *, so these
368          * casts are necessary unfortunately. */
369         me->hor_proj = (void*)base_ptr;
370         me->ver_proj = (void*)(base_ptr + isp_stats->hor_size);
371
372         return me;
373 err:
374         if (me)
375                 sh_css_free(me);
376         return NULL;
377 }
378
379 void
380 ia_css_isp_dvs_statistics_map_free(struct ia_css_isp_dvs_statistics_map *me)
381 {
382         if (me) {
383                 if (me->data_allocated)
384                         sh_css_free(me->data_ptr);
385                 sh_css_free(me);
386         }
387 }
388
389 void
390 ia_css_isp_dvs_statistics_free(struct ia_css_isp_dvs_statistics *me)
391 {
392         if (me != NULL) {
393                 hmm_free(me->data_ptr);
394                 sh_css_free(me);
395         }
396 }
397
398 void ia_css_sdis_horicoef_debug_dtrace(
399         const struct ia_css_dvs_coefficients *config, unsigned level)
400 {
401         (void)config;
402         (void)level;
403 }
404
405 void ia_css_sdis_vertcoef_debug_dtrace(
406         const struct ia_css_dvs_coefficients *config, unsigned level)
407 {
408         (void)config;
409         (void)level;
410 }
411
412 void ia_css_sdis_horiproj_debug_dtrace(
413         const struct ia_css_dvs_coefficients *config, unsigned level)
414 {
415         (void)config;
416         (void)level;
417 }
418
419 void ia_css_sdis_vertproj_debug_dtrace(
420         const struct ia_css_dvs_coefficients *config, unsigned level)
421 {
422         (void)config;
423         (void)level;
424 }