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