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