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