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