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