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 "ia_css_frame_public.h"
10 #define IA_CSS_INCLUDE_CONFIGURATIONS
11 #include "ia_css_isp_configs.h"
12
13 #include "ia_css_types.h"
14 #include "ia_css_host_data.h"
15 #include "sh_css_param_dvs.h"
16 #include "sh_css_params.h"
17 #include "ia_css_binary.h"
18 #include "ia_css_debug.h"
19 #include "assert_support.h"
20
21 #include "ia_css_dvs.host.h"
22
23 static const struct ia_css_dvs_configuration default_config = {
24 .info = (struct ia_css_frame_info *)NULL,
25 };
26
27 void
ia_css_dvs_config(struct sh_css_isp_dvs_isp_config * to,const struct ia_css_dvs_configuration * from,unsigned int size)28 ia_css_dvs_config(
29 struct sh_css_isp_dvs_isp_config *to,
30 const struct ia_css_dvs_configuration *from,
31 unsigned int size)
32 {
33 (void)size;
34 to->num_horizontal_blocks =
35 DVS_NUM_BLOCKS_X(from->info->res.width);
36 to->num_vertical_blocks =
37 DVS_NUM_BLOCKS_Y(from->info->res.height);
38 }
39
ia_css_dvs_configure(const struct ia_css_binary * binary,const struct ia_css_frame_info * info)40 int ia_css_dvs_configure(const struct ia_css_binary *binary,
41 const struct ia_css_frame_info *info)
42 {
43 struct ia_css_dvs_configuration config = default_config;
44
45 config.info = info;
46
47 return ia_css_configure_dvs(binary, &config);
48 }
49
50 static void
convert_coords_to_ispparams(struct ia_css_host_data * gdc_warp_table,const struct ia_css_dvs_6axis_config * config,unsigned int i_stride,unsigned int o_width,unsigned int o_height,unsigned int uv_flag)51 convert_coords_to_ispparams(
52 struct ia_css_host_data *gdc_warp_table,
53 const struct ia_css_dvs_6axis_config *config,
54 unsigned int i_stride,
55 unsigned int o_width,
56 unsigned int o_height,
57 unsigned int uv_flag)
58 {
59 unsigned int i, j;
60 gdc_warp_param_mem_t s = { 0 };
61 unsigned int x00, x01, x10, x11,
62 y00, y01, y10, y11;
63
64 unsigned int xmin, ymin, xmax, ymax;
65 unsigned int topleft_x, topleft_y, bottom_x, bottom_y,
66 topleft_x_frac, topleft_y_frac;
67 unsigned int dvs_interp_envelope = (DVS_GDC_INTERP_METHOD == HRT_GDC_BLI_MODE ?
68 DVS_GDC_BLI_INTERP_ENVELOPE : DVS_GDC_BCI_INTERP_ENVELOPE);
69
70 /* number of blocks per height and width */
71 unsigned int num_blocks_y = (uv_flag ? DVS_NUM_BLOCKS_Y_CHROMA(
72 o_height) : DVS_NUM_BLOCKS_Y(o_height));
73 unsigned int num_blocks_x = (uv_flag ? DVS_NUM_BLOCKS_X_CHROMA(
74 o_width) : DVS_NUM_BLOCKS_X(
75 o_width)); // round num_x up to blockdim_x, if it concerns the Y0Y1 block (uv_flag==0) round up to even
76
77 unsigned int in_stride = i_stride * DVS_INPUT_BYTES_PER_PIXEL;
78 unsigned int width, height;
79 unsigned int *xbuff = NULL;
80 unsigned int *ybuff = NULL;
81 struct gdc_warp_param_mem_s *ptr;
82
83 assert(config);
84 assert(gdc_warp_table);
85 assert(gdc_warp_table->address);
86
87 ptr = (struct gdc_warp_param_mem_s *)gdc_warp_table->address;
88
89 ptr += (2 * uv_flag); /* format is Y0 Y1 UV, so UV starts at 3rd position */
90
91 if (uv_flag == 0) {
92 xbuff = config->xcoords_y;
93 ybuff = config->ycoords_y;
94 width = config->width_y;
95 height = config->height_y;
96 } else {
97 xbuff = config->xcoords_uv;
98 ybuff = config->ycoords_uv;
99 width = config->width_uv;
100 height = config->height_uv;
101 }
102
103 IA_CSS_LOG("blockdim_x %d blockdim_y %d",
104 DVS_BLOCKDIM_X, DVS_BLOCKDIM_Y_LUMA >> uv_flag);
105 IA_CSS_LOG("num_blocks_x %d num_blocks_y %d", num_blocks_x, num_blocks_y);
106 IA_CSS_LOG("width %d height %d", width, height);
107
108 assert(width == num_blocks_x +
109 1); // the width and height of the provided morphing table should be 1 more than the number of blocks
110 assert(height == num_blocks_y + 1);
111
112 for (j = 0; j < num_blocks_y; j++) {
113 for (i = 0; i < num_blocks_x; i++) {
114 x00 = xbuff[j * width + i];
115 x01 = xbuff[j * width + (i + 1)];
116 x10 = xbuff[(j + 1) * width + i];
117 x11 = xbuff[(j + 1) * width + (i + 1)];
118
119 y00 = ybuff[j * width + i];
120 y01 = ybuff[j * width + (i + 1)];
121 y10 = ybuff[(j + 1) * width + i];
122 y11 = ybuff[(j + 1) * width + (i + 1)];
123
124 xmin = min(x00, x10);
125 xmax = max(x01, x11);
126 ymin = min(y00, y01);
127 ymax = max(y10, y11);
128
129 /* Assert that right column's X is greater */
130 assert(x01 >= xmin);
131 assert(x11 >= xmin);
132 /* Assert that bottom row's Y is greater */
133 assert(y10 >= ymin);
134 assert(y11 >= ymin);
135
136 topleft_y = ymin >> DVS_COORD_FRAC_BITS;
137 topleft_x = ((xmin >> DVS_COORD_FRAC_BITS)
138 >> XMEM_ALIGN_LOG2)
139 << (XMEM_ALIGN_LOG2);
140 s.in_addr_offset = topleft_y * in_stride + topleft_x;
141
142 /* similar to topleft_y calculation, but round up if ymax
143 * has any fraction bits */
144 bottom_y = CEIL_DIV(ymax, 1 << DVS_COORD_FRAC_BITS);
145 s.in_block_height = bottom_y - topleft_y + dvs_interp_envelope;
146
147 bottom_x = CEIL_DIV(xmax, 1 << DVS_COORD_FRAC_BITS);
148 s.in_block_width = bottom_x - topleft_x + dvs_interp_envelope;
149
150 topleft_x_frac = topleft_x << (DVS_COORD_FRAC_BITS);
151 topleft_y_frac = topleft_y << (DVS_COORD_FRAC_BITS);
152
153 s.p0_x = x00 - topleft_x_frac;
154 s.p1_x = x01 - topleft_x_frac;
155 s.p2_x = x10 - topleft_x_frac;
156 s.p3_x = x11 - topleft_x_frac;
157
158 s.p0_y = y00 - topleft_y_frac;
159 s.p1_y = y01 - topleft_y_frac;
160 s.p2_y = y10 - topleft_y_frac;
161 s.p3_y = y11 - topleft_y_frac;
162
163 // block should fit within the boundingbox.
164 assert(s.p0_x < (s.in_block_width << DVS_COORD_FRAC_BITS));
165 assert(s.p1_x < (s.in_block_width << DVS_COORD_FRAC_BITS));
166 assert(s.p2_x < (s.in_block_width << DVS_COORD_FRAC_BITS));
167 assert(s.p3_x < (s.in_block_width << DVS_COORD_FRAC_BITS));
168 assert(s.p0_y < (s.in_block_height << DVS_COORD_FRAC_BITS));
169 assert(s.p1_y < (s.in_block_height << DVS_COORD_FRAC_BITS));
170 assert(s.p2_y < (s.in_block_height << DVS_COORD_FRAC_BITS));
171 assert(s.p3_y < (s.in_block_height << DVS_COORD_FRAC_BITS));
172
173 // block size should be greater than zero.
174 assert(s.p0_x < s.p1_x);
175 assert(s.p2_x < s.p3_x);
176 assert(s.p0_y < s.p2_y);
177 assert(s.p1_y < s.p3_y);
178
179 #if 0
180 printf("j: %d\ti:%d\n", j, i);
181 printf("offset: %d\n", s.in_addr_offset);
182 printf("p0_x: %d\n", s.p0_x);
183 printf("p0_y: %d\n", s.p0_y);
184 printf("p1_x: %d\n", s.p1_x);
185 printf("p1_y: %d\n", s.p1_y);
186 printf("p2_x: %d\n", s.p2_x);
187 printf("p2_y: %d\n", s.p2_y);
188 printf("p3_x: %d\n", s.p3_x);
189 printf("p3_y: %d\n", s.p3_y);
190
191 printf("p0_x_nofrac[0]: %d\n", s.p0_x >> DVS_COORD_FRAC_BITS);
192 printf("p0_y_nofrac[1]: %d\n", s.p0_y >> DVS_COORD_FRAC_BITS);
193 printf("p1_x_nofrac[2]: %d\n", s.p1_x >> DVS_COORD_FRAC_BITS);
194 printf("p1_y_nofrac[3]: %d\n", s.p1_y >> DVS_COORD_FRAC_BITS);
195 printf("p2_x_nofrac[0]: %d\n", s.p2_x >> DVS_COORD_FRAC_BITS);
196 printf("p2_y_nofrac[1]: %d\n", s.p2_y >> DVS_COORD_FRAC_BITS);
197 printf("p3_x_nofrac[2]: %d\n", s.p3_x >> DVS_COORD_FRAC_BITS);
198 printf("p3_y_nofrac[3]: %d\n", s.p3_y >> DVS_COORD_FRAC_BITS);
199 printf("\n");
200 #endif
201
202 *ptr = s;
203
204 // storage format:
205 // Y0 Y1 UV0 Y2 Y3 UV1
206 /* if uv_flag equals true increment with 2 incase x is odd, this to
207 skip the uv position. */
208 if (uv_flag)
209 ptr += 3;
210 else
211 ptr += (1 + (i & 1));
212 }
213 }
214 }
215
216 struct ia_css_host_data *
convert_allocate_dvs_6axis_config(const struct ia_css_dvs_6axis_config * dvs_6axis_config,const struct ia_css_binary * binary,const struct ia_css_frame_info * dvs_in_frame_info)217 convert_allocate_dvs_6axis_config(
218 const struct ia_css_dvs_6axis_config *dvs_6axis_config,
219 const struct ia_css_binary *binary,
220 const struct ia_css_frame_info *dvs_in_frame_info)
221 {
222 unsigned int i_stride;
223 unsigned int o_width;
224 unsigned int o_height;
225 struct ia_css_host_data *me;
226
227 assert(binary);
228 assert(dvs_6axis_config);
229 assert(dvs_in_frame_info);
230
231 me = ia_css_host_data_allocate((size_t)((DVS_6AXIS_BYTES(binary) / 2) * 3));
232
233 if (!me)
234 return NULL;
235
236 /*DVS only supports input frame of YUV420 or NV12. Fail for all other cases*/
237 assert((dvs_in_frame_info->format == IA_CSS_FRAME_FORMAT_NV12)
238 || (dvs_in_frame_info->format == IA_CSS_FRAME_FORMAT_YUV420));
239
240 i_stride = dvs_in_frame_info->padded_width;
241
242 o_width = binary->out_frame_info[0].res.width;
243 o_height = binary->out_frame_info[0].res.height;
244
245 /* Y plane */
246 convert_coords_to_ispparams(me, dvs_6axis_config,
247 i_stride, o_width, o_height, 0);
248
249 if (dvs_in_frame_info->format == IA_CSS_FRAME_FORMAT_YUV420) {
250 /*YUV420 has half the stride for U/V plane*/
251 i_stride /= 2;
252 }
253
254 /* UV plane (packed inside the y plane) */
255 convert_coords_to_ispparams(me, dvs_6axis_config,
256 i_stride, o_width / 2, o_height / 2, 1);
257
258 return me;
259 }
260
261 int
store_dvs_6axis_config(const struct ia_css_dvs_6axis_config * dvs_6axis_config,const struct ia_css_binary * binary,const struct ia_css_frame_info * dvs_in_frame_info,ia_css_ptr ddr_addr_y)262 store_dvs_6axis_config(
263 const struct ia_css_dvs_6axis_config *dvs_6axis_config,
264 const struct ia_css_binary *binary,
265 const struct ia_css_frame_info *dvs_in_frame_info,
266 ia_css_ptr ddr_addr_y) {
267 struct ia_css_host_data *me;
268
269 assert(dvs_6axis_config);
270 assert(ddr_addr_y != mmgr_NULL);
271 assert(dvs_in_frame_info);
272
273 me = convert_allocate_dvs_6axis_config(dvs_6axis_config,
274 binary,
275 dvs_in_frame_info);
276
277 if (!me)
278 {
279 IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
280 return -ENOMEM;
281 }
282
283 ia_css_params_store_ia_css_host_data(
284 ddr_addr_y,
285 me);
286 ia_css_host_data_free(me);
287
288 return 0;
289 }
290