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