1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Support for Intel Camera Imaging ISP subsystem. 4 * Copyright (c) 2010 - 2015, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 */ 15 16 #include "hmm.h" 17 18 #include "ia_css_debug.h" 19 #include "sw_event_global.h" /* encode_sw_event */ 20 #include "sp.h" /* cnd_sp_irq_enable() */ 21 #include "assert_support.h" 22 #include "sh_css_sp.h" 23 #include "ia_css_pipeline.h" 24 #include "ia_css_isp_param.h" 25 #include "ia_css_bufq.h" 26 27 #define PIPELINE_NUM_UNMAPPED (~0U) 28 #define PIPELINE_SP_THREAD_EMPTY_TOKEN (0x0) 29 #define PIPELINE_SP_THREAD_RESERVED_TOKEN (0x1) 30 31 /******************************************************* 32 *** Static variables 33 ********************************************************/ 34 static unsigned int pipeline_num_to_sp_thread_map[IA_CSS_PIPELINE_NUM_MAX]; 35 static unsigned int pipeline_sp_thread_list[SH_CSS_MAX_SP_THREADS]; 36 37 /******************************************************* 38 *** Static functions 39 ********************************************************/ 40 static void pipeline_init_sp_thread_map(void); 41 static void pipeline_map_num_to_sp_thread(unsigned int pipe_num); 42 static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num); 43 static void pipeline_init_defaults( 44 struct ia_css_pipeline *pipeline, 45 enum ia_css_pipe_id pipe_id, 46 unsigned int pipe_num, 47 unsigned int dvs_frame_delay); 48 49 static void pipeline_stage_destroy(struct ia_css_pipeline_stage *stage); 50 static int pipeline_stage_create( 51 struct ia_css_pipeline_stage_desc *stage_desc, 52 struct ia_css_pipeline_stage **new_stage); 53 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline); 54 static void ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me, 55 bool continuous); 56 57 /******************************************************* 58 *** Public functions 59 ********************************************************/ 60 void ia_css_pipeline_init(void) 61 { 62 pipeline_init_sp_thread_map(); 63 } 64 65 int ia_css_pipeline_create( 66 struct ia_css_pipeline *pipeline, 67 enum ia_css_pipe_id pipe_id, 68 unsigned int pipe_num, 69 unsigned int dvs_frame_delay) 70 { 71 assert(pipeline); 72 IA_CSS_ENTER_PRIVATE("pipeline = %p, pipe_id = %d, pipe_num = %d, dvs_frame_delay = %d", 73 pipeline, pipe_id, pipe_num, dvs_frame_delay); 74 if (!pipeline) { 75 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 76 return -EINVAL; 77 } 78 79 pipeline_init_defaults(pipeline, pipe_id, pipe_num, dvs_frame_delay); 80 81 IA_CSS_LEAVE_ERR_PRIVATE(0); 82 return 0; 83 } 84 85 void ia_css_pipeline_map(unsigned int pipe_num, bool map) 86 { 87 assert(pipe_num < IA_CSS_PIPELINE_NUM_MAX); 88 IA_CSS_ENTER_PRIVATE("pipe_num = %d, map = %d", pipe_num, map); 89 90 if (pipe_num >= IA_CSS_PIPELINE_NUM_MAX) { 91 IA_CSS_ERROR("Invalid pipe number"); 92 IA_CSS_LEAVE_PRIVATE("void"); 93 return; 94 } 95 if (map) 96 pipeline_map_num_to_sp_thread(pipe_num); 97 else 98 pipeline_unmap_num_to_sp_thread(pipe_num); 99 IA_CSS_LEAVE_PRIVATE("void"); 100 } 101 102 /* @brief destroy a pipeline 103 * 104 * @param[in] pipeline 105 * @return None 106 * 107 */ 108 void ia_css_pipeline_destroy(struct ia_css_pipeline *pipeline) 109 { 110 assert(pipeline); 111 IA_CSS_ENTER_PRIVATE("pipeline = %p", pipeline); 112 113 if (!pipeline) { 114 IA_CSS_ERROR("NULL input parameter"); 115 IA_CSS_LEAVE_PRIVATE("void"); 116 return; 117 } 118 119 IA_CSS_LOG("pipe_num = %d", pipeline->pipe_num); 120 121 /* Free the pipeline number */ 122 ia_css_pipeline_clean(pipeline); 123 124 IA_CSS_LEAVE_PRIVATE("void"); 125 } 126 127 /* Run a pipeline and wait till it completes. */ 128 void ia_css_pipeline_start(enum ia_css_pipe_id pipe_id, 129 struct ia_css_pipeline *pipeline) 130 { 131 u8 pipe_num = 0; 132 unsigned int thread_id; 133 134 assert(pipeline); 135 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 136 "ia_css_pipeline_start() enter: pipe_id=%d, pipeline=%p\n", 137 pipe_id, pipeline); 138 pipeline->pipe_id = pipe_id; 139 sh_css_sp_init_pipeline(pipeline, pipe_id, pipe_num, 140 false, false, false, true, SH_CSS_BDS_FACTOR_1_00, 141 SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD, 142 IA_CSS_INPUT_MODE_MEMORY, NULL, NULL, 143 #if !defined(HAS_NO_INPUT_SYSTEM) 144 (enum mipi_port_id)0, 145 #endif 146 NULL, NULL); 147 148 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 149 if (!sh_css_sp_is_running()) { 150 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 151 "ia_css_pipeline_start() error,leaving\n"); 152 /* queues are invalid*/ 153 return; 154 } 155 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM, 156 (uint8_t)thread_id, 157 0, 158 0); 159 160 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 161 "ia_css_pipeline_start() leave: return_void\n"); 162 } 163 164 /* 165 * @brief Query the SP thread ID. 166 * Refer to "sh_css_internal.h" for details. 167 */ 168 bool ia_css_pipeline_get_sp_thread_id(unsigned int key, unsigned int *val) 169 { 170 IA_CSS_ENTER("key=%d, val=%p", key, val); 171 172 if ((!val) || (key >= IA_CSS_PIPELINE_NUM_MAX) || (key >= IA_CSS_PIPE_ID_NUM)) { 173 IA_CSS_LEAVE("return value = false"); 174 return false; 175 } 176 177 *val = pipeline_num_to_sp_thread_map[key]; 178 179 if (*val == (unsigned int)PIPELINE_NUM_UNMAPPED) { 180 IA_CSS_LOG("unmapped pipeline number"); 181 IA_CSS_LEAVE("return value = false"); 182 return false; 183 } 184 IA_CSS_LEAVE("return value = true"); 185 return true; 186 } 187 188 void ia_css_pipeline_dump_thread_map_info(void) 189 { 190 unsigned int i; 191 192 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 193 "pipeline_num_to_sp_thread_map:\n"); 194 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { 195 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 196 "pipe_num: %u, tid: 0x%x\n", i, pipeline_num_to_sp_thread_map[i]); 197 } 198 } 199 200 int ia_css_pipeline_request_stop(struct ia_css_pipeline *pipeline) 201 { 202 int err = 0; 203 unsigned int thread_id; 204 205 assert(pipeline); 206 207 if (!pipeline) 208 return -EINVAL; 209 210 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 211 "ia_css_pipeline_request_stop() enter: pipeline=%p\n", 212 pipeline); 213 pipeline->stop_requested = true; 214 215 /* Send stop event to the sp*/ 216 /* This needs improvement, stop on all the pipes available 217 * in the stream*/ 218 ia_css_pipeline_get_sp_thread_id(pipeline->pipe_num, &thread_id); 219 if (!sh_css_sp_is_running()) { 220 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 221 "ia_css_pipeline_request_stop() leaving\n"); 222 /* queues are invalid */ 223 return -EBUSY; 224 } 225 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_STOP_STREAM, 226 (uint8_t)thread_id, 227 0, 228 0); 229 sh_css_sp_uninit_pipeline(pipeline->pipe_num); 230 231 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 232 "ia_css_pipeline_request_stop() leave: return_err=%d\n", 233 err); 234 return err; 235 } 236 237 void ia_css_pipeline_clean(struct ia_css_pipeline *pipeline) 238 { 239 struct ia_css_pipeline_stage *s; 240 241 assert(pipeline); 242 IA_CSS_ENTER_PRIVATE("pipeline = %p", pipeline); 243 244 if (!pipeline) { 245 IA_CSS_ERROR("NULL input parameter"); 246 IA_CSS_LEAVE_PRIVATE("void"); 247 return; 248 } 249 s = pipeline->stages; 250 251 while (s) { 252 struct ia_css_pipeline_stage *next = s->next; 253 254 pipeline_stage_destroy(s); 255 s = next; 256 } 257 pipeline_init_defaults(pipeline, pipeline->pipe_id, pipeline->pipe_num, 258 pipeline->dvs_frame_delay); 259 260 IA_CSS_LEAVE_PRIVATE("void"); 261 } 262 263 /* @brief Add a stage to pipeline. 264 * 265 * @param pipeline Pointer to the pipeline to be added to. 266 * @param[in] stage_desc The description of the stage 267 * @param[out] stage The successor of the stage. 268 * @return 0 or error code upon error. 269 * 270 * Add a new stage to a non-NULL pipeline. 271 * The stage consists of an ISP binary or firmware and input and 272 * output arguments. 273 */ 274 int ia_css_pipeline_create_and_add_stage( 275 struct ia_css_pipeline *pipeline, 276 struct ia_css_pipeline_stage_desc *stage_desc, 277 struct ia_css_pipeline_stage **stage) 278 { 279 struct ia_css_pipeline_stage *last, *new_stage = NULL; 280 int err; 281 282 /* other arguments can be NULL */ 283 assert(pipeline); 284 assert(stage_desc); 285 last = pipeline->stages; 286 287 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 288 "ia_css_pipeline_create_and_add_stage() enter:\n"); 289 if (!stage_desc->binary && !stage_desc->firmware 290 && (stage_desc->sp_func == IA_CSS_PIPELINE_NO_FUNC)) { 291 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 292 "ia_css_pipeline_create_and_add_stage() done: Invalid args\n"); 293 294 return -EINVAL; 295 } 296 297 /* Find the last stage */ 298 while (last && last->next) 299 last = last->next; 300 301 /* if in_frame is not set, we use the out_frame from the previous 302 * stage, if no previous stage, it's an error. 303 */ 304 if ((stage_desc->sp_func == IA_CSS_PIPELINE_NO_FUNC) 305 && (!stage_desc->in_frame) 306 && (!stage_desc->firmware) 307 && (!stage_desc->binary->online)) { 308 /* Do this only for ISP stages*/ 309 if (last && last->args.out_frame[0]) 310 stage_desc->in_frame = last->args.out_frame[0]; 311 312 if (!stage_desc->in_frame) 313 return -EINVAL; 314 } 315 316 /* Create the new stage */ 317 err = pipeline_stage_create(stage_desc, &new_stage); 318 if (err) { 319 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 320 "ia_css_pipeline_create_and_add_stage() done: stage_create_failed\n"); 321 return err; 322 } 323 324 if (last) 325 last->next = new_stage; 326 else 327 pipeline->stages = new_stage; 328 329 /* Output the new stage */ 330 if (stage) 331 *stage = new_stage; 332 333 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 334 "ia_css_pipeline_create_and_add_stage() done:\n"); 335 return 0; 336 } 337 338 void ia_css_pipeline_finalize_stages(struct ia_css_pipeline *pipeline, 339 bool continuous) 340 { 341 unsigned int i = 0; 342 struct ia_css_pipeline_stage *stage; 343 344 assert(pipeline); 345 for (stage = pipeline->stages; stage; stage = stage->next) { 346 stage->stage_num = i; 347 i++; 348 } 349 pipeline->num_stages = i; 350 351 ia_css_pipeline_set_zoom_stage(pipeline); 352 ia_css_pipeline_configure_inout_port(pipeline, continuous); 353 } 354 355 int ia_css_pipeline_get_stage(struct ia_css_pipeline *pipeline, 356 int mode, 357 struct ia_css_pipeline_stage **stage) 358 { 359 struct ia_css_pipeline_stage *s; 360 361 assert(pipeline); 362 assert(stage); 363 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 364 "ia_css_pipeline_get_stage() enter:\n"); 365 for (s = pipeline->stages; s; s = s->next) { 366 if (s->mode == mode) { 367 *stage = s; 368 return 0; 369 } 370 } 371 return -EINVAL; 372 } 373 374 int ia_css_pipeline_get_stage_from_fw(struct ia_css_pipeline 375 *pipeline, 376 u32 fw_handle, 377 struct ia_css_pipeline_stage **stage) 378 { 379 struct ia_css_pipeline_stage *s; 380 381 assert(pipeline); 382 assert(stage); 383 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s()\n", __func__); 384 for (s = pipeline->stages; s; s = s->next) { 385 if ((s->firmware) && (s->firmware->handle == fw_handle)) { 386 *stage = s; 387 return 0; 388 } 389 } 390 return -EINVAL; 391 } 392 393 int ia_css_pipeline_get_fw_from_stage(struct ia_css_pipeline 394 *pipeline, 395 u32 stage_num, 396 uint32_t *fw_handle) 397 { 398 struct ia_css_pipeline_stage *s; 399 400 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s()\n", __func__); 401 if ((!pipeline) || (!fw_handle)) 402 return -EINVAL; 403 404 for (s = pipeline->stages; s; s = s->next) { 405 if ((s->stage_num == stage_num) && (s->firmware)) { 406 *fw_handle = s->firmware->handle; 407 return 0; 408 } 409 } 410 return -EINVAL; 411 } 412 413 int ia_css_pipeline_get_output_stage( 414 struct ia_css_pipeline *pipeline, 415 int mode, 416 struct ia_css_pipeline_stage **stage) 417 { 418 struct ia_css_pipeline_stage *s; 419 420 assert(pipeline); 421 assert(stage); 422 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 423 "ia_css_pipeline_get_output_stage() enter:\n"); 424 425 *stage = NULL; 426 /* First find acceleration firmware at end of pipe */ 427 for (s = pipeline->stages; s; s = s->next) { 428 if (s->firmware && s->mode == mode && 429 s->firmware->info.isp.sp.enable.output) 430 *stage = s; 431 } 432 if (*stage) 433 return 0; 434 /* If no firmware, find binary in pipe */ 435 return ia_css_pipeline_get_stage(pipeline, mode, stage); 436 } 437 438 bool ia_css_pipeline_has_stopped(struct ia_css_pipeline *pipeline) 439 { 440 /* Android compilation files if made an local variable 441 stack size on android is limited to 2k and this structure 442 is around 2.5K, in place of static malloc can be done but 443 if this call is made too often it will lead to fragment memory 444 versus a fixed allocation */ 445 static struct sh_css_sp_group sp_group; 446 unsigned int thread_id; 447 const struct ia_css_fw_info *fw; 448 unsigned int HIVE_ADDR_sp_group; 449 450 fw = &sh_css_sp_fw; 451 HIVE_ADDR_sp_group = fw->info.sp.group; 452 453 ia_css_pipeline_get_sp_thread_id(pipeline->pipe_num, &thread_id); 454 sp_dmem_load(SP0_ID, 455 (unsigned int)sp_address_of(sp_group), 456 &sp_group, sizeof(struct sh_css_sp_group)); 457 return sp_group.pipe[thread_id].num_stages == 0; 458 } 459 460 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 461 struct sh_css_sp_pipeline_io_status *ia_css_pipeline_get_pipe_io_status(void) 462 { 463 return(&sh_css_sp_group.pipe_io_status); 464 } 465 #endif 466 467 bool ia_css_pipeline_is_mapped(unsigned int key) 468 { 469 bool ret = false; 470 471 IA_CSS_ENTER_PRIVATE("key = %d", key); 472 473 if ((key >= IA_CSS_PIPELINE_NUM_MAX) || (key >= IA_CSS_PIPE_ID_NUM)) { 474 IA_CSS_ERROR("Invalid key!!"); 475 IA_CSS_LEAVE_PRIVATE("return = %d", false); 476 return false; 477 } 478 479 ret = (bool)(pipeline_num_to_sp_thread_map[key] != (unsigned int) 480 PIPELINE_NUM_UNMAPPED); 481 482 IA_CSS_LEAVE_PRIVATE("return = %d", ret); 483 return ret; 484 } 485 486 /******************************************************* 487 *** Static functions 488 ********************************************************/ 489 490 /* Pipeline: 491 * To organize the several different binaries for each type of mode, 492 * we use a pipeline. A pipeline contains a number of stages, each with 493 * their own binary and frame pointers. 494 * When stages are added to a pipeline, output frames that are not passed 495 * from outside are automatically allocated. 496 * When input frames are not passed from outside, each stage will use the 497 * output frame of the previous stage as input (the full resolution output, 498 * not the viewfinder output). 499 * Pipelines must be cleaned and re-created when settings of the binaries 500 * change. 501 */ 502 static void pipeline_stage_destroy(struct ia_css_pipeline_stage *stage) 503 { 504 unsigned int i; 505 506 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { 507 if (stage->out_frame_allocated[i]) { 508 ia_css_frame_free(stage->args.out_frame[i]); 509 stage->args.out_frame[i] = NULL; 510 } 511 } 512 if (stage->vf_frame_allocated) { 513 ia_css_frame_free(stage->args.out_vf_frame); 514 stage->args.out_vf_frame = NULL; 515 } 516 kvfree(stage); 517 } 518 519 static void pipeline_init_sp_thread_map(void) 520 { 521 unsigned int i; 522 523 for (i = 1; i < SH_CSS_MAX_SP_THREADS; i++) 524 pipeline_sp_thread_list[i] = PIPELINE_SP_THREAD_EMPTY_TOKEN; 525 526 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) 527 pipeline_num_to_sp_thread_map[i] = PIPELINE_NUM_UNMAPPED; 528 } 529 530 static void pipeline_map_num_to_sp_thread(unsigned int pipe_num) 531 { 532 unsigned int i; 533 bool found_sp_thread = false; 534 535 /* pipe is not mapped to any thread */ 536 assert(pipeline_num_to_sp_thread_map[pipe_num] 537 == (unsigned int)PIPELINE_NUM_UNMAPPED); 538 539 for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) { 540 if (pipeline_sp_thread_list[i] == 541 PIPELINE_SP_THREAD_EMPTY_TOKEN) { 542 pipeline_sp_thread_list[i] = 543 PIPELINE_SP_THREAD_RESERVED_TOKEN; 544 pipeline_num_to_sp_thread_map[pipe_num] = i; 545 found_sp_thread = true; 546 break; 547 } 548 } 549 550 /* Make sure a mapping is found */ 551 /* I could do: 552 assert(i < SH_CSS_MAX_SP_THREADS); 553 554 But the below is more descriptive. 555 */ 556 assert(found_sp_thread); 557 } 558 559 static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num) 560 { 561 unsigned int thread_id; 562 563 assert(pipeline_num_to_sp_thread_map[pipe_num] 564 != (unsigned int)PIPELINE_NUM_UNMAPPED); 565 566 thread_id = pipeline_num_to_sp_thread_map[pipe_num]; 567 pipeline_num_to_sp_thread_map[pipe_num] = PIPELINE_NUM_UNMAPPED; 568 pipeline_sp_thread_list[thread_id] = PIPELINE_SP_THREAD_EMPTY_TOKEN; 569 } 570 571 static int pipeline_stage_create( 572 struct ia_css_pipeline_stage_desc *stage_desc, 573 struct ia_css_pipeline_stage **new_stage) 574 { 575 int err = 0; 576 struct ia_css_pipeline_stage *stage = NULL; 577 struct ia_css_binary *binary; 578 struct ia_css_frame *vf_frame; 579 struct ia_css_frame *out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 580 const struct ia_css_fw_info *firmware; 581 unsigned int i; 582 583 /* Verify input parameters*/ 584 if (!(stage_desc->in_frame) && !(stage_desc->firmware) 585 && (stage_desc->binary) && !(stage_desc->binary->online)) { 586 err = -EINVAL; 587 goto ERR; 588 } 589 590 binary = stage_desc->binary; 591 firmware = stage_desc->firmware; 592 vf_frame = stage_desc->vf_frame; 593 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { 594 out_frame[i] = stage_desc->out_frame[i]; 595 } 596 597 stage = kvzalloc(sizeof(*stage), GFP_KERNEL); 598 if (!stage) { 599 err = -ENOMEM; 600 goto ERR; 601 } 602 603 if (firmware) { 604 stage->binary = NULL; 605 stage->binary_info = 606 (struct ia_css_binary_info *)&firmware->info.isp; 607 } else { 608 stage->binary = binary; 609 if (binary) 610 stage->binary_info = 611 (struct ia_css_binary_info *)binary->info; 612 else 613 stage->binary_info = NULL; 614 } 615 616 stage->firmware = firmware; 617 stage->sp_func = stage_desc->sp_func; 618 stage->max_input_width = stage_desc->max_input_width; 619 stage->mode = stage_desc->mode; 620 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) 621 stage->out_frame_allocated[i] = false; 622 stage->vf_frame_allocated = false; 623 stage->next = NULL; 624 sh_css_binary_args_reset(&stage->args); 625 626 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { 627 if (!(out_frame[i]) && (binary) 628 && (binary->out_frame_info[i].res.width)) { 629 err = ia_css_frame_allocate_from_info(&out_frame[i], 630 &binary->out_frame_info[i]); 631 if (err) 632 goto ERR; 633 stage->out_frame_allocated[i] = true; 634 } 635 } 636 /* VF frame is not needed in case of need_pp 637 However, the capture binary needs a vf frame to write to. 638 */ 639 if (!vf_frame) { 640 if ((binary && binary->vf_frame_info.res.width) || 641 (firmware && firmware->info.isp.sp.enable.vf_veceven) 642 ) { 643 err = ia_css_frame_allocate_from_info(&vf_frame, 644 &binary->vf_frame_info); 645 if (err) 646 goto ERR; 647 stage->vf_frame_allocated = true; 648 } 649 } else if (vf_frame && binary && binary->vf_frame_info.res.width 650 && !firmware) { 651 /* only mark as allocated if buffer pointer available */ 652 if (vf_frame->data != mmgr_NULL) 653 stage->vf_frame_allocated = true; 654 } 655 656 stage->args.in_frame = stage_desc->in_frame; 657 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) 658 stage->args.out_frame[i] = out_frame[i]; 659 stage->args.out_vf_frame = vf_frame; 660 *new_stage = stage; 661 return err; 662 ERR: 663 if (stage) 664 pipeline_stage_destroy(stage); 665 return err; 666 } 667 668 static const struct ia_css_frame ia_css_default_frame = DEFAULT_FRAME; 669 670 static void pipeline_init_defaults( 671 struct ia_css_pipeline *pipeline, 672 enum ia_css_pipe_id pipe_id, 673 unsigned int pipe_num, 674 unsigned int dvs_frame_delay) 675 { 676 unsigned int i; 677 678 pipeline->pipe_id = pipe_id; 679 pipeline->stages = NULL; 680 pipeline->stop_requested = false; 681 pipeline->current_stage = NULL; 682 683 memcpy(&pipeline->in_frame, &ia_css_default_frame, 684 sizeof(ia_css_default_frame)); 685 686 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 687 memcpy(&pipeline->out_frame[i], &ia_css_default_frame, 688 sizeof(ia_css_default_frame)); 689 memcpy(&pipeline->vf_frame[i], &ia_css_default_frame, 690 sizeof(ia_css_default_frame)); 691 } 692 pipeline->num_execs = -1; 693 pipeline->acquire_isp_each_stage = true; 694 pipeline->pipe_num = (uint8_t)pipe_num; 695 pipeline->dvs_frame_delay = dvs_frame_delay; 696 } 697 698 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline) 699 { 700 struct ia_css_pipeline_stage *stage = NULL; 701 int err = 0; 702 703 assert(pipeline); 704 if (pipeline->pipe_id == IA_CSS_PIPE_ID_PREVIEW) { 705 /* in preview pipeline, vf_pp stage should do zoom */ 706 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VF_PP, &stage); 707 if (!err) 708 stage->enable_zoom = true; 709 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_CAPTURE) { 710 /* in capture pipeline, capture_pp stage should do zoom */ 711 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP, 712 &stage); 713 if (!err) 714 stage->enable_zoom = true; 715 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_VIDEO) { 716 /* in video pipeline, video stage should do zoom */ 717 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VIDEO, &stage); 718 if (!err) 719 stage->enable_zoom = true; 720 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_YUVPP) { 721 /* in yuvpp pipeline, first yuv_scaler stage should do zoom */ 722 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP, 723 &stage); 724 if (!err) 725 stage->enable_zoom = true; 726 } 727 } 728 729 static void 730 ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me, 731 bool continuous) 732 { 733 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 734 "ia_css_pipeline_configure_inout_port() enter: pipe_id(%d) continuous(%d)\n", 735 me->pipe_id, continuous); 736 switch (me->pipe_id) { 737 case IA_CSS_PIPE_ID_PREVIEW: 738 case IA_CSS_PIPE_ID_VIDEO: 739 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 740 (uint8_t)SH_CSS_PORT_INPUT, 741 (uint8_t)(continuous ? SH_CSS_COPYSINK_TYPE : SH_CSS_HOST_TYPE), 1); 742 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 743 (uint8_t)SH_CSS_PORT_OUTPUT, 744 (uint8_t)SH_CSS_HOST_TYPE, 1); 745 break; 746 case IA_CSS_PIPE_ID_COPY: /*Copy pipe ports configured to "offline" mode*/ 747 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 748 (uint8_t)SH_CSS_PORT_INPUT, 749 (uint8_t)SH_CSS_HOST_TYPE, 1); 750 if (continuous) { 751 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 752 (uint8_t)SH_CSS_PORT_OUTPUT, 753 (uint8_t)SH_CSS_COPYSINK_TYPE, 1); 754 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 755 (uint8_t)SH_CSS_PORT_OUTPUT, 756 (uint8_t)SH_CSS_TAGGERSINK_TYPE, 1); 757 } else { 758 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 759 (uint8_t)SH_CSS_PORT_OUTPUT, 760 (uint8_t)SH_CSS_HOST_TYPE, 1); 761 } 762 break; 763 case IA_CSS_PIPE_ID_CAPTURE: 764 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 765 (uint8_t)SH_CSS_PORT_INPUT, 766 (uint8_t)(continuous ? SH_CSS_TAGGERSINK_TYPE : SH_CSS_HOST_TYPE), 767 1); 768 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 769 (uint8_t)SH_CSS_PORT_OUTPUT, 770 (uint8_t)SH_CSS_HOST_TYPE, 1); 771 break; 772 case IA_CSS_PIPE_ID_YUVPP: 773 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 774 (uint8_t)SH_CSS_PORT_INPUT, 775 (uint8_t)(SH_CSS_HOST_TYPE), 1); 776 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 777 (uint8_t)SH_CSS_PORT_OUTPUT, 778 (uint8_t)SH_CSS_HOST_TYPE, 1); 779 break; 780 case IA_CSS_PIPE_ID_ACC: 781 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 782 (uint8_t)SH_CSS_PORT_INPUT, 783 (uint8_t)SH_CSS_HOST_TYPE, 1); 784 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config, 785 (uint8_t)SH_CSS_PORT_OUTPUT, 786 (uint8_t)SH_CSS_HOST_TYPE, 1); 787 break; 788 default: 789 break; 790 } 791 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 792 "ia_css_pipeline_configure_inout_port() leave: inout_port_config(%x)\n", 793 me->inout_port_config); 794 } 795