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 			 &params->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 			 &params->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