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