xref: /linux/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c (revision bf4afc53b77aeaa48b5409da5c8da6bb4eff7f43)
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 "sh_css_param_dvs.h"
8 #include <assert_support.h>
9 #include <type_support.h>
10 #include <ia_css_err.h>
11 #include <ia_css_types.h>
12 #include "ia_css_debug.h"
13 
14 static struct ia_css_dvs_6axis_config *
alloc_dvs_6axis_table(const struct ia_css_resolution * frame_res,struct ia_css_dvs_6axis_config * dvs_config_src)15 alloc_dvs_6axis_table(const struct ia_css_resolution *frame_res,
16 		      struct ia_css_dvs_6axis_config  *dvs_config_src)
17 {
18 	unsigned int width_y = 0;
19 	unsigned int height_y = 0;
20 	unsigned int width_uv = 0;
21 	unsigned int height_uv = 0;
22 	int err = 0;
23 	struct ia_css_dvs_6axis_config  *dvs_config = NULL;
24 
25 	dvs_config = kvmalloc_obj(struct ia_css_dvs_6axis_config);
26 	if (!dvs_config)	{
27 		IA_CSS_ERROR("out of memory");
28 		err = -ENOMEM;
29 	} else {
30 		/*Initialize new struct with latest config settings*/
31 		if (dvs_config_src) {
32 			dvs_config->width_y = width_y = dvs_config_src->width_y;
33 			dvs_config->height_y = height_y = dvs_config_src->height_y;
34 			dvs_config->width_uv = width_uv = dvs_config_src->width_uv;
35 			dvs_config->height_uv = height_uv = dvs_config_src->height_uv;
36 			IA_CSS_LOG("alloc_dvs_6axis_table Y: W %d H %d", width_y, height_y);
37 		} else if (frame_res) {
38 			dvs_config->width_y = width_y = DVS_TABLE_IN_BLOCKDIM_X_LUMA(frame_res->width);
39 			dvs_config->height_y = height_y = DVS_TABLE_IN_BLOCKDIM_Y_LUMA(
40 							      frame_res->height);
41 			dvs_config->width_uv = width_uv = DVS_TABLE_IN_BLOCKDIM_X_CHROMA(
42 							      frame_res->width /
43 							      2); /* UV = Y/2, depens on colour format YUV 4.2.0*/
44 			dvs_config->height_uv = height_uv = DVS_TABLE_IN_BLOCKDIM_Y_CHROMA(
45 								frame_res->height /
46 								2);/* UV = Y/2, depens on colour format YUV 4.2.0*/
47 			IA_CSS_LOG("alloc_dvs_6axis_table Y: W %d H %d", width_y, height_y);
48 		}
49 
50 		/* Generate Y buffers  */
51 		dvs_config->xcoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
52 						 GFP_KERNEL);
53 		if (!dvs_config->xcoords_y) {
54 			IA_CSS_ERROR("out of memory");
55 			err = -ENOMEM;
56 			goto exit;
57 		}
58 
59 		dvs_config->ycoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
60 						 GFP_KERNEL);
61 		if (!dvs_config->ycoords_y) {
62 			IA_CSS_ERROR("out of memory");
63 			err = -ENOMEM;
64 			goto exit;
65 		}
66 
67 		/* Generate UV buffers  */
68 		IA_CSS_LOG("UV W %d H %d", width_uv, height_uv);
69 
70 		dvs_config->xcoords_uv = kvmalloc(width_uv * height_uv * sizeof(uint32_t),
71 						  GFP_KERNEL);
72 		if (!dvs_config->xcoords_uv) {
73 			IA_CSS_ERROR("out of memory");
74 			err = -ENOMEM;
75 			goto exit;
76 		}
77 
78 		dvs_config->ycoords_uv = kvmalloc(width_uv * height_uv * sizeof(uint32_t),
79 						  GFP_KERNEL);
80 		if (!dvs_config->ycoords_uv) {
81 			IA_CSS_ERROR("out of memory");
82 			err = -ENOMEM;
83 		}
84 exit:
85 		if (err) {
86 			free_dvs_6axis_table(
87 			    &dvs_config); /* we might have allocated some memory, release this */
88 			dvs_config = NULL;
89 		}
90 	}
91 
92 	IA_CSS_LEAVE("dvs_config=%p", dvs_config);
93 	return dvs_config;
94 }
95 
96 static void
init_dvs_6axis_table_from_default(struct ia_css_dvs_6axis_config * dvs_config,const struct ia_css_resolution * dvs_offset)97 init_dvs_6axis_table_from_default(struct ia_css_dvs_6axis_config *dvs_config,
98 				  const struct ia_css_resolution *dvs_offset)
99 {
100 	unsigned int x, y;
101 	unsigned int width_y = dvs_config->width_y;
102 	unsigned int height_y = dvs_config->height_y;
103 	unsigned int width_uv = dvs_config->width_uv;
104 	unsigned int height_uv = dvs_config->height_uv;
105 
106 	IA_CSS_LOG("Env_X=%d, Env_Y=%d, width_y=%d, height_y=%d",
107 		   dvs_offset->width, dvs_offset->height, width_y, height_y);
108 	for (y = 0; y < height_y; y++) {
109 		for (x = 0; x < width_y; x++) {
110 			dvs_config->xcoords_y[y * width_y + x] =  (dvs_offset->width + x *
111 				DVS_BLOCKDIM_X) << DVS_COORD_FRAC_BITS;
112 		}
113 	}
114 
115 	for (y = 0; y < height_y; y++) {
116 		for (x = 0; x < width_y; x++) {
117 			dvs_config->ycoords_y[y * width_y + x] =  (dvs_offset->height + y *
118 				DVS_BLOCKDIM_Y_LUMA) << DVS_COORD_FRAC_BITS;
119 		}
120 	}
121 
122 	for (y = 0; y < height_uv; y++) {
123 		for (x = 0; x < width_uv;
124 		     x++) { /* Envelope dimensions set in Ypixels hence offset UV = offset Y/2 */
125 			dvs_config->xcoords_uv[y * width_uv + x] =  ((dvs_offset->width / 2) + x *
126 				DVS_BLOCKDIM_X) << DVS_COORD_FRAC_BITS;
127 		}
128 	}
129 
130 	for (y = 0; y < height_uv; y++) {
131 		for (x = 0; x < width_uv;
132 		     x++) { /* Envelope dimensions set in Ypixels hence offset UV = offset Y/2 */
133 			dvs_config->ycoords_uv[y * width_uv + x] =  ((dvs_offset->height / 2) + y *
134 				DVS_BLOCKDIM_Y_CHROMA) <<
135 				DVS_COORD_FRAC_BITS;
136 		}
137 	}
138 }
139 
140 static void
init_dvs_6axis_table_from_config(struct ia_css_dvs_6axis_config * dvs_config,struct ia_css_dvs_6axis_config * dvs_config_src)141 init_dvs_6axis_table_from_config(struct ia_css_dvs_6axis_config *dvs_config,
142 				 struct ia_css_dvs_6axis_config  *dvs_config_src)
143 {
144 	unsigned int width_y = dvs_config->width_y;
145 	unsigned int height_y = dvs_config->height_y;
146 	unsigned int width_uv = dvs_config->width_uv;
147 	unsigned int height_uv = dvs_config->height_uv;
148 
149 	memcpy(dvs_config->xcoords_y, dvs_config_src->xcoords_y,
150 	       (width_y * height_y * sizeof(uint32_t)));
151 	memcpy(dvs_config->ycoords_y, dvs_config_src->ycoords_y,
152 	       (width_y * height_y * sizeof(uint32_t)));
153 	memcpy(dvs_config->xcoords_uv, dvs_config_src->xcoords_uv,
154 	       (width_uv * height_uv * sizeof(uint32_t)));
155 	memcpy(dvs_config->ycoords_uv, dvs_config_src->ycoords_uv,
156 	       (width_uv * height_uv * sizeof(uint32_t)));
157 }
158 
159 struct ia_css_dvs_6axis_config *
generate_dvs_6axis_table(const struct ia_css_resolution * frame_res,const struct ia_css_resolution * dvs_offset)160 generate_dvs_6axis_table(const struct ia_css_resolution *frame_res,
161 			 const struct ia_css_resolution *dvs_offset)
162 {
163 	struct ia_css_dvs_6axis_config *dvs_6axis_table;
164 
165 	assert(frame_res);
166 	assert(dvs_offset);
167 
168 	dvs_6axis_table = alloc_dvs_6axis_table(frame_res, NULL);
169 	if (dvs_6axis_table) {
170 		init_dvs_6axis_table_from_default(dvs_6axis_table, dvs_offset);
171 		return dvs_6axis_table;
172 	}
173 	return NULL;
174 }
175 
176 struct ia_css_dvs_6axis_config *
generate_dvs_6axis_table_from_config(struct ia_css_dvs_6axis_config * dvs_config_src)177 generate_dvs_6axis_table_from_config(struct ia_css_dvs_6axis_config
178 				     *dvs_config_src)
179 {
180 	struct ia_css_dvs_6axis_config *dvs_6axis_table;
181 
182 	assert(dvs_config_src);
183 
184 	dvs_6axis_table = alloc_dvs_6axis_table(NULL, dvs_config_src);
185 	if (dvs_6axis_table) {
186 		init_dvs_6axis_table_from_config(dvs_6axis_table, dvs_config_src);
187 		return dvs_6axis_table;
188 	}
189 	return NULL;
190 }
191 
192 void
free_dvs_6axis_table(struct ia_css_dvs_6axis_config ** dvs_6axis_config)193 free_dvs_6axis_table(struct ia_css_dvs_6axis_config  **dvs_6axis_config)
194 {
195 	if ((dvs_6axis_config) && (*dvs_6axis_config)) {
196 		IA_CSS_ENTER_PRIVATE("dvs_6axis_config %p", (*dvs_6axis_config));
197 		if ((*dvs_6axis_config)->xcoords_y) {
198 			kvfree((*dvs_6axis_config)->xcoords_y);
199 			(*dvs_6axis_config)->xcoords_y = NULL;
200 		}
201 
202 		if ((*dvs_6axis_config)->ycoords_y) {
203 			kvfree((*dvs_6axis_config)->ycoords_y);
204 			(*dvs_6axis_config)->ycoords_y = NULL;
205 		}
206 
207 		/* Free up UV buffers */
208 		if ((*dvs_6axis_config)->xcoords_uv) {
209 			kvfree((*dvs_6axis_config)->xcoords_uv);
210 			(*dvs_6axis_config)->xcoords_uv = NULL;
211 		}
212 
213 		if ((*dvs_6axis_config)->ycoords_uv) {
214 			kvfree((*dvs_6axis_config)->ycoords_uv);
215 			(*dvs_6axis_config)->ycoords_uv = NULL;
216 		}
217 
218 		IA_CSS_LEAVE_PRIVATE("dvs_6axis_config %p", (*dvs_6axis_config));
219 		kvfree(*dvs_6axis_config);
220 		*dvs_6axis_config = NULL;
221 	}
222 }
223 
copy_dvs_6axis_table(struct ia_css_dvs_6axis_config * dvs_config_dst,const struct ia_css_dvs_6axis_config * dvs_config_src)224 void copy_dvs_6axis_table(struct ia_css_dvs_6axis_config *dvs_config_dst,
225 			  const struct ia_css_dvs_6axis_config *dvs_config_src)
226 {
227 	unsigned int width_y;
228 	unsigned int height_y;
229 	unsigned int width_uv;
230 	unsigned int height_uv;
231 
232 	assert(dvs_config_src);
233 	assert(dvs_config_dst);
234 	assert(dvs_config_src->xcoords_y);
235 	assert(dvs_config_src->xcoords_uv);
236 	assert(dvs_config_src->ycoords_y);
237 	assert(dvs_config_src->ycoords_uv);
238 	assert(dvs_config_src->width_y == dvs_config_dst->width_y);
239 	assert(dvs_config_src->width_uv == dvs_config_dst->width_uv);
240 	assert(dvs_config_src->height_y == dvs_config_dst->height_y);
241 	assert(dvs_config_src->height_uv == dvs_config_dst->height_uv);
242 
243 	width_y = dvs_config_src->width_y;
244 	height_y = dvs_config_src->height_y;
245 	width_uv =
246 	    dvs_config_src->width_uv; /* = Y/2, depens on colour format YUV 4.2.0*/
247 	height_uv = dvs_config_src->height_uv;
248 
249 	memcpy(dvs_config_dst->xcoords_y, dvs_config_src->xcoords_y,
250 	       (width_y * height_y * sizeof(uint32_t)));
251 	memcpy(dvs_config_dst->ycoords_y, dvs_config_src->ycoords_y,
252 	       (width_y * height_y * sizeof(uint32_t)));
253 
254 	memcpy(dvs_config_dst->xcoords_uv, dvs_config_src->xcoords_uv,
255 	       (width_uv * height_uv * sizeof(uint32_t)));
256 	memcpy(dvs_config_dst->ycoords_uv, dvs_config_src->ycoords_uv,
257 	       (width_uv * height_uv * sizeof(uint32_t)));
258 }
259 
260 void
ia_css_dvs_statistics_get(enum dvs_statistics_type type,union ia_css_dvs_statistics_host * host_stats,const union ia_css_dvs_statistics_isp * isp_stats)261 ia_css_dvs_statistics_get(enum dvs_statistics_type type,
262 			  union ia_css_dvs_statistics_host  *host_stats,
263 			  const union ia_css_dvs_statistics_isp *isp_stats)
264 {
265 	if (type == DVS_STATISTICS) {
266 		ia_css_get_dvs_statistics(host_stats->p_dvs_statistics_host,
267 					  isp_stats->p_dvs_statistics_isp);
268 	} else if (type == DVS2_STATISTICS) {
269 		ia_css_get_dvs2_statistics(host_stats->p_dvs2_statistics_host,
270 					   isp_stats->p_dvs_statistics_isp);
271 	}
272 	return;
273 }
274