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