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