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 "hmm.h" 16 17 #include "assert_support.h" 18 #include "ia_css_debug.h" 19 #include "ia_css_sdis_types.h" 20 #include "sdis/common/ia_css_sdis_common.host.h" 21 #include "ia_css_sdis.host.h" 22 23 const struct ia_css_dvs_coefficients default_sdis_config = { 24 .grid = { 0, 0, 0, 0, 0, 0, 0, 0 }, 25 .hor_coefs = NULL, 26 .ver_coefs = NULL 27 }; 28 29 static void 30 fill_row(short *private, const short *public, unsigned int width, 31 unsigned int padding) 32 { 33 assert((int)width >= 0); 34 assert((int)padding >= 0); 35 memcpy(private, public, width * sizeof(short)); 36 memset(&private[width], 0, padding * sizeof(short)); 37 } 38 39 void ia_css_sdis_horicoef_vmem_encode( 40 struct sh_css_isp_sdis_hori_coef_tbl *to, 41 const struct ia_css_dvs_coefficients *from, 42 unsigned int size) 43 { 44 unsigned int aligned_width = from->grid.aligned_width * 45 from->grid.bqs_per_grid_cell; 46 unsigned int width = from->grid.num_hor_coefs; 47 int padding = aligned_width - width; 48 unsigned int stride = size / IA_CSS_DVS_NUM_COEF_TYPES / sizeof(short); 49 unsigned int total_bytes = aligned_width * IA_CSS_DVS_NUM_COEF_TYPES * sizeof( 50 short); 51 short *public = from->hor_coefs; 52 short *private = (short *)to; 53 unsigned int type; 54 55 /* Copy the table, add padding */ 56 assert(padding >= 0); 57 assert(total_bytes <= size); 58 assert(size % (IA_CSS_DVS_NUM_COEF_TYPES * ISP_VEC_NELEMS * sizeof( 59 short)) == 0); 60 61 for (type = 0; type < IA_CSS_DVS_NUM_COEF_TYPES; type++) { 62 fill_row(&private[type * stride], &public[type * width], width, padding); 63 } 64 } 65 66 void ia_css_sdis_vertcoef_vmem_encode( 67 struct sh_css_isp_sdis_vert_coef_tbl *to, 68 const struct ia_css_dvs_coefficients *from, 69 unsigned int size) 70 { 71 unsigned int aligned_height = from->grid.aligned_height * 72 from->grid.bqs_per_grid_cell; 73 unsigned int height = from->grid.num_ver_coefs; 74 int padding = aligned_height - height; 75 unsigned int stride = size / IA_CSS_DVS_NUM_COEF_TYPES / sizeof(short); 76 unsigned int total_bytes = aligned_height * IA_CSS_DVS_NUM_COEF_TYPES * 77 sizeof(short); 78 short *public = from->ver_coefs; 79 short *private = (short *)to; 80 unsigned int type; 81 82 /* Copy the table, add padding */ 83 assert(padding >= 0); 84 assert(total_bytes <= size); 85 assert(size % (IA_CSS_DVS_NUM_COEF_TYPES * ISP_VEC_NELEMS * sizeof( 86 short)) == 0); 87 88 for (type = 0; type < IA_CSS_DVS_NUM_COEF_TYPES; type++) { 89 fill_row(&private[type * stride], &public[type * height], height, padding); 90 } 91 } 92 93 void ia_css_sdis_horiproj_encode( 94 struct sh_css_isp_sdis_hori_proj_tbl *to, 95 const struct ia_css_dvs_coefficients *from, 96 unsigned int size) 97 { 98 (void)to; 99 (void)from; 100 (void)size; 101 } 102 103 void ia_css_sdis_vertproj_encode( 104 struct sh_css_isp_sdis_vert_proj_tbl *to, 105 const struct ia_css_dvs_coefficients *from, 106 unsigned int size) 107 { 108 (void)to; 109 (void)from; 110 (void)size; 111 } 112 113 void ia_css_get_isp_dis_coefficients( 114 struct ia_css_stream *stream, 115 short *horizontal_coefficients, 116 short *vertical_coefficients) 117 { 118 struct ia_css_isp_parameters *params; 119 unsigned int hor_num_isp, ver_num_isp; 120 unsigned int hor_num_3a, ver_num_3a; 121 int i; 122 struct ia_css_binary *dvs_binary; 123 124 IA_CSS_ENTER("void"); 125 126 assert(horizontal_coefficients); 127 assert(vertical_coefficients); 128 129 params = stream->isp_params_configs; 130 131 /* Only video pipe supports DVS */ 132 dvs_binary = ia_css_stream_get_dvs_binary(stream); 133 if (!dvs_binary) 134 return; 135 136 hor_num_isp = dvs_binary->dis.coef.pad.width; 137 ver_num_isp = dvs_binary->dis.coef.pad.height; 138 hor_num_3a = dvs_binary->dis.coef.dim.width; 139 ver_num_3a = dvs_binary->dis.coef.dim.height; 140 141 for (i = 0; i < IA_CSS_DVS_NUM_COEF_TYPES; i++) { 142 fill_row(&horizontal_coefficients[i * hor_num_isp], 143 ¶ms->dvs_coefs.hor_coefs[i * hor_num_3a], hor_num_3a, 144 hor_num_isp - hor_num_3a); 145 } 146 for (i = 0; i < SH_CSS_DIS_VER_NUM_COEF_TYPES(dvs_binary); i++) { 147 fill_row(&vertical_coefficients[i * ver_num_isp], 148 ¶ms->dvs_coefs.ver_coefs[i * ver_num_3a], ver_num_3a, 149 ver_num_isp - ver_num_3a); 150 } 151 152 IA_CSS_LEAVE("void"); 153 } 154 155 size_t 156 ia_css_sdis_hor_coef_tbl_bytes( 157 const struct ia_css_binary *binary) 158 { 159 if (binary->info->sp.pipeline.isp_pipe_version == 1) 160 return sizeof(short) * IA_CSS_DVS_NUM_COEF_TYPES * binary->dis.coef.pad.width; 161 else 162 return sizeof(short) * IA_CSS_DVS2_NUM_COEF_TYPES * binary->dis.coef.pad.width; 163 } 164 165 size_t 166 ia_css_sdis_ver_coef_tbl_bytes( 167 const struct ia_css_binary *binary) 168 { 169 return sizeof(short) * SH_CSS_DIS_VER_NUM_COEF_TYPES(binary) * 170 binary->dis.coef.pad.height; 171 } 172 173 void 174 ia_css_sdis_init_info( 175 struct ia_css_sdis_info *dis, 176 unsigned int sc_3a_dis_width, 177 unsigned int sc_3a_dis_padded_width, 178 unsigned int sc_3a_dis_height, 179 unsigned int isp_pipe_version, 180 unsigned int enabled) 181 { 182 if (!enabled) { 183 *dis = (struct ia_css_sdis_info) { }; 184 return; 185 } 186 187 dis->deci_factor_log2 = SH_CSS_DIS_DECI_FACTOR_LOG2; 188 189 dis->grid.dim.width = 190 _ISP_BQS(sc_3a_dis_width) >> SH_CSS_DIS_DECI_FACTOR_LOG2; 191 dis->grid.dim.height = 192 _ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2; 193 dis->grid.pad.width = 194 CEIL_SHIFT(_ISP_BQS(sc_3a_dis_padded_width), SH_CSS_DIS_DECI_FACTOR_LOG2); 195 dis->grid.pad.height = 196 CEIL_SHIFT(_ISP_BQS(sc_3a_dis_height), SH_CSS_DIS_DECI_FACTOR_LOG2); 197 198 dis->coef.dim.width = 199 (_ISP_BQS(sc_3a_dis_width) >> SH_CSS_DIS_DECI_FACTOR_LOG2) << 200 SH_CSS_DIS_DECI_FACTOR_LOG2; 201 dis->coef.dim.height = 202 (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2) << 203 SH_CSS_DIS_DECI_FACTOR_LOG2; 204 dis->coef.pad.width = 205 __ISP_SDIS_HOR_COEF_NUM_VECS(sc_3a_dis_padded_width) * ISP_VEC_NELEMS; 206 dis->coef.pad.height = 207 __ISP_SDIS_VER_COEF_NUM_VECS(sc_3a_dis_height) * ISP_VEC_NELEMS; 208 if (isp_pipe_version == 1) { 209 dis->proj.dim.width = 210 _ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2; 211 dis->proj.dim.height = 212 _ISP_BQS(sc_3a_dis_width) >> SH_CSS_DIS_DECI_FACTOR_LOG2; 213 } else { 214 dis->proj.dim.width = 215 (_ISP_BQS(sc_3a_dis_width) >> SH_CSS_DIS_DECI_FACTOR_LOG2) * 216 (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2); 217 dis->proj.dim.height = 218 (_ISP_BQS(sc_3a_dis_width) >> SH_CSS_DIS_DECI_FACTOR_LOG2) * 219 (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2); 220 } 221 dis->proj.pad.width = 222 __ISP_SDIS_HOR_PROJ_NUM_ISP(sc_3a_dis_padded_width, 223 sc_3a_dis_height, 224 SH_CSS_DIS_DECI_FACTOR_LOG2, 225 isp_pipe_version); 226 dis->proj.pad.height = 227 __ISP_SDIS_VER_PROJ_NUM_ISP(sc_3a_dis_padded_width, 228 SH_CSS_DIS_DECI_FACTOR_LOG2); 229 } 230 231 void ia_css_sdis_clear_coefficients( 232 struct ia_css_dvs_coefficients *dvs_coefs) 233 { 234 dvs_coefs->hor_coefs = NULL; 235 dvs_coefs->ver_coefs = NULL; 236 } 237 238 enum ia_css_err 239 ia_css_get_dvs_statistics( 240 struct ia_css_dvs_statistics *host_stats, 241 const struct ia_css_isp_dvs_statistics *isp_stats) { 242 struct ia_css_isp_dvs_statistics_map *map; 243 enum ia_css_err ret = IA_CSS_SUCCESS; 244 245 IA_CSS_ENTER("host_stats=%p, isp_stats=%p", host_stats, isp_stats); 246 247 assert(host_stats); 248 assert(isp_stats); 249 250 map = ia_css_isp_dvs_statistics_map_allocate(isp_stats, NULL); 251 if (map) 252 { 253 hmm_load(isp_stats->data_ptr, map->data_ptr, isp_stats->size); 254 ia_css_translate_dvs_statistics(host_stats, map); 255 ia_css_isp_dvs_statistics_map_free(map); 256 } else 257 { 258 IA_CSS_ERROR("out of memory"); 259 ret = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 260 } 261 262 IA_CSS_LEAVE_ERR(ret); 263 return ret; 264 } 265 266 void 267 ia_css_translate_dvs_statistics( 268 struct ia_css_dvs_statistics *host_stats, 269 const struct ia_css_isp_dvs_statistics_map *isp_stats) 270 { 271 unsigned int hor_num_isp, ver_num_isp, hor_num_dvs, ver_num_dvs, i; 272 s32 *hor_ptr_dvs, *ver_ptr_dvs, *hor_ptr_isp, *ver_ptr_isp; 273 274 assert(host_stats); 275 assert(host_stats->hor_proj); 276 assert(host_stats->ver_proj); 277 assert(isp_stats); 278 assert(isp_stats->hor_proj); 279 assert(isp_stats->ver_proj); 280 281 IA_CSS_ENTER("hproj=%p, vproj=%p, haddr=%p, vaddr=%p", 282 host_stats->hor_proj, host_stats->ver_proj, 283 isp_stats->hor_proj, isp_stats->ver_proj); 284 285 hor_num_isp = host_stats->grid.aligned_height; 286 ver_num_isp = host_stats->grid.aligned_width; 287 hor_ptr_isp = isp_stats->hor_proj; 288 ver_ptr_isp = isp_stats->ver_proj; 289 hor_num_dvs = host_stats->grid.height; 290 ver_num_dvs = host_stats->grid.width; 291 hor_ptr_dvs = host_stats->hor_proj; 292 ver_ptr_dvs = host_stats->ver_proj; 293 294 for (i = 0; i < IA_CSS_DVS_NUM_COEF_TYPES; i++) { 295 memcpy(hor_ptr_dvs, hor_ptr_isp, hor_num_dvs * sizeof(int32_t)); 296 hor_ptr_isp += hor_num_isp; 297 hor_ptr_dvs += hor_num_dvs; 298 299 memcpy(ver_ptr_dvs, ver_ptr_isp, ver_num_dvs * sizeof(int32_t)); 300 ver_ptr_isp += ver_num_isp; 301 ver_ptr_dvs += ver_num_dvs; 302 } 303 304 IA_CSS_LEAVE("void"); 305 } 306 307 struct ia_css_isp_dvs_statistics * 308 ia_css_isp_dvs_statistics_allocate( 309 const struct ia_css_dvs_grid_info *grid) 310 { 311 struct ia_css_isp_dvs_statistics *me; 312 int hor_size, ver_size; 313 314 assert(grid); 315 316 IA_CSS_ENTER("grid=%p", grid); 317 318 if (!grid->enable) 319 return NULL; 320 321 me = kvcalloc(1, sizeof(*me), GFP_KERNEL); 322 if (!me) 323 goto err; 324 325 hor_size = CEIL_MUL(sizeof(int) * IA_CSS_DVS_NUM_COEF_TYPES * 326 grid->aligned_height, 327 HIVE_ISP_DDR_WORD_BYTES); 328 ver_size = CEIL_MUL(sizeof(int) * IA_CSS_DVS_NUM_COEF_TYPES * 329 grid->aligned_width, 330 HIVE_ISP_DDR_WORD_BYTES); 331 332 me->size = hor_size + ver_size; 333 me->data_ptr = hmm_alloc(me->size, HMM_BO_PRIVATE, 0, NULL, 0); 334 if (me->data_ptr == mmgr_NULL) 335 goto err; 336 me->hor_size = hor_size; 337 me->hor_proj = me->data_ptr; 338 me->ver_size = ver_size; 339 me->ver_proj = me->data_ptr + hor_size; 340 341 IA_CSS_LEAVE("return=%p", me); 342 343 return me; 344 err: 345 ia_css_isp_dvs_statistics_free(me); 346 347 IA_CSS_LEAVE("return=%p", NULL); 348 349 return NULL; 350 } 351 352 struct ia_css_isp_dvs_statistics_map * 353 ia_css_isp_dvs_statistics_map_allocate( 354 const struct ia_css_isp_dvs_statistics *isp_stats, 355 void *data_ptr) 356 { 357 struct ia_css_isp_dvs_statistics_map *me; 358 /* Windows compiler does not like adding sizes to a void * 359 * so we use a local char * instead. */ 360 char *base_ptr; 361 362 me = kvmalloc(sizeof(*me), GFP_KERNEL); 363 if (!me) { 364 IA_CSS_LOG("cannot allocate memory"); 365 goto err; 366 } 367 368 me->data_ptr = data_ptr; 369 me->data_allocated = !data_ptr; 370 371 if (!me->data_ptr) { 372 me->data_ptr = kvmalloc(isp_stats->size, GFP_KERNEL); 373 if (!me->data_ptr) { 374 IA_CSS_LOG("cannot allocate memory"); 375 goto err; 376 } 377 } 378 base_ptr = me->data_ptr; 379 380 me->size = isp_stats->size; 381 /* GCC complains when we assign a char * to a void *, so these 382 * casts are necessary unfortunately. */ 383 me->hor_proj = (void *)base_ptr; 384 me->ver_proj = (void *)(base_ptr + isp_stats->hor_size); 385 386 return me; 387 err: 388 if (me) 389 kvfree(me); 390 return NULL; 391 } 392 393 void 394 ia_css_isp_dvs_statistics_map_free(struct ia_css_isp_dvs_statistics_map *me) 395 { 396 if (me) { 397 if (me->data_allocated) 398 kvfree(me->data_ptr); 399 kvfree(me); 400 } 401 } 402 403 void 404 ia_css_isp_dvs_statistics_free(struct ia_css_isp_dvs_statistics *me) 405 { 406 if (me) { 407 hmm_free(me->data_ptr); 408 kvfree(me); 409 } 410 } 411 412 void ia_css_sdis_horicoef_debug_dtrace( 413 const struct ia_css_dvs_coefficients *config, unsigned int level) 414 { 415 (void)config; 416 (void)level; 417 } 418 419 void ia_css_sdis_vertcoef_debug_dtrace( 420 const struct ia_css_dvs_coefficients *config, unsigned int level) 421 { 422 (void)config; 423 (void)level; 424 } 425 426 void ia_css_sdis_horiproj_debug_dtrace( 427 const struct ia_css_dvs_coefficients *config, unsigned int level) 428 { 429 (void)config; 430 (void)level; 431 } 432 433 void ia_css_sdis_vertproj_debug_dtrace( 434 const struct ia_css_dvs_coefficients *config, unsigned int level) 435 { 436 (void)config; 437 (void)level; 438 } 439