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