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 {
235 struct ia_css_isp_dvs_statistics_map *map;
236 int ret = 0;
237
238 IA_CSS_ENTER("host_stats=%p, isp_stats=%p", host_stats, isp_stats);
239
240 assert(host_stats);
241 assert(isp_stats);
242
243 map = ia_css_isp_dvs_statistics_map_allocate(isp_stats, NULL);
244 if (map) {
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 IA_CSS_ERROR("out of memory");
250 ret = -ENOMEM;
251 }
252
253 IA_CSS_LEAVE_ERR(ret);
254 return ret;
255 }
256
257 void
ia_css_translate_dvs_statistics(struct ia_css_dvs_statistics * host_stats,const struct ia_css_isp_dvs_statistics_map * isp_stats)258 ia_css_translate_dvs_statistics(
259 struct ia_css_dvs_statistics *host_stats,
260 const struct ia_css_isp_dvs_statistics_map *isp_stats)
261 {
262 unsigned int hor_num_isp, ver_num_isp, hor_num_dvs, ver_num_dvs, i;
263 s32 *hor_ptr_dvs, *ver_ptr_dvs, *hor_ptr_isp, *ver_ptr_isp;
264
265 assert(host_stats);
266 assert(host_stats->hor_proj);
267 assert(host_stats->ver_proj);
268 assert(isp_stats);
269 assert(isp_stats->hor_proj);
270 assert(isp_stats->ver_proj);
271
272 IA_CSS_ENTER("hproj=%p, vproj=%p, haddr=%p, vaddr=%p",
273 host_stats->hor_proj, host_stats->ver_proj,
274 isp_stats->hor_proj, isp_stats->ver_proj);
275
276 hor_num_isp = host_stats->grid.aligned_height;
277 ver_num_isp = host_stats->grid.aligned_width;
278 hor_ptr_isp = isp_stats->hor_proj;
279 ver_ptr_isp = isp_stats->ver_proj;
280 hor_num_dvs = host_stats->grid.height;
281 ver_num_dvs = host_stats->grid.width;
282 hor_ptr_dvs = host_stats->hor_proj;
283 ver_ptr_dvs = host_stats->ver_proj;
284
285 for (i = 0; i < IA_CSS_DVS_NUM_COEF_TYPES; i++) {
286 memcpy(hor_ptr_dvs, hor_ptr_isp, hor_num_dvs * sizeof(int32_t));
287 hor_ptr_isp += hor_num_isp;
288 hor_ptr_dvs += hor_num_dvs;
289
290 memcpy(ver_ptr_dvs, ver_ptr_isp, ver_num_dvs * sizeof(int32_t));
291 ver_ptr_isp += ver_num_isp;
292 ver_ptr_dvs += ver_num_dvs;
293 }
294
295 IA_CSS_LEAVE("void");
296 }
297
298 struct ia_css_isp_dvs_statistics *
ia_css_isp_dvs_statistics_allocate(const struct ia_css_dvs_grid_info * grid)299 ia_css_isp_dvs_statistics_allocate(
300 const struct ia_css_dvs_grid_info *grid)
301 {
302 struct ia_css_isp_dvs_statistics *me;
303 int hor_size, ver_size;
304
305 assert(grid);
306
307 IA_CSS_ENTER("grid=%p", grid);
308
309 if (!grid->enable)
310 return NULL;
311
312 me = kvcalloc(1, sizeof(*me), GFP_KERNEL);
313 if (!me)
314 goto err;
315
316 hor_size = CEIL_MUL(sizeof(int) * IA_CSS_DVS_NUM_COEF_TYPES *
317 grid->aligned_height,
318 HIVE_ISP_DDR_WORD_BYTES);
319 ver_size = CEIL_MUL(sizeof(int) * IA_CSS_DVS_NUM_COEF_TYPES *
320 grid->aligned_width,
321 HIVE_ISP_DDR_WORD_BYTES);
322
323 me->size = hor_size + ver_size;
324 me->data_ptr = hmm_alloc(me->size);
325 if (me->data_ptr == mmgr_NULL)
326 goto err;
327 me->hor_size = hor_size;
328 me->hor_proj = me->data_ptr;
329 me->ver_size = ver_size;
330 me->ver_proj = me->data_ptr + hor_size;
331
332 IA_CSS_LEAVE("return=%p", me);
333
334 return me;
335 err:
336 ia_css_isp_dvs_statistics_free(me);
337
338 IA_CSS_LEAVE("return=%p", NULL);
339
340 return NULL;
341 }
342
343 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)344 ia_css_isp_dvs_statistics_map_allocate(
345 const struct ia_css_isp_dvs_statistics *isp_stats,
346 void *data_ptr)
347 {
348 struct ia_css_isp_dvs_statistics_map *me;
349 /* Windows compiler does not like adding sizes to a void *
350 * so we use a local char * instead. */
351 char *base_ptr;
352
353 me = kvmalloc(sizeof(*me), GFP_KERNEL);
354 if (!me) {
355 IA_CSS_LOG("cannot allocate memory");
356 goto err;
357 }
358
359 me->data_ptr = data_ptr;
360 me->data_allocated = !data_ptr;
361
362 if (!me->data_ptr) {
363 me->data_ptr = kvmalloc(isp_stats->size, GFP_KERNEL);
364 if (!me->data_ptr) {
365 IA_CSS_LOG("cannot allocate memory");
366 goto err;
367 }
368 }
369 base_ptr = me->data_ptr;
370
371 me->size = isp_stats->size;
372 /* GCC complains when we assign a char * to a void *, so these
373 * casts are necessary unfortunately. */
374 me->hor_proj = (void *)base_ptr;
375 me->ver_proj = (void *)(base_ptr + isp_stats->hor_size);
376
377 return me;
378 err:
379 kvfree(me);
380 return NULL;
381 }
382
383 void
ia_css_isp_dvs_statistics_map_free(struct ia_css_isp_dvs_statistics_map * me)384 ia_css_isp_dvs_statistics_map_free(struct ia_css_isp_dvs_statistics_map *me)
385 {
386 if (me) {
387 if (me->data_allocated)
388 kvfree(me->data_ptr);
389 kvfree(me);
390 }
391 }
392
393 void
ia_css_isp_dvs_statistics_free(struct ia_css_isp_dvs_statistics * me)394 ia_css_isp_dvs_statistics_free(struct ia_css_isp_dvs_statistics *me)
395 {
396 if (me) {
397 hmm_free(me->data_ptr);
398 kvfree(me);
399 }
400 }
401
ia_css_sdis_horicoef_debug_dtrace(const struct ia_css_dvs_coefficients * config,unsigned int level)402 void ia_css_sdis_horicoef_debug_dtrace(
403 const struct ia_css_dvs_coefficients *config, unsigned int level)
404 {
405 (void)config;
406 (void)level;
407 }
408
ia_css_sdis_vertcoef_debug_dtrace(const struct ia_css_dvs_coefficients * config,unsigned int level)409 void ia_css_sdis_vertcoef_debug_dtrace(
410 const struct ia_css_dvs_coefficients *config, unsigned int level)
411 {
412 (void)config;
413 (void)level;
414 }
415
ia_css_sdis_horiproj_debug_dtrace(const struct ia_css_dvs_coefficients * config,unsigned int level)416 void ia_css_sdis_horiproj_debug_dtrace(
417 const struct ia_css_dvs_coefficients *config, unsigned int level)
418 {
419 (void)config;
420 (void)level;
421 }
422
ia_css_sdis_vertproj_debug_dtrace(const struct ia_css_dvs_coefficients * config,unsigned int level)423 void ia_css_sdis_vertproj_debug_dtrace(
424 const struct ia_css_dvs_coefficients *config, unsigned int level)
425 {
426 (void)config;
427 (void)level;
428 }
429