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