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_sdis2.host.h"
21 
22 const struct ia_css_dvs2_coefficients default_sdis2_config = {
23 	.grid = { 0, 0, 0, 0, 0, 0, 0, 0 },
24 	.hor_coefs = { NULL, NULL, NULL, NULL },
25 	.ver_coefs = { NULL, NULL, NULL, NULL },
26 };
27 
28 static void
29 fill_row(short *private, const short *public, unsigned int width,
30 	 unsigned int padding)
31 {
32 	memcpy(private, public, width * sizeof(short));
33 	memset(&private[width], 0, padding * sizeof(short));
34 }
35 
36 void ia_css_sdis2_horicoef_vmem_encode(
37     struct sh_css_isp_sdis_hori_coef_tbl *to,
38     const struct ia_css_dvs2_coefficients *from,
39     unsigned int size)
40 {
41 	unsigned int aligned_width = from->grid.aligned_width *
42 				     from->grid.bqs_per_grid_cell;
43 	unsigned int width         = from->grid.num_hor_coefs;
44 	int      padding       = aligned_width - width;
45 	unsigned int stride        = size / IA_CSS_DVS2_NUM_COEF_TYPES / sizeof(short);
46 	unsigned int total_bytes   = aligned_width * IA_CSS_DVS2_NUM_COEF_TYPES *
47 				     sizeof(short);
48 	short   *private       = (short *)to;
49 
50 	/* Copy the table, add padding */
51 	assert(padding >= 0);
52 	assert(total_bytes <= size);
53 	assert(size % (IA_CSS_DVS2_NUM_COEF_TYPES * ISP_VEC_NELEMS * sizeof(
54 			   short)) == 0);
55 	fill_row(&private[0 * stride], from->hor_coefs.odd_real,  width, padding);
56 	fill_row(&private[1 * stride], from->hor_coefs.odd_imag,  width, padding);
57 	fill_row(&private[2 * stride], from->hor_coefs.even_real, width, padding);
58 	fill_row(&private[3 * stride], from->hor_coefs.even_imag, width, padding);
59 }
60 
61 void ia_css_sdis2_vertcoef_vmem_encode(
62     struct sh_css_isp_sdis_vert_coef_tbl *to,
63     const struct ia_css_dvs2_coefficients *from,
64     unsigned int size)
65 {
66 	unsigned int aligned_height = from->grid.aligned_height *
67 				      from->grid.bqs_per_grid_cell;
68 	unsigned int height         = from->grid.num_ver_coefs;
69 	int      padding        = aligned_height - height;
70 	unsigned int stride         = size / IA_CSS_DVS2_NUM_COEF_TYPES / sizeof(short);
71 	unsigned int total_bytes    = aligned_height * IA_CSS_DVS2_NUM_COEF_TYPES *
72 				      sizeof(short);
73 	short   *private        = (short *)to;
74 
75 	/* Copy the table, add padding */
76 	assert(padding >= 0);
77 	assert(total_bytes <= size);
78 	assert(size % (IA_CSS_DVS2_NUM_COEF_TYPES * ISP_VEC_NELEMS * sizeof(
79 			   short)) == 0);
80 	fill_row(&private[0 * stride], from->ver_coefs.odd_real,  height, padding);
81 	fill_row(&private[1 * stride], from->ver_coefs.odd_imag,  height, padding);
82 	fill_row(&private[2 * stride], from->ver_coefs.even_real, height, padding);
83 	fill_row(&private[3 * stride], from->ver_coefs.even_imag, height, padding);
84 }
85 
86 void ia_css_sdis2_horiproj_encode(
87     struct sh_css_isp_sdis_hori_proj_tbl *to,
88     const struct ia_css_dvs2_coefficients *from,
89     unsigned int size)
90 {
91 	(void)to;
92 	(void)from;
93 	(void)size;
94 }
95 
96 void ia_css_sdis2_vertproj_encode(
97     struct sh_css_isp_sdis_vert_proj_tbl *to,
98     const struct ia_css_dvs2_coefficients *from,
99     unsigned int size)
100 {
101 	(void)to;
102 	(void)from;
103 	(void)size;
104 }
105 
106 void ia_css_get_isp_dvs2_coefficients(
107     struct ia_css_stream *stream,
108     short *hor_coefs_odd_real,
109     short *hor_coefs_odd_imag,
110     short *hor_coefs_even_real,
111     short *hor_coefs_even_imag,
112     short *ver_coefs_odd_real,
113     short *ver_coefs_odd_imag,
114     short *ver_coefs_even_real,
115     short *ver_coefs_even_imag)
116 {
117 	struct ia_css_isp_parameters *params;
118 	unsigned int hor_num_3a, ver_num_3a;
119 	unsigned int hor_num_isp, ver_num_isp;
120 	struct ia_css_binary *dvs_binary;
121 
122 	IA_CSS_ENTER("void");
123 
124 	assert(stream);
125 	assert(hor_coefs_odd_real);
126 	assert(hor_coefs_odd_imag);
127 	assert(hor_coefs_even_real);
128 	assert(hor_coefs_even_imag);
129 	assert(ver_coefs_odd_real);
130 	assert(ver_coefs_odd_imag);
131 	assert(ver_coefs_even_real);
132 	assert(ver_coefs_even_imag);
133 
134 	params = stream->isp_params_configs;
135 
136 	/* Only video pipe supports DVS */
137 	dvs_binary = ia_css_stream_get_dvs_binary(stream);
138 	if (!dvs_binary)
139 		return;
140 
141 	hor_num_3a  = dvs_binary->dis.coef.dim.width;
142 	ver_num_3a  = dvs_binary->dis.coef.dim.height;
143 	hor_num_isp = dvs_binary->dis.coef.pad.width;
144 	ver_num_isp = dvs_binary->dis.coef.pad.height;
145 
146 	memcpy(hor_coefs_odd_real,  params->dvs2_coefs.hor_coefs.odd_real,
147 	       hor_num_3a * sizeof(short));
148 	memcpy(hor_coefs_odd_imag,  params->dvs2_coefs.hor_coefs.odd_imag,
149 	       hor_num_3a * sizeof(short));
150 	memcpy(hor_coefs_even_real, params->dvs2_coefs.hor_coefs.even_real,
151 	       hor_num_3a * sizeof(short));
152 	memcpy(hor_coefs_even_imag, params->dvs2_coefs.hor_coefs.even_imag,
153 	       hor_num_3a * sizeof(short));
154 	memcpy(ver_coefs_odd_real,  params->dvs2_coefs.ver_coefs.odd_real,
155 	       ver_num_3a * sizeof(short));
156 	memcpy(ver_coefs_odd_imag,  params->dvs2_coefs.ver_coefs.odd_imag,
157 	       ver_num_3a * sizeof(short));
158 	memcpy(ver_coefs_even_real, params->dvs2_coefs.ver_coefs.even_real,
159 	       ver_num_3a * sizeof(short));
160 	memcpy(ver_coefs_even_imag, params->dvs2_coefs.ver_coefs.even_imag,
161 	       ver_num_3a * sizeof(short));
162 
163 	IA_CSS_LEAVE("void");
164 }
165 
166 void ia_css_sdis2_clear_coefficients(
167     struct ia_css_dvs2_coefficients *dvs2_coefs)
168 {
169 	dvs2_coefs->hor_coefs.odd_real  = NULL;
170 	dvs2_coefs->hor_coefs.odd_imag  = NULL;
171 	dvs2_coefs->hor_coefs.even_real = NULL;
172 	dvs2_coefs->hor_coefs.even_imag = NULL;
173 	dvs2_coefs->ver_coefs.odd_real  = NULL;
174 	dvs2_coefs->ver_coefs.odd_imag  = NULL;
175 	dvs2_coefs->ver_coefs.even_real = NULL;
176 	dvs2_coefs->ver_coefs.even_imag = NULL;
177 }
178 
179 int
180 ia_css_get_dvs2_statistics(
181     struct ia_css_dvs2_statistics          *host_stats,
182     const struct ia_css_isp_dvs_statistics *isp_stats) {
183 	struct ia_css_isp_dvs_statistics_map *map;
184 	int ret = 0;
185 
186 	IA_CSS_ENTER("host_stats=%p, isp_stats=%p", host_stats, isp_stats);
187 
188 	assert(host_stats);
189 	assert(isp_stats);
190 
191 	map = ia_css_isp_dvs_statistics_map_allocate(isp_stats, NULL);
192 	if (map)
193 	{
194 		hmm_load(isp_stats->data_ptr, map->data_ptr, isp_stats->size);
195 		ia_css_translate_dvs2_statistics(host_stats, map);
196 		ia_css_isp_dvs_statistics_map_free(map);
197 	} else
198 	{
199 		IA_CSS_ERROR("out of memory");
200 		ret = -ENOMEM;
201 	}
202 
203 	IA_CSS_LEAVE_ERR(ret);
204 	return ret;
205 }
206 
207 void
208 ia_css_translate_dvs2_statistics(
209     struct ia_css_dvs2_statistics		   *host_stats,
210     const struct ia_css_isp_dvs_statistics_map *isp_stats)
211 {
212 	unsigned int size_bytes, table_width, table_size, height;
213 	unsigned int src_offset = 0, dst_offset = 0;
214 	s32 *htemp_ptr, *vtemp_ptr;
215 
216 	assert(host_stats);
217 	assert(host_stats->hor_prod.odd_real);
218 	assert(host_stats->hor_prod.odd_imag);
219 	assert(host_stats->hor_prod.even_real);
220 	assert(host_stats->hor_prod.even_imag);
221 	assert(host_stats->ver_prod.odd_real);
222 	assert(host_stats->ver_prod.odd_imag);
223 	assert(host_stats->ver_prod.even_real);
224 	assert(host_stats->ver_prod.even_imag);
225 	assert(isp_stats);
226 	assert(isp_stats->hor_proj);
227 	assert(isp_stats->ver_proj);
228 
229 	IA_CSS_ENTER("hor_coefs.odd_real=%p, hor_coefs.odd_imag=%p, hor_coefs.even_real=%p, hor_coefs.even_imag=%p, ver_coefs.odd_real=%p, ver_coefs.odd_imag=%p, ver_coefs.even_real=%p, ver_coefs.even_imag=%p, haddr=%p, vaddr=%p",
230 		     host_stats->hor_prod.odd_real, host_stats->hor_prod.odd_imag,
231 		     host_stats->hor_prod.even_real, host_stats->hor_prod.even_imag,
232 		     host_stats->ver_prod.odd_real, host_stats->ver_prod.odd_imag,
233 		     host_stats->ver_prod.even_real, host_stats->ver_prod.even_imag,
234 		     isp_stats->hor_proj, isp_stats->ver_proj);
235 
236 	/* Host side: reflecting the true width in bytes */
237 	size_bytes = host_stats->grid.aligned_width * sizeof(*htemp_ptr);
238 
239 	/* DDR side: need to be aligned to the system bus width */
240 	/* statistics table width in terms of 32-bit words*/
241 	table_width = CEIL_MUL(size_bytes,
242 			       HIVE_ISP_DDR_WORD_BYTES) / sizeof(*htemp_ptr);
243 	table_size = table_width * host_stats->grid.aligned_height;
244 
245 	htemp_ptr = isp_stats->hor_proj; /* horizontal stats */
246 	vtemp_ptr = isp_stats->ver_proj; /* vertical stats */
247 	for (height = 0; height < host_stats->grid.aligned_height; height++) {
248 		/* hor stats */
249 		memcpy(host_stats->hor_prod.odd_real + dst_offset,
250 		       &htemp_ptr[0 * table_size + src_offset], size_bytes);
251 		memcpy(host_stats->hor_prod.odd_imag + dst_offset,
252 		       &htemp_ptr[1 * table_size + src_offset], size_bytes);
253 		memcpy(host_stats->hor_prod.even_real + dst_offset,
254 		       &htemp_ptr[2 * table_size + src_offset], size_bytes);
255 		memcpy(host_stats->hor_prod.even_imag + dst_offset,
256 		       &htemp_ptr[3 * table_size + src_offset], size_bytes);
257 
258 		/* ver stats */
259 		memcpy(host_stats->ver_prod.odd_real + dst_offset,
260 		       &vtemp_ptr[0 * table_size + src_offset], size_bytes);
261 		memcpy(host_stats->ver_prod.odd_imag + dst_offset,
262 		       &vtemp_ptr[1 * table_size + src_offset], size_bytes);
263 		memcpy(host_stats->ver_prod.even_real + dst_offset,
264 		       &vtemp_ptr[2 * table_size + src_offset], size_bytes);
265 		memcpy(host_stats->ver_prod.even_imag + dst_offset,
266 		       &vtemp_ptr[3 * table_size + src_offset], size_bytes);
267 
268 		src_offset += table_width; /* aligned table width */
269 		dst_offset += host_stats->grid.aligned_width;
270 	}
271 
272 	IA_CSS_LEAVE("void");
273 }
274 
275 struct ia_css_isp_dvs_statistics *
276 ia_css_isp_dvs2_statistics_allocate(
277     const struct ia_css_dvs_grid_info *grid)
278 {
279 	struct ia_css_isp_dvs_statistics *me;
280 	int size;
281 
282 	assert(grid);
283 
284 	IA_CSS_ENTER("grid=%p", grid);
285 
286 	if (!grid->enable)
287 		return NULL;
288 
289 	me = kvcalloc(1, sizeof(*me), GFP_KERNEL);
290 	if (!me)
291 		goto err;
292 
293 	/* on ISP 2 SDIS DMA model, every row of projection table width must be
294 	   aligned to HIVE_ISP_DDR_WORD_BYTES
295 	*/
296 	size = CEIL_MUL(sizeof(int) * grid->aligned_width, HIVE_ISP_DDR_WORD_BYTES)
297 	       * grid->aligned_height * IA_CSS_DVS2_NUM_COEF_TYPES;
298 
299 	me->size = 2 * size;
300 	me->data_ptr = hmm_alloc(me->size, HMM_BO_PRIVATE, 0, NULL, 0);
301 	if (me->data_ptr == mmgr_NULL)
302 		goto err;
303 	me->hor_proj = me->data_ptr;
304 	me->hor_size = size;
305 	me->ver_proj = me->data_ptr + size;
306 	me->ver_size = size;
307 
308 	IA_CSS_LEAVE("return=%p", me);
309 	return me;
310 err:
311 	ia_css_isp_dvs2_statistics_free(me);
312 	IA_CSS_LEAVE("return=%p", NULL);
313 
314 	return NULL;
315 }
316 
317 void
318 ia_css_isp_dvs2_statistics_free(struct ia_css_isp_dvs_statistics *me)
319 {
320 	if (me) {
321 		hmm_free(me->data_ptr);
322 		kvfree(me);
323 	}
324 }
325 
326 void ia_css_sdis2_horicoef_debug_dtrace(
327     const struct ia_css_dvs2_coefficients *config, unsigned int level)
328 {
329 	(void)config;
330 	(void)level;
331 }
332 
333 void ia_css_sdis2_vertcoef_debug_dtrace(
334     const struct ia_css_dvs2_coefficients *config, unsigned int level)
335 {
336 	(void)config;
337 	(void)level;
338 }
339 
340 void ia_css_sdis2_horiproj_debug_dtrace(
341     const struct ia_css_dvs2_coefficients *config, unsigned int level)
342 {
343 	(void)config;
344 	(void)level;
345 }
346 
347 void ia_css_sdis2_vertproj_debug_dtrace(
348     const struct ia_css_dvs2_coefficients *config, unsigned int level)
349 {
350 	(void)config;
351 	(void)level;
352 }
353