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