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 <linux/math.h> 17 18 #include <math_support.h> 19 #include <gdc_device.h> /* HR_GDC_N */ 20 21 #include "hmm.h" 22 23 #include "isp.h" /* ISP_VEC_NELEMS */ 24 25 #include "ia_css_binary.h" 26 #include "ia_css_debug.h" 27 #include "ia_css_util.h" 28 #include "ia_css_isp_param.h" 29 #include "sh_css_internal.h" 30 #include "sh_css_sp.h" 31 #include "sh_css_firmware.h" 32 #include "sh_css_defs.h" 33 #include "sh_css_legacy.h" 34 35 #include "atomisp_internal.h" 36 37 #include "vf/vf_1.0/ia_css_vf.host.h" 38 #include "sc/sc_1.0/ia_css_sc.host.h" 39 #include "sdis/sdis_1.0/ia_css_sdis.host.h" 40 #include "fixedbds/fixedbds_1.0/ia_css_fixedbds_param.h" /* FRAC_ACC */ 41 42 #include "camera/pipe/interface/ia_css_pipe_binarydesc.h" 43 44 #include "assert_support.h" 45 46 #define IMPLIES(a, b) (!(a) || (b)) /* A => B */ 47 48 static struct ia_css_binary_xinfo *all_binaries; /* ISP binaries only (no SP) */ 49 static struct ia_css_binary_xinfo 50 *binary_infos[IA_CSS_BINARY_NUM_MODES] = { NULL, }; 51 52 static void 53 ia_css_binary_dvs_env(const struct ia_css_binary_info *info, 54 const struct ia_css_resolution *dvs_env, 55 struct ia_css_resolution *binary_dvs_env) 56 { 57 if (info->enable.dvs_envelope) { 58 assert(dvs_env); 59 binary_dvs_env->width = max(dvs_env->width, SH_CSS_MIN_DVS_ENVELOPE); 60 binary_dvs_env->height = max(dvs_env->height, SH_CSS_MIN_DVS_ENVELOPE); 61 } 62 } 63 64 static void 65 ia_css_binary_internal_res(const struct ia_css_frame_info *in_info, 66 const struct ia_css_frame_info *bds_out_info, 67 const struct ia_css_frame_info *out_info, 68 const struct ia_css_resolution *dvs_env, 69 const struct ia_css_binary_info *info, 70 struct ia_css_resolution *internal_res) 71 { 72 unsigned int isp_tmp_internal_width = 0, 73 isp_tmp_internal_height = 0; 74 bool binary_supports_yuv_ds = info->enable.ds & 2; 75 struct ia_css_resolution binary_dvs_env; 76 77 binary_dvs_env.width = 0; 78 binary_dvs_env.height = 0; 79 ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env); 80 81 if (binary_supports_yuv_ds) { 82 if (in_info) { 83 isp_tmp_internal_width = in_info->res.width 84 + info->pipeline.left_cropping + binary_dvs_env.width; 85 isp_tmp_internal_height = in_info->res.height 86 + info->pipeline.top_cropping + binary_dvs_env.height; 87 } 88 } else if ((bds_out_info) && (out_info) && 89 /* TODO: hack to make video_us case work. this should be reverted after 90 a nice solution in ISP */ 91 (bds_out_info->res.width >= out_info->res.width)) { 92 isp_tmp_internal_width = bds_out_info->padded_width; 93 isp_tmp_internal_height = bds_out_info->res.height; 94 } else { 95 if (out_info) { 96 isp_tmp_internal_width = out_info->padded_width; 97 isp_tmp_internal_height = out_info->res.height; 98 } 99 } 100 101 /* We first calculate the resolutions used by the ISP. After that, 102 * we use those resolutions to compute sizes for tables etc. */ 103 internal_res->width = __ISP_INTERNAL_WIDTH(isp_tmp_internal_width, 104 (int)binary_dvs_env.width, 105 info->pipeline.left_cropping, info->pipeline.mode, 106 info->pipeline.c_subsampling, 107 info->output.num_chunks, info->pipeline.pipelining); 108 internal_res->height = __ISP_INTERNAL_HEIGHT(isp_tmp_internal_height, 109 info->pipeline.top_cropping, 110 binary_dvs_env.height); 111 } 112 113 /* Computation results of the origin coordinate of bayer on the shading table. */ 114 struct sh_css_shading_table_bayer_origin_compute_results { 115 u32 bayer_scale_hor_ratio_in; /* Horizontal ratio (in) of bayer scaling. */ 116 u32 bayer_scale_hor_ratio_out; /* Horizontal ratio (out) of bayer scaling. */ 117 u32 bayer_scale_ver_ratio_in; /* Vertical ratio (in) of bayer scaling. */ 118 u32 bayer_scale_ver_ratio_out; /* Vertical ratio (out) of bayer scaling. */ 119 u32 sc_bayer_origin_x_bqs_on_shading_table; /* X coordinate (in bqs) of bayer origin on shading table. */ 120 u32 sc_bayer_origin_y_bqs_on_shading_table; /* Y coordinate (in bqs) of bayer origin on shading table. */ 121 }; 122 123 /* Get the requirements for the shading correction. */ 124 static int 125 ia_css_binary_compute_shading_table_bayer_origin( 126 const struct ia_css_binary *binary, /* [in] */ 127 unsigned int required_bds_factor, /* [in] */ 128 const struct ia_css_stream_config *stream_config, /* [in] */ 129 struct sh_css_shading_table_bayer_origin_compute_results *res) /* [out] */ 130 { 131 int err; 132 133 /* Rational fraction of the fixed bayer downscaling factor. */ 134 struct u32_fract bds; 135 136 /* Left padding set by InputFormatter. */ 137 unsigned int left_padding_bqs; /* in bqs */ 138 139 /* Flag for the NEED_BDS_FACTOR_2_00 macro defined in isp kernels. */ 140 unsigned int need_bds_factor_2_00; 141 142 /* Left padding adjusted inside the isp. */ 143 unsigned int left_padding_adjusted_bqs; /* in bqs */ 144 145 /* Bad pixels caused by filters. 146 NxN-filter (before/after bayer scaling) moves the image position 147 to right/bottom directions by a few pixels. 148 It causes bad pixels at left/top sides, 149 and effective bayer size decreases. */ 150 unsigned int bad_bqs_on_left_before_bs; /* in bqs */ 151 unsigned int bad_bqs_on_left_after_bs; /* in bqs */ 152 unsigned int bad_bqs_on_top_before_bs; /* in bqs */ 153 unsigned int bad_bqs_on_top_after_bs; /* in bqs */ 154 155 /* Get the rational fraction of bayer downscaling factor. */ 156 err = sh_css_bds_factor_get_fract(required_bds_factor, &bds); 157 if (err) 158 return err; 159 160 /* Set the left padding set by InputFormatter. (ifmtr.c) */ 161 if (stream_config->left_padding == -1) 162 left_padding_bqs = _ISP_BQS(binary->left_padding); 163 else 164 left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS 165 - _ISP_BQS(stream_config->left_padding)); 166 167 /* Set the left padding adjusted inside the isp. 168 When bds_factor 2.00 is needed, some padding is added to left_padding 169 inside the isp, before bayer downscaling. (raw.isp.c) 170 (Hopefully, left_crop/left_padding/top_crop should be defined in css 171 appropriately, depending on bds_factor.) 172 */ 173 need_bds_factor_2_00 = ((binary->info->sp.bds.supported_bds_factors & 174 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_00) | 175 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) | 176 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) | 177 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_00) | 178 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) | 179 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00) | 180 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00) | 181 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_8_00))) != 0); 182 183 if (need_bds_factor_2_00 && binary->info->sp.pipeline.left_cropping > 0) 184 left_padding_adjusted_bqs = left_padding_bqs + ISP_VEC_NELEMS; 185 else 186 left_padding_adjusted_bqs = left_padding_bqs; 187 188 /* Currently, the bad pixel caused by filters before bayer scaling 189 is NOT considered, because the bad pixel is subtle. 190 When some large filter is used in the future, 191 we need to consider the bad pixel. 192 193 Currently, when bds_factor isn't 1.00, 3x3 anti-alias filter is applied 194 to each color plane(Gr/R/B/Gb) before bayer downscaling. 195 This filter moves each color plane to right/bottom directions 196 by 1 pixel at the most, depending on downscaling factor. 197 */ 198 bad_bqs_on_left_before_bs = 0; 199 bad_bqs_on_top_before_bs = 0; 200 201 /* Currently, the bad pixel caused by filters after bayer scaling 202 is NOT considered, because the bad pixel is subtle. 203 When some large filter is used in the future, 204 we need to consider the bad pixel. 205 206 Currently, when DPC&BNR is processed between bayer scaling and 207 shading correction, DPC&BNR moves each color plane to 208 right/bottom directions by 1 pixel. 209 */ 210 bad_bqs_on_left_after_bs = 0; 211 bad_bqs_on_top_after_bs = 0; 212 213 /* Calculate the origin of bayer (real sensor data area) 214 located on the shading table during the shading correction. */ 215 res->sc_bayer_origin_x_bqs_on_shading_table = 216 ((left_padding_adjusted_bqs + bad_bqs_on_left_before_bs) 217 * bds.denominator + bds.numerator / 2) / bds.numerator 218 + bad_bqs_on_left_after_bs; 219 /* "+ bds.numerator / 2": rounding for division by bds.numerator */ 220 res->sc_bayer_origin_y_bqs_on_shading_table = 221 (bad_bqs_on_top_before_bs * bds.denominator + bds.numerator / 2) / bds.numerator 222 + bad_bqs_on_top_after_bs; 223 /* "+ bds.numerator / 2": rounding for division by bds.numerator */ 224 225 res->bayer_scale_hor_ratio_in = bds.numerator; 226 res->bayer_scale_hor_ratio_out = bds.denominator; 227 res->bayer_scale_ver_ratio_in = bds.numerator; 228 res->bayer_scale_ver_ratio_out = bds.denominator; 229 230 return err; 231 } 232 233 /* Get the shading information of Shading Correction Type 1. */ 234 static int 235 binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [in] */ 236 unsigned int required_bds_factor, /* [in] */ 237 const struct ia_css_stream_config *stream_config, /* [in] */ 238 struct ia_css_shading_info *info) /* [out] */ 239 { 240 int err; 241 struct sh_css_shading_table_bayer_origin_compute_results res; 242 243 assert(binary); 244 assert(info); 245 246 info->type = IA_CSS_SHADING_CORRECTION_TYPE_1; 247 248 info->info.type_1.enable = binary->info->sp.enable.sc; 249 info->info.type_1.num_hor_grids = binary->sctbl_width_per_color; 250 info->info.type_1.num_ver_grids = binary->sctbl_height; 251 info->info.type_1.bqs_per_grid_cell = (1 << binary->deci_factor_log2); 252 253 /* Initialize by default values. */ 254 info->info.type_1.bayer_scale_hor_ratio_in = 1; 255 info->info.type_1.bayer_scale_hor_ratio_out = 1; 256 info->info.type_1.bayer_scale_ver_ratio_in = 1; 257 info->info.type_1.bayer_scale_ver_ratio_out = 1; 258 info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = 0; 259 info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = 0; 260 261 err = ia_css_binary_compute_shading_table_bayer_origin( 262 binary, 263 required_bds_factor, 264 stream_config, 265 &res); 266 if (err) 267 return err; 268 269 info->info.type_1.bayer_scale_hor_ratio_in = res.bayer_scale_hor_ratio_in; 270 info->info.type_1.bayer_scale_hor_ratio_out = res.bayer_scale_hor_ratio_out; 271 info->info.type_1.bayer_scale_ver_ratio_in = res.bayer_scale_ver_ratio_in; 272 info->info.type_1.bayer_scale_ver_ratio_out = res.bayer_scale_ver_ratio_out; 273 info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = res.sc_bayer_origin_x_bqs_on_shading_table; 274 info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = res.sc_bayer_origin_y_bqs_on_shading_table; 275 276 return err; 277 } 278 279 280 int 281 ia_css_binary_get_shading_info(const struct ia_css_binary *binary, /* [in] */ 282 enum ia_css_shading_correction_type type, /* [in] */ 283 unsigned int required_bds_factor, /* [in] */ 284 const struct ia_css_stream_config *stream_config, /* [in] */ 285 struct ia_css_shading_info *shading_info, /* [out] */ 286 struct ia_css_pipe_config *pipe_config) /* [out] */ 287 { 288 int err; 289 290 assert(binary); 291 assert(shading_info); 292 293 IA_CSS_ENTER_PRIVATE("binary=%p, type=%d, required_bds_factor=%d, stream_config=%p", 294 binary, type, required_bds_factor, stream_config); 295 296 if (type == IA_CSS_SHADING_CORRECTION_TYPE_1) 297 err = binary_get_shading_info_type_1(binary, 298 required_bds_factor, 299 stream_config, 300 shading_info); 301 else 302 err = -ENOTSUPP; 303 304 IA_CSS_LEAVE_ERR_PRIVATE(err); 305 return err; 306 } 307 308 static void sh_css_binary_common_grid_info(const struct ia_css_binary *binary, 309 struct ia_css_grid_info *info) 310 { 311 assert(binary); 312 assert(info); 313 314 info->isp_in_width = binary->internal_frame_info.res.width; 315 info->isp_in_height = binary->internal_frame_info.res.height; 316 317 info->vamem_type = IA_CSS_VAMEM_TYPE_2; 318 } 319 320 void 321 ia_css_binary_dvs_grid_info(const struct ia_css_binary *binary, 322 struct ia_css_grid_info *info, 323 struct ia_css_pipe *pipe) 324 { 325 struct ia_css_dvs_grid_info *dvs_info; 326 327 (void)pipe; 328 assert(binary); 329 assert(info); 330 331 dvs_info = &info->dvs_grid.dvs_grid_info; 332 333 /* for DIS, we use a division instead of a ceil_div. If this is smaller 334 * than the 3a grid size, it indicates that the outer values are not 335 * valid for DIS. 336 */ 337 dvs_info->enable = binary->info->sp.enable.dis; 338 dvs_info->width = binary->dis.grid.dim.width; 339 dvs_info->height = binary->dis.grid.dim.height; 340 dvs_info->aligned_width = binary->dis.grid.pad.width; 341 dvs_info->aligned_height = binary->dis.grid.pad.height; 342 dvs_info->bqs_per_grid_cell = 1 << binary->dis.deci_factor_log2; 343 dvs_info->num_hor_coefs = binary->dis.coef.dim.width; 344 dvs_info->num_ver_coefs = binary->dis.coef.dim.height; 345 346 sh_css_binary_common_grid_info(binary, info); 347 } 348 349 void 350 ia_css_binary_dvs_stat_grid_info( 351 const struct ia_css_binary *binary, 352 struct ia_css_grid_info *info, 353 struct ia_css_pipe *pipe) 354 { 355 (void)pipe; 356 sh_css_binary_common_grid_info(binary, info); 357 return; 358 } 359 360 int 361 ia_css_binary_3a_grid_info(const struct ia_css_binary *binary, 362 struct ia_css_grid_info *info, 363 struct ia_css_pipe *pipe) { 364 struct ia_css_3a_grid_info *s3a_info; 365 int err = 0; 366 367 IA_CSS_ENTER_PRIVATE("binary=%p, info=%p, pipe=%p", 368 binary, info, pipe); 369 370 assert(binary); 371 assert(info); 372 s3a_info = &info->s3a_grid; 373 374 /* 3A statistics grid */ 375 s3a_info->enable = binary->info->sp.enable.s3a; 376 s3a_info->width = binary->s3atbl_width; 377 s3a_info->height = binary->s3atbl_height; 378 s3a_info->aligned_width = binary->s3atbl_isp_width; 379 s3a_info->aligned_height = binary->s3atbl_isp_height; 380 s3a_info->bqs_per_grid_cell = (1 << binary->deci_factor_log2); 381 s3a_info->deci_factor_log2 = binary->deci_factor_log2; 382 s3a_info->elem_bit_depth = SH_CSS_BAYER_BITS; 383 s3a_info->use_dmem = binary->info->sp.s3a.s3atbl_use_dmem; 384 s3a_info->has_histogram = 0; 385 IA_CSS_LEAVE_ERR_PRIVATE(err); 386 return err; 387 } 388 389 static void 390 binary_init_pc_histogram(struct sh_css_pc_histogram *histo) 391 { 392 assert(histo); 393 394 histo->length = 0; 395 histo->run = NULL; 396 histo->stall = NULL; 397 } 398 399 static void 400 binary_init_metrics(struct sh_css_binary_metrics *metrics, 401 const struct ia_css_binary_info *info) 402 { 403 assert(metrics); 404 assert(info); 405 406 metrics->mode = info->pipeline.mode; 407 metrics->id = info->id; 408 metrics->next = NULL; 409 binary_init_pc_histogram(&metrics->isp_histogram); 410 binary_init_pc_histogram(&metrics->sp_histogram); 411 } 412 413 /* move to host part of output module */ 414 static bool 415 binary_supports_output_format(const struct ia_css_binary_xinfo *info, 416 enum ia_css_frame_format format) 417 { 418 int i; 419 420 assert(info); 421 422 for (i = 0; i < info->num_output_formats; i++) { 423 if (info->output_formats[i] == format) 424 return true; 425 } 426 return false; 427 } 428 429 static bool 430 binary_supports_vf_format(const struct ia_css_binary_xinfo *info, 431 enum ia_css_frame_format format) 432 { 433 int i; 434 435 assert(info); 436 437 for (i = 0; i < info->num_vf_formats; i++) { 438 if (info->vf_formats[i] == format) 439 return true; 440 } 441 return false; 442 } 443 444 /* move to host part of bds module */ 445 static bool 446 supports_bds_factor(u32 supported_factors, 447 uint32_t bds_factor) 448 { 449 return ((supported_factors & PACK_BDS_FACTOR(bds_factor)) != 0); 450 } 451 452 static int 453 binary_init_info(struct ia_css_binary_xinfo *info, unsigned int i, 454 bool *binary_found) { 455 const unsigned char *blob = sh_css_blob_info[i].blob; 456 unsigned int size = sh_css_blob_info[i].header.blob.size; 457 458 if ((!info) || (!binary_found)) 459 return -EINVAL; 460 461 *info = sh_css_blob_info[i].header.info.isp; 462 *binary_found = blob; 463 info->blob_index = i; 464 /* we don't have this binary, skip it */ 465 if (!size) 466 return 0; 467 468 info->xmem_addr = sh_css_load_blob(blob, size); 469 if (!info->xmem_addr) 470 return -ENOMEM; 471 return 0; 472 } 473 474 /* When binaries are put at the beginning, they will only 475 * be selected if no other primary matches. 476 */ 477 int 478 ia_css_binary_init_infos(void) { 479 unsigned int i; 480 unsigned int num_of_isp_binaries = sh_css_num_binaries - NUM_OF_SPS - NUM_OF_BLS; 481 482 if (num_of_isp_binaries == 0) 483 return 0; 484 485 all_binaries = kvmalloc(num_of_isp_binaries * sizeof(*all_binaries), 486 GFP_KERNEL); 487 if (!all_binaries) 488 return -ENOMEM; 489 490 for (i = 0; i < num_of_isp_binaries; i++) 491 { 492 int ret; 493 struct ia_css_binary_xinfo *binary = &all_binaries[i]; 494 bool binary_found; 495 496 ret = binary_init_info(binary, i, &binary_found); 497 if (ret) 498 return ret; 499 if (!binary_found) 500 continue; 501 /* Prepend new binary information */ 502 binary->next = binary_infos[binary->sp.pipeline.mode]; 503 binary_infos[binary->sp.pipeline.mode] = binary; 504 binary->blob = &sh_css_blob_info[i]; 505 binary->mem_offsets = sh_css_blob_info[i].mem_offsets; 506 } 507 return 0; 508 } 509 510 int 511 ia_css_binary_uninit(void) { 512 unsigned int i; 513 struct ia_css_binary_xinfo *b; 514 515 for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++) 516 { 517 for (b = binary_infos[i]; b; b = b->next) { 518 if (b->xmem_addr) 519 hmm_free(b->xmem_addr); 520 b->xmem_addr = mmgr_NULL; 521 } 522 binary_infos[i] = NULL; 523 } 524 kvfree(all_binaries); 525 return 0; 526 } 527 528 /* @brief Compute decimation factor for 3A statistics and shading correction. 529 * 530 * @param[in] width Frame width in pixels. 531 * @param[in] height Frame height in pixels. 532 * @return Log2 of decimation factor (= grid cell size) in bayer quads. 533 */ 534 static int 535 binary_grid_deci_factor_log2(int width, int height) 536 { 537 /* 3A/Shading decimation factor spcification (at August 2008) 538 * ------------------------------------------------------------------ 539 * [Image Width (BQ)] [Decimation Factor (BQ)] [Resulting grid cells] 540 * 1280 ?c 32 40 ?c 541 * 640 ?c 1279 16 40 ?c 80 542 * ?c 639 8 ?c 80 543 * ------------------------------------------------------------------ 544 */ 545 /* Maximum and minimum decimation factor by the specification */ 546 #define MAX_SPEC_DECI_FACT_LOG2 5 547 #define MIN_SPEC_DECI_FACT_LOG2 3 548 /* the smallest frame width in bayer quads when decimation factor (log2) is 5 or 4, by the specification */ 549 #define DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ 1280 550 #define DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ 640 551 552 int smallest_factor; /* the smallest factor (log2) where the number of cells does not exceed the limitation */ 553 int spec_factor; /* the factor (log2) which satisfies the specification */ 554 555 /* Currently supported maximum width and height are 5120(=80*64) and 3840(=60*64). */ 556 assert(ISP_BQ_GRID_WIDTH(width, 557 MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_WIDTH); 558 assert(ISP_BQ_GRID_HEIGHT(height, 559 MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_HEIGHT); 560 561 /* Compute the smallest factor. */ 562 smallest_factor = MAX_SPEC_DECI_FACT_LOG2; 563 while (ISP_BQ_GRID_WIDTH(width, 564 smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_WIDTH && 565 ISP_BQ_GRID_HEIGHT(height, smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_HEIGHT 566 && smallest_factor > MIN_SPEC_DECI_FACT_LOG2) 567 smallest_factor--; 568 569 /* Get the factor by the specification. */ 570 if (_ISP_BQS(width) >= DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ) 571 spec_factor = 5; 572 else if (_ISP_BQS(width) >= DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ) 573 spec_factor = 4; 574 else 575 spec_factor = 3; 576 577 /* If smallest_factor is smaller than or equal to spec_factor, choose spec_factor to follow the specification. 578 If smallest_factor is larger than spec_factor, choose smallest_factor. 579 580 ex. width=2560, height=1920 581 smallest_factor=4, spec_factor=5 582 smallest_factor < spec_factor -> return spec_factor 583 584 ex. width=300, height=3000 585 smallest_factor=5, spec_factor=3 586 smallest_factor > spec_factor -> return smallest_factor 587 */ 588 return max(smallest_factor, spec_factor); 589 590 #undef MAX_SPEC_DECI_FACT_LOG2 591 #undef MIN_SPEC_DECI_FACT_LOG2 592 #undef DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ 593 #undef DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ 594 } 595 596 static int 597 binary_in_frame_padded_width(int in_frame_width, 598 int isp_internal_width, 599 int dvs_env_width, 600 int stream_config_left_padding, 601 int left_cropping, 602 bool need_scaling) 603 { 604 int rval; 605 int nr_of_left_paddings; /* number of paddings pixels on the left of an image line */ 606 607 if (IS_ISP2401) { 608 /* the output image line of Input System 2401 does not have the left paddings */ 609 nr_of_left_paddings = 0; 610 } else { 611 /* in other cases, the left padding pixels are always 128 */ 612 nr_of_left_paddings = 2 * ISP_VEC_NELEMS; 613 } 614 615 if (need_scaling) { 616 /* In SDV use-case, we need to match left-padding of 617 * primary and the video binary. */ 618 if (stream_config_left_padding != -1) { 619 /* Different than before, we do left&right padding. */ 620 rval = 621 CEIL_MUL(in_frame_width + nr_of_left_paddings, 622 2 * ISP_VEC_NELEMS); 623 } else { 624 /* Different than before, we do left&right padding. */ 625 in_frame_width += dvs_env_width; 626 rval = 627 CEIL_MUL(in_frame_width + 628 (left_cropping ? nr_of_left_paddings : 0), 629 2 * ISP_VEC_NELEMS); 630 } 631 } else { 632 rval = isp_internal_width; 633 } 634 635 return rval; 636 } 637 638 int 639 ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo, 640 bool online, 641 bool two_ppc, 642 enum atomisp_input_format stream_format, 643 const struct ia_css_frame_info *in_info, /* can be NULL */ 644 const struct ia_css_frame_info *bds_out_info, /* can be NULL */ 645 const struct ia_css_frame_info *out_info[], /* can be NULL */ 646 const struct ia_css_frame_info *vf_info, /* can be NULL */ 647 struct ia_css_binary *binary, 648 struct ia_css_resolution *dvs_env, 649 int stream_config_left_padding, 650 bool accelerator) { 651 const struct ia_css_binary_info *info = &xinfo->sp; 652 unsigned int dvs_env_width = 0, 653 dvs_env_height = 0, 654 vf_log_ds = 0, 655 s3a_log_deci = 0, 656 bits_per_pixel = 0, 657 /* Resolution at SC/3A/DIS kernel. */ 658 sc_3a_dis_width = 0, 659 /* Resolution at SC/3A/DIS kernel. */ 660 sc_3a_dis_padded_width = 0, 661 /* Resolution at SC/3A/DIS kernel. */ 662 sc_3a_dis_height = 0, 663 isp_internal_width = 0, 664 isp_internal_height = 0, 665 s3a_isp_width = 0; 666 667 bool need_scaling = false; 668 struct ia_css_resolution binary_dvs_env, internal_res; 669 int err; 670 unsigned int i; 671 const struct ia_css_frame_info *bin_out_info = NULL; 672 673 assert(info); 674 assert(binary); 675 676 binary->info = xinfo; 677 if (!accelerator) 678 { 679 /* binary->css_params has been filled by accelerator itself. */ 680 err = ia_css_isp_param_allocate_isp_parameters( 681 &binary->mem_params, &binary->css_params, 682 &info->mem_initializers); 683 if (err) { 684 return err; 685 } 686 } 687 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) 688 { 689 if (out_info[i] && (out_info[i]->res.width != 0)) { 690 bin_out_info = out_info[i]; 691 break; 692 } 693 } 694 if (in_info && bin_out_info) 695 { 696 need_scaling = (in_info->res.width != bin_out_info->res.width) || 697 (in_info->res.height != bin_out_info->res.height); 698 } 699 700 /* binary_dvs_env has to be equal or larger than SH_CSS_MIN_DVS_ENVELOPE */ 701 binary_dvs_env.width = 0; 702 binary_dvs_env.height = 0; 703 ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env); 704 dvs_env_width = binary_dvs_env.width; 705 dvs_env_height = binary_dvs_env.height; 706 binary->dvs_envelope.width = dvs_env_width; 707 binary->dvs_envelope.height = dvs_env_height; 708 709 /* internal resolution calculation */ 710 internal_res.width = 0; 711 internal_res.height = 0; 712 ia_css_binary_internal_res(in_info, bds_out_info, bin_out_info, dvs_env, 713 info, &internal_res); 714 isp_internal_width = internal_res.width; 715 isp_internal_height = internal_res.height; 716 717 /* internal frame info */ 718 if (bin_out_info) /* { */ 719 binary->internal_frame_info.format = bin_out_info->format; 720 /* } */ 721 binary->internal_frame_info.res.width = isp_internal_width; 722 binary->internal_frame_info.padded_width = CEIL_MUL(isp_internal_width, 2 * ISP_VEC_NELEMS); 723 binary->internal_frame_info.res.height = isp_internal_height; 724 binary->internal_frame_info.raw_bit_depth = bits_per_pixel; 725 726 if (in_info) 727 { 728 binary->effective_in_frame_res.width = in_info->res.width; 729 binary->effective_in_frame_res.height = in_info->res.height; 730 731 bits_per_pixel = in_info->raw_bit_depth; 732 733 /* input info */ 734 binary->in_frame_info.res.width = in_info->res.width + 735 info->pipeline.left_cropping; 736 binary->in_frame_info.res.height = in_info->res.height + 737 info->pipeline.top_cropping; 738 739 binary->in_frame_info.res.width += dvs_env_width; 740 binary->in_frame_info.res.height += dvs_env_height; 741 742 binary->in_frame_info.padded_width = 743 binary_in_frame_padded_width(in_info->res.width, 744 isp_internal_width, 745 dvs_env_width, 746 stream_config_left_padding, 747 info->pipeline.left_cropping, 748 need_scaling); 749 750 binary->in_frame_info.format = in_info->format; 751 binary->in_frame_info.raw_bayer_order = in_info->raw_bayer_order; 752 binary->in_frame_info.crop_info = in_info->crop_info; 753 } 754 755 if (online) 756 { 757 bits_per_pixel = ia_css_util_input_format_bpp( 758 stream_format, two_ppc); 759 } 760 binary->in_frame_info.raw_bit_depth = bits_per_pixel; 761 762 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) 763 { 764 if (out_info[i]) { 765 binary->out_frame_info[i].res.width = out_info[i]->res.width; 766 binary->out_frame_info[i].res.height = out_info[i]->res.height; 767 binary->out_frame_info[i].padded_width = out_info[i]->padded_width; 768 if (info->pipeline.mode == IA_CSS_BINARY_MODE_COPY) { 769 binary->out_frame_info[i].raw_bit_depth = bits_per_pixel; 770 } else { 771 /* Only relevant for RAW format. 772 * At the moment, all outputs are raw, 16 bit per pixel, except for copy. 773 * To do this cleanly, the binary should specify in its info 774 * the bit depth per output channel. 775 */ 776 binary->out_frame_info[i].raw_bit_depth = 16; 777 } 778 binary->out_frame_info[i].format = out_info[i]->format; 779 } 780 } 781 782 if (vf_info && (vf_info->res.width != 0)) 783 { 784 err = ia_css_vf_configure(binary, bin_out_info, 785 (struct ia_css_frame_info *)vf_info, &vf_log_ds); 786 if (err) { 787 if (!accelerator) { 788 ia_css_isp_param_destroy_isp_parameters( 789 &binary->mem_params, 790 &binary->css_params); 791 } 792 return err; 793 } 794 } 795 binary->vf_downscale_log2 = vf_log_ds; 796 797 binary->online = online; 798 binary->input_format = stream_format; 799 800 /* viewfinder output info */ 801 if ((vf_info) && (vf_info->res.width != 0)) 802 { 803 unsigned int vf_out_vecs, vf_out_width, vf_out_height; 804 805 binary->vf_frame_info.format = vf_info->format; 806 if (!bin_out_info) 807 return -EINVAL; 808 vf_out_vecs = __ISP_VF_OUTPUT_WIDTH_VECS(bin_out_info->padded_width, 809 vf_log_ds); 810 vf_out_width = _ISP_VF_OUTPUT_WIDTH(vf_out_vecs); 811 vf_out_height = _ISP_VF_OUTPUT_HEIGHT(bin_out_info->res.height, 812 vf_log_ds); 813 814 /* For preview mode, output pin is used instead of vf. */ 815 if (info->pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW) { 816 binary->out_frame_info[0].res.width = 817 (bin_out_info->res.width >> vf_log_ds); 818 binary->out_frame_info[0].padded_width = vf_out_width; 819 binary->out_frame_info[0].res.height = vf_out_height; 820 821 binary->vf_frame_info.res.width = 0; 822 binary->vf_frame_info.padded_width = 0; 823 binary->vf_frame_info.res.height = 0; 824 } else { 825 /* we also store the raw downscaled width. This is 826 * used for digital zoom in preview to zoom only on 827 * the width that we actually want to keep, not on 828 * the aligned width. */ 829 binary->vf_frame_info.res.width = 830 (bin_out_info->res.width >> vf_log_ds); 831 binary->vf_frame_info.padded_width = vf_out_width; 832 binary->vf_frame_info.res.height = vf_out_height; 833 } 834 } else 835 { 836 binary->vf_frame_info.res.width = 0; 837 binary->vf_frame_info.padded_width = 0; 838 binary->vf_frame_info.res.height = 0; 839 } 840 841 if (info->enable.ca_gdc) 842 { 843 binary->morph_tbl_width = 844 _ISP_MORPH_TABLE_WIDTH(isp_internal_width); 845 binary->morph_tbl_aligned_width = 846 _ISP_MORPH_TABLE_ALIGNED_WIDTH(isp_internal_width); 847 binary->morph_tbl_height = 848 _ISP_MORPH_TABLE_HEIGHT(isp_internal_height); 849 } else 850 { 851 binary->morph_tbl_width = 0; 852 binary->morph_tbl_aligned_width = 0; 853 binary->morph_tbl_height = 0; 854 } 855 856 sc_3a_dis_width = binary->in_frame_info.res.width; 857 sc_3a_dis_padded_width = binary->in_frame_info.padded_width; 858 sc_3a_dis_height = binary->in_frame_info.res.height; 859 if (bds_out_info && in_info && 860 bds_out_info->res.width != in_info->res.width) 861 { 862 /* TODO: Next, "internal_frame_info" should be derived from 863 * bds_out. So this part will change once it is in place! */ 864 sc_3a_dis_width = bds_out_info->res.width + info->pipeline.left_cropping; 865 sc_3a_dis_padded_width = isp_internal_width; 866 sc_3a_dis_height = isp_internal_height; 867 } 868 869 s3a_isp_width = _ISP_S3A_ELEMS_ISP_WIDTH(sc_3a_dis_padded_width, 870 info->pipeline.left_cropping); 871 if (info->s3a.fixed_s3a_deci_log) 872 { 873 s3a_log_deci = info->s3a.fixed_s3a_deci_log; 874 } else 875 { 876 s3a_log_deci = binary_grid_deci_factor_log2(s3a_isp_width, 877 sc_3a_dis_height); 878 } 879 binary->deci_factor_log2 = s3a_log_deci; 880 881 if (info->enable.s3a) 882 { 883 binary->s3atbl_width = 884 _ISP_S3ATBL_WIDTH(sc_3a_dis_width, 885 s3a_log_deci); 886 binary->s3atbl_height = 887 _ISP_S3ATBL_HEIGHT(sc_3a_dis_height, 888 s3a_log_deci); 889 binary->s3atbl_isp_width = 890 _ISP_S3ATBL_ISP_WIDTH(s3a_isp_width, 891 s3a_log_deci); 892 binary->s3atbl_isp_height = 893 _ISP_S3ATBL_ISP_HEIGHT(sc_3a_dis_height, 894 s3a_log_deci); 895 } else 896 { 897 binary->s3atbl_width = 0; 898 binary->s3atbl_height = 0; 899 binary->s3atbl_isp_width = 0; 900 binary->s3atbl_isp_height = 0; 901 } 902 903 if (info->enable.sc) 904 { 905 binary->sctbl_width_per_color = _ISP_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci); 906 binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; 907 binary->sctbl_height = _ISP_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci); 908 } else 909 { 910 binary->sctbl_width_per_color = 0; 911 binary->sctbl_aligned_width_per_color = 0; 912 binary->sctbl_height = 0; 913 } 914 ia_css_sdis_init_info(&binary->dis, 915 sc_3a_dis_width, 916 sc_3a_dis_padded_width, 917 sc_3a_dis_height, 918 info->pipeline.isp_pipe_version, 919 info->enable.dis); 920 if (info->pipeline.left_cropping) 921 binary->left_padding = 2 * ISP_VEC_NELEMS - info->pipeline.left_cropping; 922 else 923 binary->left_padding = 0; 924 925 return 0; 926 } 927 928 static int __ia_css_binary_find(struct ia_css_binary_descr *descr, 929 struct ia_css_binary *binary) { 930 int mode; 931 bool online; 932 bool two_ppc; 933 enum atomisp_input_format stream_format; 934 const struct ia_css_frame_info *req_in_info, 935 *req_bds_out_info, 936 *req_out_info[IA_CSS_BINARY_MAX_OUTPUT_PORTS], 937 *req_bin_out_info = NULL, 938 *req_vf_info; 939 940 struct ia_css_binary_xinfo *xcandidate; 941 bool need_ds, need_dz, need_dvs, need_xnr, need_dpc; 942 bool striped; 943 bool enable_yuv_ds; 944 bool enable_high_speed; 945 bool enable_dvs_6axis; 946 bool enable_reduced_pipe; 947 bool enable_capture_pp_bli; 948 int err = -EINVAL; 949 bool continuous; 950 unsigned int isp_pipe_version; 951 struct ia_css_resolution dvs_env, internal_res; 952 unsigned int i; 953 954 assert(descr); 955 /* MW: used after an error check, may accept NULL, but doubtfull */ 956 assert(binary); 957 958 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 959 "ia_css_binary_find() enter: descr=%p, (mode=%d), binary=%p\n", 960 descr, descr->mode, 961 binary); 962 963 mode = descr->mode; 964 online = descr->online; 965 two_ppc = descr->two_ppc; 966 stream_format = descr->stream_format; 967 req_in_info = descr->in_info; 968 req_bds_out_info = descr->bds_out_info; 969 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { 970 req_out_info[i] = descr->out_info[i]; 971 if (req_out_info[i] && (req_out_info[i]->res.width != 0)) 972 req_bin_out_info = req_out_info[i]; 973 } 974 if (!req_bin_out_info) 975 return -EINVAL; 976 req_vf_info = descr->vf_info; 977 978 need_xnr = descr->enable_xnr; 979 need_ds = descr->enable_fractional_ds; 980 need_dz = false; 981 need_dvs = false; 982 need_dpc = descr->enable_dpc; 983 984 enable_yuv_ds = descr->enable_yuv_ds; 985 enable_high_speed = descr->enable_high_speed; 986 enable_dvs_6axis = descr->enable_dvs_6axis; 987 enable_reduced_pipe = descr->enable_reduced_pipe; 988 enable_capture_pp_bli = descr->enable_capture_pp_bli; 989 continuous = descr->continuous; 990 striped = descr->striped; 991 isp_pipe_version = descr->isp_pipe_version; 992 993 dvs_env.width = 0; 994 dvs_env.height = 0; 995 internal_res.width = 0; 996 internal_res.height = 0; 997 998 if (mode == IA_CSS_BINARY_MODE_VIDEO) { 999 dvs_env = descr->dvs_env; 1000 need_dz = descr->enable_dz; 1001 /* Video is the only mode that has a nodz variant. */ 1002 need_dvs = dvs_env.width || dvs_env.height; 1003 } 1004 1005 /* print a map of the binary file */ 1006 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "BINARY INFO:\n"); 1007 for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++) { 1008 xcandidate = binary_infos[i]; 1009 if (xcandidate) { 1010 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%d:\n", i); 1011 while (xcandidate) { 1012 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, " Name:%s Type:%d Cont:%d\n", 1013 xcandidate->blob->name, xcandidate->type, 1014 xcandidate->sp.enable.continuous); 1015 xcandidate = xcandidate->next; 1016 } 1017 } 1018 } 1019 1020 /* printf("sh_css_binary_find: pipe version %d\n", isp_pipe_version); */ 1021 for (xcandidate = binary_infos[mode]; xcandidate; 1022 xcandidate = xcandidate->next) { 1023 struct ia_css_binary_info *candidate = &xcandidate->sp; 1024 /* printf("sh_css_binary_find: evaluating candidate: 1025 * %d\n",candidate->id); */ 1026 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1027 "ia_css_binary_find() candidate = %p, mode = %d ID = %d\n", 1028 candidate, candidate->pipeline.mode, candidate->id); 1029 1030 /* 1031 * MW: Only a limited set of jointly configured binaries can 1032 * be used in a continuous preview/video mode unless it is 1033 * the copy mode and runs on SP. 1034 */ 1035 if (!candidate->enable.continuous && 1036 continuous && (mode != IA_CSS_BINARY_MODE_COPY)) { 1037 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1038 "ia_css_binary_find() [%d] continue: !%d && %d && (%d != %d)\n", 1039 __LINE__, candidate->enable.continuous, 1040 continuous, mode, 1041 IA_CSS_BINARY_MODE_COPY); 1042 continue; 1043 } 1044 if (striped && candidate->iterator.num_stripes == 1) { 1045 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1046 "ia_css_binary_find() [%d] continue: binary is not striped\n", 1047 __LINE__); 1048 continue; 1049 } 1050 1051 if (candidate->pipeline.isp_pipe_version != isp_pipe_version && 1052 (mode != IA_CSS_BINARY_MODE_COPY) && 1053 (mode != IA_CSS_BINARY_MODE_CAPTURE_PP) && 1054 (mode != IA_CSS_BINARY_MODE_VF_PP)) { 1055 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1056 "ia_css_binary_find() [%d] continue: (%d != %d)\n", 1057 __LINE__, 1058 candidate->pipeline.isp_pipe_version, isp_pipe_version); 1059 continue; 1060 } 1061 if (!candidate->enable.reduced_pipe && enable_reduced_pipe) { 1062 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1063 "ia_css_binary_find() [%d] continue: !%d && %d\n", 1064 __LINE__, 1065 candidate->enable.reduced_pipe, 1066 enable_reduced_pipe); 1067 continue; 1068 } 1069 if (!candidate->enable.dvs_6axis && enable_dvs_6axis) { 1070 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1071 "ia_css_binary_find() [%d] continue: !%d && %d\n", 1072 __LINE__, 1073 candidate->enable.dvs_6axis, 1074 enable_dvs_6axis); 1075 continue; 1076 } 1077 if (candidate->enable.high_speed && !enable_high_speed) { 1078 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1079 "ia_css_binary_find() [%d] continue: %d && !%d\n", 1080 __LINE__, 1081 candidate->enable.high_speed, 1082 enable_high_speed); 1083 continue; 1084 } 1085 if (!candidate->enable.xnr && need_xnr) { 1086 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1087 "ia_css_binary_find() [%d] continue: %d && !%d\n", 1088 __LINE__, 1089 candidate->enable.xnr, 1090 need_xnr); 1091 continue; 1092 } 1093 if (!(candidate->enable.ds & 2) && enable_yuv_ds) { 1094 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1095 "ia_css_binary_find() [%d] continue: !%d && %d\n", 1096 __LINE__, 1097 ((candidate->enable.ds & 2) != 0), 1098 enable_yuv_ds); 1099 continue; 1100 } 1101 if ((candidate->enable.ds & 2) && !enable_yuv_ds) { 1102 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1103 "ia_css_binary_find() [%d] continue: %d && !%d\n", 1104 __LINE__, 1105 ((candidate->enable.ds & 2) != 0), 1106 enable_yuv_ds); 1107 continue; 1108 } 1109 1110 if (mode == IA_CSS_BINARY_MODE_VIDEO && 1111 candidate->enable.ds && need_ds) 1112 need_dz = false; 1113 1114 /* when we require vf output, we need to have vf_veceven */ 1115 if ((req_vf_info) && !(candidate->enable.vf_veceven || 1116 /* or variable vf vec even */ 1117 candidate->vf_dec.is_variable || 1118 /* or more than one output pin. */ 1119 xcandidate->num_output_pins > 1)) { 1120 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1121 "ia_css_binary_find() [%d] continue: (%p != NULL) && !(%d || %d || (%d >%d))\n", 1122 __LINE__, req_vf_info, 1123 candidate->enable.vf_veceven, 1124 candidate->vf_dec.is_variable, 1125 xcandidate->num_output_pins, 1); 1126 continue; 1127 } 1128 if (!candidate->enable.dvs_envelope && need_dvs) { 1129 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1130 "ia_css_binary_find() [%d] continue: !%d && %d\n", 1131 __LINE__, 1132 candidate->enable.dvs_envelope, (int)need_dvs); 1133 continue; 1134 } 1135 /* internal_res check considers input, output, and dvs envelope sizes */ 1136 ia_css_binary_internal_res(req_in_info, req_bds_out_info, 1137 req_bin_out_info, &dvs_env, candidate, &internal_res); 1138 if (internal_res.width > candidate->internal.max_width) { 1139 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1140 "ia_css_binary_find() [%d] continue: (%d > %d)\n", 1141 __LINE__, internal_res.width, 1142 candidate->internal.max_width); 1143 continue; 1144 } 1145 if (internal_res.height > candidate->internal.max_height) { 1146 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1147 "ia_css_binary_find() [%d] continue: (%d > %d)\n", 1148 __LINE__, internal_res.height, 1149 candidate->internal.max_height); 1150 continue; 1151 } 1152 if (!candidate->enable.ds && need_ds && !(xcandidate->num_output_pins > 1)) { 1153 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1154 "ia_css_binary_find() [%d] continue: !%d && %d\n", 1155 __LINE__, candidate->enable.ds, (int)need_ds); 1156 continue; 1157 } 1158 if (!candidate->enable.uds && !candidate->enable.dvs_6axis && need_dz) { 1159 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1160 "ia_css_binary_find() [%d] continue: !%d && !%d && %d\n", 1161 __LINE__, candidate->enable.uds, 1162 candidate->enable.dvs_6axis, (int)need_dz); 1163 continue; 1164 } 1165 if (online && candidate->input.source == IA_CSS_BINARY_INPUT_MEMORY) { 1166 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1167 "ia_css_binary_find() [%d] continue: %d && (%d == %d)\n", 1168 __LINE__, online, candidate->input.source, 1169 IA_CSS_BINARY_INPUT_MEMORY); 1170 continue; 1171 } 1172 if (!online && candidate->input.source == IA_CSS_BINARY_INPUT_SENSOR) { 1173 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1174 "ia_css_binary_find() [%d] continue: !%d && (%d == %d)\n", 1175 __LINE__, online, candidate->input.source, 1176 IA_CSS_BINARY_INPUT_SENSOR); 1177 continue; 1178 } 1179 if (req_bin_out_info->res.width < candidate->output.min_width || 1180 req_bin_out_info->res.width > candidate->output.max_width) { 1181 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1182 "ia_css_binary_find() [%d] continue: (%d > %d) || (%d < %d)\n", 1183 __LINE__, 1184 req_bin_out_info->padded_width, 1185 candidate->output.min_width, 1186 req_bin_out_info->padded_width, 1187 candidate->output.max_width); 1188 continue; 1189 } 1190 if (xcandidate->num_output_pins > 1 && 1191 /* in case we have a second output pin, */ 1192 req_vf_info) { /* and we need vf output. */ 1193 if (req_vf_info->res.width > candidate->output.max_width) { 1194 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1195 "ia_css_binary_find() [%d] continue: (%d < %d)\n", 1196 __LINE__, 1197 req_vf_info->res.width, 1198 candidate->output.max_width); 1199 continue; 1200 } 1201 } 1202 if (req_in_info->padded_width > candidate->input.max_width) { 1203 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1204 "ia_css_binary_find() [%d] continue: (%d > %d)\n", 1205 __LINE__, req_in_info->padded_width, 1206 candidate->input.max_width); 1207 continue; 1208 } 1209 if (!binary_supports_output_format(xcandidate, req_bin_out_info->format)) { 1210 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1211 "ia_css_binary_find() [%d] continue: !%d\n", 1212 __LINE__, 1213 binary_supports_output_format(xcandidate, req_bin_out_info->format)); 1214 continue; 1215 } 1216 if (xcandidate->num_output_pins > 1 && 1217 /* in case we have a second output pin, */ 1218 req_vf_info && /* and we need vf output. */ 1219 /* check if the required vf format 1220 is supported. */ 1221 !binary_supports_output_format(xcandidate, req_vf_info->format)) { 1222 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1223 "ia_css_binary_find() [%d] continue: (%d > %d) && (%p != NULL) && !%d\n", 1224 __LINE__, xcandidate->num_output_pins, 1, 1225 req_vf_info, 1226 binary_supports_output_format(xcandidate, req_vf_info->format)); 1227 continue; 1228 } 1229 1230 /* Check if vf_veceven supports the requested vf format */ 1231 if (xcandidate->num_output_pins == 1 && 1232 req_vf_info && candidate->enable.vf_veceven && 1233 !binary_supports_vf_format(xcandidate, req_vf_info->format)) { 1234 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1235 "ia_css_binary_find() [%d] continue: (%d == %d) && (%p != NULL) && %d && !%d\n", 1236 __LINE__, xcandidate->num_output_pins, 1, 1237 req_vf_info, candidate->enable.vf_veceven, 1238 binary_supports_vf_format(xcandidate, req_vf_info->format)); 1239 continue; 1240 } 1241 1242 /* Check if vf_veceven supports the requested vf width */ 1243 if (xcandidate->num_output_pins == 1 && 1244 req_vf_info && candidate->enable.vf_veceven) { /* and we need vf output. */ 1245 if (req_vf_info->res.width > candidate->output.max_width) { 1246 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1247 "ia_css_binary_find() [%d] continue: (%d < %d)\n", 1248 __LINE__, 1249 req_vf_info->res.width, 1250 candidate->output.max_width); 1251 continue; 1252 } 1253 } 1254 1255 if (!supports_bds_factor(candidate->bds.supported_bds_factors, 1256 descr->required_bds_factor)) { 1257 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1258 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n", 1259 __LINE__, candidate->bds.supported_bds_factors, 1260 descr->required_bds_factor); 1261 continue; 1262 } 1263 1264 if (!candidate->enable.dpc && need_dpc) { 1265 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1266 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n", 1267 __LINE__, candidate->enable.dpc, 1268 descr->enable_dpc); 1269 continue; 1270 } 1271 1272 if (candidate->uds.use_bci && enable_capture_pp_bli) { 1273 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1274 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n", 1275 __LINE__, candidate->uds.use_bci, 1276 descr->enable_capture_pp_bli); 1277 continue; 1278 } 1279 1280 /* reconfigure any variable properties of the binary */ 1281 err = ia_css_binary_fill_info(xcandidate, online, two_ppc, 1282 stream_format, req_in_info, 1283 req_bds_out_info, 1284 req_out_info, req_vf_info, 1285 binary, &dvs_env, 1286 descr->stream_config_left_padding, 1287 false); 1288 1289 if (err) 1290 break; 1291 binary_init_metrics(&binary->metrics, &binary->info->sp); 1292 break; 1293 } 1294 1295 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1296 "ia_css_binary_find() selected = %p, mode = %d ID = %d\n", 1297 xcandidate, xcandidate ? xcandidate->sp.pipeline.mode : 0, xcandidate ? xcandidate->sp.id : 0); 1298 1299 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1300 "ia_css_binary_find() leave: return_err=%d\n", err); 1301 1302 if (!err && xcandidate) 1303 dev_dbg(atomisp_dev, 1304 "Using binary %s (id %d), type %d, mode %d, continuous %s\n", 1305 xcandidate->blob->name, 1306 xcandidate->sp.id, 1307 xcandidate->type, 1308 xcandidate->sp.pipeline.mode, 1309 xcandidate->sp.enable.continuous ? "true" : "false"); 1310 1311 1312 return err; 1313 } 1314 1315 int ia_css_binary_find(struct ia_css_binary_descr *descr, 1316 struct ia_css_binary *binary) 1317 { 1318 int ret = __ia_css_binary_find(descr, binary); 1319 1320 if (unlikely(ret)) { 1321 dev_dbg(atomisp_dev, "Seeking for binary failed at:"); 1322 dump_stack(); 1323 } 1324 1325 return ret; 1326 } 1327 1328 unsigned 1329 ia_css_binary_max_vf_width(void) 1330 { 1331 /* This is (should be) true for IPU1 and IPU2 */ 1332 /* For IPU3 (SkyCam) this pointer is guaranteed to be NULL simply because such a binary does not exist */ 1333 if (binary_infos[IA_CSS_BINARY_MODE_VF_PP]) 1334 return binary_infos[IA_CSS_BINARY_MODE_VF_PP]->sp.output.max_width; 1335 return 0; 1336 } 1337 1338 void 1339 ia_css_binary_destroy_isp_parameters(struct ia_css_binary *binary) 1340 { 1341 if (binary) { 1342 ia_css_isp_param_destroy_isp_parameters(&binary->mem_params, 1343 &binary->css_params); 1344 } 1345 } 1346 1347 void 1348 ia_css_binary_get_isp_binaries(struct ia_css_binary_xinfo **binaries, 1349 uint32_t *num_isp_binaries) 1350 { 1351 assert(binaries); 1352 1353 if (num_isp_binaries) 1354 *num_isp_binaries = 0; 1355 1356 *binaries = all_binaries; 1357 if (all_binaries && num_isp_binaries) { 1358 /* -1 to account for sp binary which is not stored in all_binaries */ 1359 if (sh_css_num_binaries > 0) 1360 *num_isp_binaries = sh_css_num_binaries - 1; 1361 } 1362 } 1363