1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Support for Intel Camera Imaging ISP subsystem. 4 * Copyright (c) 2015, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 */ 15 16 /*! \file */ 17 #include <linux/mm.h> 18 #include <linux/slab.h> 19 #include <linux/vmalloc.h> 20 21 #include "hmm.h" 22 23 #include "ia_css.h" 24 #include "sh_css_hrt.h" /* only for file 2 MIPI */ 25 #include "ia_css_buffer.h" 26 #include "ia_css_binary.h" 27 #include "sh_css_internal.h" 28 #include "sh_css_mipi.h" 29 #include "sh_css_sp.h" /* sh_css_sp_group */ 30 #include "ia_css_isys.h" 31 #include "ia_css_frame.h" 32 #include "sh_css_defs.h" 33 #include "sh_css_firmware.h" 34 #include "sh_css_params.h" 35 #include "sh_css_params_internal.h" 36 #include "sh_css_param_shading.h" 37 #include "ia_css_refcount.h" 38 #include "ia_css_rmgr.h" 39 #include "ia_css_debug.h" 40 #include "ia_css_debug_pipe.h" 41 #include "ia_css_device_access.h" 42 #include "device_access.h" 43 #include "sh_css_legacy.h" 44 #include "ia_css_pipeline.h" 45 #include "ia_css_stream.h" 46 #include "sh_css_stream_format.h" 47 #include "ia_css_pipe.h" 48 #include "ia_css_util.h" 49 #include "ia_css_pipe_util.h" 50 #include "ia_css_pipe_binarydesc.h" 51 #include "ia_css_pipe_stagedesc.h" 52 #ifdef USE_INPUT_SYSTEM_VERSION_2 53 #include "ia_css_isys.h" 54 #endif 55 56 #include "tag.h" 57 #include "assert_support.h" 58 #include "math_support.h" 59 #include "sw_event_global.h" /* Event IDs.*/ 60 #if !defined(HAS_NO_INPUT_FORMATTER) 61 #include "ia_css_ifmtr.h" 62 #endif 63 #include "input_system.h" 64 #include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */ 65 #include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */ 66 #include "gdc_device.h" /* HRT_GDC_N */ 67 #include "dma.h" /* dma_set_max_burst_size() */ 68 #include "irq.h" /* virq */ 69 #include "sp.h" /* cnd_sp_irq_enable() */ 70 #include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */ 71 #include "gp_device.h" /* gp_device_reg_store() */ 72 #define __INLINE_GPIO__ 73 #include "gpio.h" 74 #include "timed_ctrl.h" 75 #include "ia_css_inputfifo.h" 76 #define WITH_PC_MONITORING 0 77 78 #define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0 79 80 #if WITH_PC_MONITORING 81 #define MULTIPLE_SAMPLES 1 82 #define NOF_SAMPLES 60 83 #include "linux/kthread.h" 84 #include "linux/sched.h" 85 #include "linux/delay.h" 86 #include "sh_css_metrics.h" 87 static int thread_alive; 88 #endif /* WITH_PC_MONITORING */ 89 90 #include "ia_css_spctrl.h" 91 #include "ia_css_version_data.h" 92 #include "sh_css_struct.h" 93 #include "ia_css_bufq.h" 94 #include "ia_css_timer.h" /* clock_value_t */ 95 96 #include "isp/modes/interface/input_buf.isp.h" 97 98 /* Name of the sp program: should not be built-in */ 99 #define SP_PROG_NAME "sp" 100 /* Size of Refcount List */ 101 #define REFCOUNT_SIZE 1000 102 103 /* for JPEG, we don't know the length of the image upfront, 104 * but since we support sensor upto 16MP, we take this as 105 * upper limit. 106 */ 107 #define JPEG_BYTES (16 * 1024 * 1024) 108 109 #define STATS_ENABLED(stage) (stage && stage->binary && stage->binary->info && \ 110 (stage->binary->info->sp.enable.s3a || stage->binary->info->sp.enable.dis)) 111 112 struct sh_css my_css; 113 114 int (*sh_css_printf)(const char *fmt, va_list args) = NULL; 115 116 /* modes of work: stream_create and stream_destroy will update the save/restore data 117 only when in working mode, not suspend/resume 118 */ 119 enum ia_sh_css_modes { 120 sh_css_mode_none = 0, 121 sh_css_mode_working, 122 sh_css_mode_suspend, 123 sh_css_mode_resume 124 }; 125 126 /* a stream seed, to save and restore the stream data. 127 the stream seed contains all the data required to "grow" the seed again after it was closed. 128 */ 129 struct sh_css_stream_seed { 130 struct ia_css_stream 131 **orig_stream; /* pointer to restore the original handle */ 132 struct ia_css_stream *stream; /* handle, used as ID too.*/ 133 struct ia_css_stream_config stream_config; /* stream config struct */ 134 int num_pipes; 135 struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; /* pipe handles */ 136 struct ia_css_pipe 137 **orig_pipes[IA_CSS_PIPE_ID_NUM]; /* pointer to restore original handle */ 138 struct ia_css_pipe_config 139 pipe_config[IA_CSS_PIPE_ID_NUM]; /* pipe config structs */ 140 }; 141 142 #define MAX_ACTIVE_STREAMS 5 143 /* A global struct for save/restore to hold all the data that should sustain power-down: 144 MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds. 145 */ 146 struct sh_css_save { 147 enum ia_sh_css_modes mode; 148 u32 mmu_base; /* the last mmu_base */ 149 enum ia_css_irq_type irq_type; 150 struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS]; 151 struct ia_css_fw *loaded_fw; /* fw struct previously loaded */ 152 struct ia_css_env driver_env; /* driver-supplied env copy */ 153 }; 154 155 static bool my_css_save_initialized; /* if my_css_save was initialized */ 156 static struct sh_css_save my_css_save; 157 158 /* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline, 159 this array is temporary and will be replaced by resource manager*/ 160 /* Taking the biggest Size for number of Elements */ 161 #define MAX_HMM_BUFFER_NUM \ 162 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2)) 163 164 struct sh_css_hmm_buffer_record { 165 bool in_use; 166 enum ia_css_buffer_type type; 167 struct ia_css_rmgr_vbuf_handle *h_vbuf; 168 hrt_address kernel_ptr; 169 }; 170 171 static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM]; 172 173 #define GPIO_FLASH_PIN_MASK BIT(HIVE_GPIO_STROBE_TRIGGER_PIN) 174 175 static bool fw_explicitly_loaded; 176 177 /* 178 * Local prototypes 179 */ 180 181 static int 182 allocate_delay_frames(struct ia_css_pipe *pipe); 183 184 static int 185 sh_css_pipe_start(struct ia_css_stream *stream); 186 187 /* ISP 2401 */ 188 /* 189 * @brief Stop all "ia_css_pipe" instances in the target 190 * "ia_css_stream" instance. 191 * 192 * @param[in] stream Point to the target "ia_css_stream" instance. 193 * 194 * @return 195 * - 0, if the "stop" requests have been successfully sent out. 196 * - CSS error code, otherwise. 197 * 198 * 199 * NOTE 200 * This API sends the "stop" requests to the "ia_css_pipe" 201 * instances in the same "ia_css_stream" instance. It will 202 * return without waiting for all "ia_css_pipe" instatnces 203 * being stopped. 204 */ 205 static int 206 sh_css_pipes_stop(struct ia_css_stream *stream); 207 208 /* 209 * @brief Check if all "ia_css_pipe" instances in the target 210 * "ia_css_stream" instance have stopped. 211 * 212 * @param[in] stream Point to the target "ia_css_stream" instance. 213 * 214 * @return 215 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream" 216 * instance have ben stopped. 217 * - false, otherwise. 218 */ 219 /* ISP 2401 */ 220 static bool 221 sh_css_pipes_have_stopped(struct ia_css_stream *stream); 222 223 /* ISP 2401 */ 224 static int 225 ia_css_pipe_check_format(struct ia_css_pipe *pipe, 226 enum ia_css_frame_format format); 227 228 /* ISP 2401 */ 229 static int 230 check_pipe_resolutions(const struct ia_css_pipe *pipe); 231 232 static int 233 ia_css_pipe_load_extension(struct ia_css_pipe *pipe, 234 struct ia_css_fw_info *firmware); 235 236 static void 237 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe, 238 struct ia_css_fw_info *firmware); 239 static void 240 ia_css_reset_defaults(struct sh_css *css); 241 242 static void 243 sh_css_init_host_sp_control_vars(void); 244 245 static int set_num_primary_stages(unsigned int *num, 246 enum ia_css_pipe_version version); 247 248 static bool 249 need_capture_pp(const struct ia_css_pipe *pipe); 250 251 static bool 252 need_yuv_scaler_stage(const struct ia_css_pipe *pipe); 253 254 static int ia_css_pipe_create_cas_scaler_desc_single_output( 255 struct ia_css_frame_info *cas_scaler_in_info, 256 struct ia_css_frame_info *cas_scaler_out_info, 257 struct ia_css_frame_info *cas_scaler_vf_info, 258 struct ia_css_cas_binary_descr *descr); 259 260 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr 261 *descr); 262 263 static bool 264 need_downscaling(const struct ia_css_resolution in_res, 265 const struct ia_css_resolution out_res); 266 267 static bool need_capt_ldc(const struct ia_css_pipe *pipe); 268 269 static int 270 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe); 271 272 static 273 int sh_css_pipe_get_viewfinder_frame_info( 274 struct ia_css_pipe *pipe, 275 struct ia_css_frame_info *info, 276 unsigned int idx); 277 278 static int 279 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, 280 struct ia_css_frame_info *info, 281 unsigned int idx); 282 283 static int 284 capture_start(struct ia_css_pipe *pipe); 285 286 static int 287 video_start(struct ia_css_pipe *pipe); 288 289 static int 290 preview_start(struct ia_css_pipe *pipe); 291 292 static int 293 yuvpp_start(struct ia_css_pipe *pipe); 294 295 static bool copy_on_sp(struct ia_css_pipe *pipe); 296 297 static int 298 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, 299 struct ia_css_frame *vf_frame, unsigned int idx); 300 301 static int 302 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe, 303 struct ia_css_frame *frame, enum ia_css_frame_format format); 304 305 static int 306 init_out_frameinfo_defaults(struct ia_css_pipe *pipe, 307 struct ia_css_frame *out_frame, unsigned int idx); 308 309 static int 310 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, 311 const void *acc_fw); 312 313 static int 314 alloc_continuous_frames( 315 struct ia_css_pipe *pipe, bool init_time); 316 317 static void 318 pipe_global_init(void); 319 320 static int 321 pipe_generate_pipe_num(const struct ia_css_pipe *pipe, 322 unsigned int *pipe_number); 323 324 static void 325 pipe_release_pipe_num(unsigned int pipe_num); 326 327 static int 328 create_host_pipeline_structure(struct ia_css_stream *stream); 329 330 static int 331 create_host_pipeline(struct ia_css_stream *stream); 332 333 static int 334 create_host_preview_pipeline(struct ia_css_pipe *pipe); 335 336 static int 337 create_host_video_pipeline(struct ia_css_pipe *pipe); 338 339 static int 340 create_host_copy_pipeline(struct ia_css_pipe *pipe, 341 unsigned int max_input_width, 342 struct ia_css_frame *out_frame); 343 344 static int 345 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe); 346 347 static int 348 create_host_capture_pipeline(struct ia_css_pipe *pipe); 349 350 static int 351 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe); 352 353 static int 354 create_host_acc_pipeline(struct ia_css_pipe *pipe); 355 356 static unsigned int 357 sh_css_get_sw_interrupt_value(unsigned int irq); 358 359 static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary( 360 const struct ia_css_pipe *pipe); 361 362 static struct ia_css_binary * 363 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe); 364 365 static struct ia_css_binary * 366 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe); 367 368 static void 369 sh_css_hmm_buffer_record_init(void); 370 371 static void 372 sh_css_hmm_buffer_record_uninit(void); 373 374 static void 375 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record); 376 377 static struct sh_css_hmm_buffer_record 378 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf, 379 enum ia_css_buffer_type type, 380 hrt_address kernel_ptr); 381 382 static struct sh_css_hmm_buffer_record 383 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr, 384 enum ia_css_buffer_type type); 385 386 void 387 ia_css_get_acc_configs( 388 struct ia_css_pipe *pipe, 389 struct ia_css_isp_config *config); 390 391 #if CONFIG_ON_FRAME_ENQUEUE() 392 static int set_config_on_frame_enqueue(struct ia_css_frame_info 393 *info, struct frame_data_wrapper *frame); 394 #endif 395 396 #ifdef USE_INPUT_SYSTEM_VERSION_2401 397 static unsigned int get_crop_lines_for_bayer_order(const struct 398 ia_css_stream_config *config); 399 static unsigned int get_crop_columns_for_bayer_order(const struct 400 ia_css_stream_config *config); 401 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe, 402 unsigned int *extra_row, unsigned int *extra_column); 403 static int 404 aspect_ratio_crop_init(struct ia_css_stream *curr_stream, 405 struct ia_css_pipe *pipes[], 406 bool *do_crop_status); 407 408 static bool 409 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe); 410 411 static int 412 aspect_ratio_crop(struct ia_css_pipe *curr_pipe, 413 struct ia_css_resolution *effective_res); 414 #endif 415 416 static void 417 sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe) 418 { 419 assert(pipe); 420 if (!pipe) { 421 IA_CSS_ERROR("NULL input parameter"); 422 return; 423 } 424 425 if (pipe->shading_table) 426 ia_css_shading_table_free(pipe->shading_table); 427 pipe->shading_table = NULL; 428 } 429 430 static enum ia_css_frame_format yuv420_copy_formats[] = { 431 IA_CSS_FRAME_FORMAT_NV12, 432 IA_CSS_FRAME_FORMAT_NV21, 433 IA_CSS_FRAME_FORMAT_YV12, 434 IA_CSS_FRAME_FORMAT_YUV420, 435 IA_CSS_FRAME_FORMAT_YUV420_16, 436 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8, 437 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8 438 }; 439 440 static enum ia_css_frame_format yuv422_copy_formats[] = { 441 IA_CSS_FRAME_FORMAT_NV12, 442 IA_CSS_FRAME_FORMAT_NV16, 443 IA_CSS_FRAME_FORMAT_NV21, 444 IA_CSS_FRAME_FORMAT_NV61, 445 IA_CSS_FRAME_FORMAT_YV12, 446 IA_CSS_FRAME_FORMAT_YV16, 447 IA_CSS_FRAME_FORMAT_YUV420, 448 IA_CSS_FRAME_FORMAT_YUV420_16, 449 IA_CSS_FRAME_FORMAT_YUV422, 450 IA_CSS_FRAME_FORMAT_YUV422_16, 451 IA_CSS_FRAME_FORMAT_UYVY, 452 IA_CSS_FRAME_FORMAT_YUYV 453 }; 454 455 /* Verify whether the selected output format is can be produced 456 * by the copy binary given the stream format. 457 * */ 458 static int 459 verify_copy_out_frame_format(struct ia_css_pipe *pipe) { 460 enum ia_css_frame_format out_fmt = pipe->output_info[0].format; 461 unsigned int i, found = 0; 462 463 assert(pipe); 464 assert(pipe->stream); 465 466 switch (pipe->stream->config.input_config.format) 467 { 468 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: 469 case ATOMISP_INPUT_FORMAT_YUV420_8: 470 for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++) 471 found = (out_fmt == yuv420_copy_formats[i]); 472 break; 473 case ATOMISP_INPUT_FORMAT_YUV420_10: 474 case ATOMISP_INPUT_FORMAT_YUV420_16: 475 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16); 476 break; 477 case ATOMISP_INPUT_FORMAT_YUV422_8: 478 for (i = 0; i < ARRAY_SIZE(yuv422_copy_formats) && !found; i++) 479 found = (out_fmt == yuv422_copy_formats[i]); 480 break; 481 case ATOMISP_INPUT_FORMAT_YUV422_10: 482 case ATOMISP_INPUT_FORMAT_YUV422_16: 483 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 || 484 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16); 485 break; 486 case ATOMISP_INPUT_FORMAT_RGB_444: 487 case ATOMISP_INPUT_FORMAT_RGB_555: 488 case ATOMISP_INPUT_FORMAT_RGB_565: 489 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 || 490 out_fmt == IA_CSS_FRAME_FORMAT_RGB565); 491 break; 492 case ATOMISP_INPUT_FORMAT_RGB_666: 493 case ATOMISP_INPUT_FORMAT_RGB_888: 494 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 || 495 out_fmt == IA_CSS_FRAME_FORMAT_YUV420); 496 break; 497 case ATOMISP_INPUT_FORMAT_RAW_6: 498 case ATOMISP_INPUT_FORMAT_RAW_7: 499 case ATOMISP_INPUT_FORMAT_RAW_8: 500 case ATOMISP_INPUT_FORMAT_RAW_10: 501 case ATOMISP_INPUT_FORMAT_RAW_12: 502 case ATOMISP_INPUT_FORMAT_RAW_14: 503 case ATOMISP_INPUT_FORMAT_RAW_16: 504 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) || 505 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED); 506 break; 507 case ATOMISP_INPUT_FORMAT_BINARY_8: 508 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8); 509 break; 510 default: 511 break; 512 } 513 if (!found) 514 return -EINVAL; 515 return 0; 516 } 517 518 unsigned int 519 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream) 520 { 521 int bpp = 0; 522 523 if (stream) 524 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format, 525 stream->config.pixels_per_clock == 2); 526 527 return bpp; 528 } 529 530 #define GP_ISEL_TPG_MODE 0x90058 531 532 #if defined(USE_INPUT_SYSTEM_VERSION_2) 533 static int 534 sh_css_config_input_network(struct ia_css_stream *stream) { 535 unsigned int fmt_type; 536 struct ia_css_pipe *pipe = stream->last_pipe; 537 struct ia_css_binary *binary = NULL; 538 int err = 0; 539 540 assert(stream); 541 assert(pipe); 542 543 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 544 "sh_css_config_input_network() enter:\n"); 545 546 if (pipe->pipeline.stages) 547 binary = pipe->pipeline.stages->binary; 548 549 err = ia_css_isys_convert_stream_format_to_mipi_format( 550 stream->config.input_config.format, 551 stream->csi_rx_config.comp, 552 &fmt_type); 553 if (err) 554 return err; 555 sh_css_sp_program_input_circuit(fmt_type, 556 stream->config.channel_id, 557 stream->config.mode); 558 559 if ((binary && (binary->online || stream->config.continuous)) || 560 pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 561 { 562 err = ia_css_ifmtr_configure(&stream->config, 563 binary); 564 if (err) 565 return err; 566 } 567 568 if (stream->config.mode == IA_CSS_INPUT_MODE_TPG || 569 stream->config.mode == IA_CSS_INPUT_MODE_PRBS) 570 { 571 unsigned int hblank_cycles = 100, 572 vblank_lines = 6, 573 width, 574 height, 575 vblank_cycles; 576 width = (stream->config.input_config.input_res.width) / (1 + 577 (stream->config.pixels_per_clock == 2)); 578 height = stream->config.input_config.input_res.height; 579 vblank_cycles = vblank_lines * (width + hblank_cycles); 580 sh_css_sp_configure_sync_gen(width, height, hblank_cycles, 581 vblank_cycles); 582 if (!IS_ISP2401) { 583 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) { 584 /* TODO: move define to proper file in tools */ 585 ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0); 586 } 587 } 588 } 589 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 590 "sh_css_config_input_network() leave:\n"); 591 return 0; 592 } 593 #elif defined(USE_INPUT_SYSTEM_VERSION_2401) 594 static unsigned int csi2_protocol_calculate_max_subpixels_per_line( 595 enum atomisp_input_format format, 596 unsigned int pixels_per_line) 597 { 598 unsigned int rval; 599 600 switch (format) { 601 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: 602 /* 603 * The frame format layout is shown below. 604 * 605 * Line 0: UYY0 UYY0 ... UYY0 606 * Line 1: VYY0 VYY0 ... VYY0 607 * Line 2: UYY0 UYY0 ... UYY0 608 * Line 3: VYY0 VYY0 ... VYY0 609 * ... 610 * Line (n-2): UYY0 UYY0 ... UYY0 611 * Line (n-1): VYY0 VYY0 ... VYY0 612 * 613 * In this frame format, the even-line is 614 * as wide as the odd-line. 615 * The 0 is introduced by the input system 616 * (mipi backend). 617 */ 618 rval = pixels_per_line * 2; 619 break; 620 case ATOMISP_INPUT_FORMAT_YUV420_8: 621 case ATOMISP_INPUT_FORMAT_YUV420_10: 622 case ATOMISP_INPUT_FORMAT_YUV420_16: 623 /* 624 * The frame format layout is shown below. 625 * 626 * Line 0: YYYY YYYY ... YYYY 627 * Line 1: UYVY UYVY ... UYVY UYVY 628 * Line 2: YYYY YYYY ... YYYY 629 * Line 3: UYVY UYVY ... UYVY UYVY 630 * ... 631 * Line (n-2): YYYY YYYY ... YYYY 632 * Line (n-1): UYVY UYVY ... UYVY UYVY 633 * 634 * In this frame format, the odd-line is twice 635 * wider than the even-line. 636 */ 637 rval = pixels_per_line * 2; 638 break; 639 case ATOMISP_INPUT_FORMAT_YUV422_8: 640 case ATOMISP_INPUT_FORMAT_YUV422_10: 641 case ATOMISP_INPUT_FORMAT_YUV422_16: 642 /* 643 * The frame format layout is shown below. 644 * 645 * Line 0: UYVY UYVY ... UYVY 646 * Line 1: UYVY UYVY ... UYVY 647 * Line 2: UYVY UYVY ... UYVY 648 * Line 3: UYVY UYVY ... UYVY 649 * ... 650 * Line (n-2): UYVY UYVY ... UYVY 651 * Line (n-1): UYVY UYVY ... UYVY 652 * 653 * In this frame format, the even-line is 654 * as wide as the odd-line. 655 */ 656 rval = pixels_per_line * 2; 657 break; 658 case ATOMISP_INPUT_FORMAT_RGB_444: 659 case ATOMISP_INPUT_FORMAT_RGB_555: 660 case ATOMISP_INPUT_FORMAT_RGB_565: 661 case ATOMISP_INPUT_FORMAT_RGB_666: 662 case ATOMISP_INPUT_FORMAT_RGB_888: 663 /* 664 * The frame format layout is shown below. 665 * 666 * Line 0: ABGR ABGR ... ABGR 667 * Line 1: ABGR ABGR ... ABGR 668 * Line 2: ABGR ABGR ... ABGR 669 * Line 3: ABGR ABGR ... ABGR 670 * ... 671 * Line (n-2): ABGR ABGR ... ABGR 672 * Line (n-1): ABGR ABGR ... ABGR 673 * 674 * In this frame format, the even-line is 675 * as wide as the odd-line. 676 */ 677 rval = pixels_per_line * 4; 678 break; 679 case ATOMISP_INPUT_FORMAT_RAW_6: 680 case ATOMISP_INPUT_FORMAT_RAW_7: 681 case ATOMISP_INPUT_FORMAT_RAW_8: 682 case ATOMISP_INPUT_FORMAT_RAW_10: 683 case ATOMISP_INPUT_FORMAT_RAW_12: 684 case ATOMISP_INPUT_FORMAT_RAW_14: 685 case ATOMISP_INPUT_FORMAT_RAW_16: 686 case ATOMISP_INPUT_FORMAT_BINARY_8: 687 case ATOMISP_INPUT_FORMAT_USER_DEF1: 688 case ATOMISP_INPUT_FORMAT_USER_DEF2: 689 case ATOMISP_INPUT_FORMAT_USER_DEF3: 690 case ATOMISP_INPUT_FORMAT_USER_DEF4: 691 case ATOMISP_INPUT_FORMAT_USER_DEF5: 692 case ATOMISP_INPUT_FORMAT_USER_DEF6: 693 case ATOMISP_INPUT_FORMAT_USER_DEF7: 694 case ATOMISP_INPUT_FORMAT_USER_DEF8: 695 /* 696 * The frame format layout is shown below. 697 * 698 * Line 0: Pixel Pixel ... Pixel 699 * Line 1: Pixel Pixel ... Pixel 700 * Line 2: Pixel Pixel ... Pixel 701 * Line 3: Pixel Pixel ... Pixel 702 * ... 703 * Line (n-2): Pixel Pixel ... Pixel 704 * Line (n-1): Pixel Pixel ... Pixel 705 * 706 * In this frame format, the even-line is 707 * as wide as the odd-line. 708 */ 709 rval = pixels_per_line; 710 break; 711 default: 712 rval = 0; 713 break; 714 } 715 716 return rval; 717 } 718 719 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id( 720 struct ia_css_stream_config *stream_cfg, 721 ia_css_isys_descr_t *isys_stream_descr) 722 { 723 bool rc; 724 725 rc = true; 726 switch (stream_cfg->mode) { 727 case IA_CSS_INPUT_MODE_TPG: 728 729 if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) { 730 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID; 731 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) { 732 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID; 733 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) { 734 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID; 735 } 736 737 break; 738 case IA_CSS_INPUT_MODE_PRBS: 739 740 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) { 741 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID; 742 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) { 743 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID; 744 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) { 745 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID; 746 } 747 748 break; 749 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: 750 751 if (stream_cfg->source.port.port == MIPI_PORT0_ID) { 752 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID; 753 } else if (stream_cfg->source.port.port == MIPI_PORT1_ID) { 754 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID; 755 } else if (stream_cfg->source.port.port == MIPI_PORT2_ID) { 756 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID; 757 } 758 759 break; 760 default: 761 rc = false; 762 break; 763 } 764 765 return rc; 766 } 767 768 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type( 769 struct ia_css_stream_config *stream_cfg, 770 ia_css_isys_descr_t *isys_stream_descr) 771 { 772 bool rc; 773 774 rc = true; 775 switch (stream_cfg->mode) { 776 case IA_CSS_INPUT_MODE_TPG: 777 778 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG; 779 780 break; 781 case IA_CSS_INPUT_MODE_PRBS: 782 783 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS; 784 785 break; 786 case IA_CSS_INPUT_MODE_SENSOR: 787 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: 788 789 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR; 790 break; 791 792 default: 793 rc = false; 794 break; 795 } 796 797 return rc; 798 } 799 800 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr( 801 struct ia_css_stream_config *stream_cfg, 802 ia_css_isys_descr_t *isys_stream_descr, 803 int isys_stream_idx) 804 { 805 bool rc; 806 807 rc = true; 808 switch (stream_cfg->mode) { 809 case IA_CSS_INPUT_MODE_TPG: 810 if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) { 811 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP; 812 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) { 813 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO; 814 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) { 815 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO; 816 } else { 817 rc = false; 818 } 819 820 /* 821 * TODO 822 * - Make "color_cfg" as part of "ia_css_tpg_config". 823 */ 824 isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51; 825 isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102; 826 isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255; 827 isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0; 828 isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100; 829 isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160; 830 831 isys_stream_descr->tpg_port_attr.mask_cfg.h_mask = 832 stream_cfg->source.tpg.x_mask; 833 isys_stream_descr->tpg_port_attr.mask_cfg.v_mask = 834 stream_cfg->source.tpg.y_mask; 835 isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask = 836 stream_cfg->source.tpg.xy_mask; 837 838 isys_stream_descr->tpg_port_attr.delta_cfg.h_delta = 839 stream_cfg->source.tpg.x_delta; 840 isys_stream_descr->tpg_port_attr.delta_cfg.v_delta = 841 stream_cfg->source.tpg.y_delta; 842 843 /* 844 * TODO 845 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config". 846 */ 847 isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100; 848 isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100; 849 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock = 850 stream_cfg->pixels_per_clock; 851 isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0); 852 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_line = 853 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width; 854 isys_stream_descr->tpg_port_attr.sync_gen_cfg.lines_per_frame = 855 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height; 856 857 break; 858 case IA_CSS_INPUT_MODE_PRBS: 859 860 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed; 861 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1; 862 863 /* 864 * TODO 865 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config". 866 */ 867 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100; 868 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100; 869 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock = 870 stream_cfg->pixels_per_clock; 871 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0); 872 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line = 873 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width; 874 isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame = 875 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height; 876 877 break; 878 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: { 879 int err; 880 unsigned int fmt_type; 881 882 err = ia_css_isys_convert_stream_format_to_mipi_format( 883 stream_cfg->isys_config[isys_stream_idx].format, 884 MIPI_PREDICTOR_NONE, 885 &fmt_type); 886 if (err) 887 rc = false; 888 889 isys_stream_descr->csi_port_attr.active_lanes = 890 stream_cfg->source.port.num_lanes; 891 isys_stream_descr->csi_port_attr.fmt_type = fmt_type; 892 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id; 893 #ifdef USE_INPUT_SYSTEM_VERSION_2401 894 isys_stream_descr->online = stream_cfg->online; 895 #endif 896 err |= ia_css_isys_convert_compressed_format( 897 &stream_cfg->source.port.compression, 898 isys_stream_descr); 899 if (err) 900 rc = false; 901 902 /* metadata */ 903 isys_stream_descr->metadata.enable = false; 904 if (stream_cfg->metadata_config.resolution.height > 0) { 905 err = ia_css_isys_convert_stream_format_to_mipi_format( 906 stream_cfg->metadata_config.data_type, 907 MIPI_PREDICTOR_NONE, 908 &fmt_type); 909 if (err) 910 rc = false; 911 isys_stream_descr->metadata.fmt_type = fmt_type; 912 isys_stream_descr->metadata.bits_per_pixel = 913 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true); 914 isys_stream_descr->metadata.pixels_per_line = 915 stream_cfg->metadata_config.resolution.width; 916 isys_stream_descr->metadata.lines_per_frame = 917 stream_cfg->metadata_config.resolution.height; 918 #ifdef USE_INPUT_SYSTEM_VERSION_2401 919 /* For new input system, number of str2mmio requests must be even. 920 * So we round up number of metadata lines to be even. */ 921 if (isys_stream_descr->metadata.lines_per_frame > 0) 922 isys_stream_descr->metadata.lines_per_frame += 923 (isys_stream_descr->metadata.lines_per_frame & 1); 924 #endif 925 isys_stream_descr->metadata.align_req_in_bytes = 926 ia_css_csi2_calculate_input_system_alignment( 927 stream_cfg->metadata_config.data_type); 928 isys_stream_descr->metadata.enable = true; 929 } 930 931 break; 932 } 933 default: 934 rc = false; 935 break; 936 } 937 938 return rc; 939 } 940 941 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution( 942 struct ia_css_stream_config *stream_cfg, 943 ia_css_isys_descr_t *isys_stream_descr, 944 int isys_stream_idx) 945 { 946 unsigned int bits_per_subpixel; 947 unsigned int max_subpixels_per_line; 948 unsigned int lines_per_frame; 949 unsigned int align_req_in_bytes; 950 enum atomisp_input_format fmt_type; 951 952 fmt_type = stream_cfg->isys_config[isys_stream_idx].format; 953 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR || 954 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) && 955 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) { 956 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == 957 UNCOMPRESSED_BITS_PER_PIXEL_10) { 958 fmt_type = ATOMISP_INPUT_FORMAT_RAW_10; 959 } else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == 960 UNCOMPRESSED_BITS_PER_PIXEL_12) { 961 fmt_type = ATOMISP_INPUT_FORMAT_RAW_12; 962 } else 963 return false; 964 } 965 966 bits_per_subpixel = 967 sh_css_stream_format_2_bits_per_subpixel(fmt_type); 968 if (bits_per_subpixel == 0) 969 return false; 970 971 max_subpixels_per_line = 972 csi2_protocol_calculate_max_subpixels_per_line(fmt_type, 973 stream_cfg->isys_config[isys_stream_idx].input_res.width); 974 if (max_subpixels_per_line == 0) 975 return false; 976 977 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height; 978 if (lines_per_frame == 0) 979 return false; 980 981 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type); 982 983 /* HW needs subpixel info for their settings */ 984 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel; 985 isys_stream_descr->input_port_resolution.pixels_per_line = 986 max_subpixels_per_line; 987 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame; 988 isys_stream_descr->input_port_resolution.align_req_in_bytes = 989 align_req_in_bytes; 990 991 return true; 992 } 993 994 static bool sh_css_translate_stream_cfg_to_isys_stream_descr( 995 struct ia_css_stream_config *stream_cfg, 996 bool early_polling, 997 ia_css_isys_descr_t *isys_stream_descr, 998 int isys_stream_idx) 999 { 1000 bool rc; 1001 1002 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 1003 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n"); 1004 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg, 1005 isys_stream_descr); 1006 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg, 1007 isys_stream_descr); 1008 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg, 1009 isys_stream_descr, isys_stream_idx); 1010 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution( 1011 stream_cfg, isys_stream_descr, isys_stream_idx); 1012 1013 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels; 1014 isys_stream_descr->linked_isys_stream_id = (int8_t) 1015 stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id; 1016 /* 1017 * Early polling is required for timestamp accuracy in certain case. 1018 * The ISYS HW polling is started on 1019 * ia_css_isys_stream_capture_indication() instead of 1020 * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of 1021 * capture takes longer than getting an ISYS frame 1022 * 1023 * Only 2401 relevant ?? 1024 */ 1025 #if 0 // FIXME: NOT USED on Yocto Aero 1026 isys_stream_descr->polling_mode 1027 = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST 1028 : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME; 1029 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 1030 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n"); 1031 #endif 1032 1033 return rc; 1034 } 1035 1036 static bool sh_css_translate_binary_info_to_input_system_output_port_attr( 1037 struct ia_css_binary *binary, 1038 ia_css_isys_descr_t *isys_stream_descr) 1039 { 1040 if (!binary) 1041 return false; 1042 1043 isys_stream_descr->output_port_attr.left_padding = binary->left_padding; 1044 isys_stream_descr->output_port_attr.max_isp_input_width = 1045 binary->info->sp.input.max_width; 1046 1047 return true; 1048 } 1049 1050 static int 1051 sh_css_config_input_network(struct ia_css_stream *stream) { 1052 bool rc; 1053 ia_css_isys_descr_t isys_stream_descr; 1054 unsigned int sp_thread_id; 1055 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal; 1056 struct ia_css_pipe *pipe = NULL; 1057 struct ia_css_binary *binary = NULL; 1058 int i; 1059 u32 isys_stream_id; 1060 bool early_polling = false; 1061 1062 assert(stream); 1063 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 1064 "sh_css_config_input_network() enter 0x%p:\n", stream); 1065 1066 if (stream->config.continuous == true) 1067 { 1068 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { 1069 pipe = stream->last_pipe; 1070 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) { 1071 pipe = stream->last_pipe; 1072 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) { 1073 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe; 1074 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) { 1075 pipe = stream->last_pipe->pipe_settings.video.copy_pipe; 1076 } 1077 } else 1078 { 1079 pipe = stream->last_pipe; 1080 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { 1081 /* 1082 * We need to poll the ISYS HW in capture_indication itself 1083 * for "non-continuous" capture usecase for getting accurate 1084 * isys frame capture timestamps. 1085 * This is because the capturepipe propcessing takes longer 1086 * to execute than the input system frame capture. 1087 * 2401 specific 1088 */ 1089 early_polling = true; 1090 } 1091 } 1092 1093 assert(pipe); 1094 if (!pipe) 1095 return -EINVAL; 1096 1097 if (pipe->pipeline.stages) 1098 if (pipe->pipeline.stages->binary) 1099 binary = pipe->pipeline.stages->binary; 1100 1101 if (binary) 1102 { 1103 /* this was being done in ifmtr in 2400. 1104 * online and cont bypass the init_in_frameinfo_memory_defaults 1105 * so need to do it here 1106 */ 1107 ia_css_get_crop_offsets(pipe, &binary->in_frame_info); 1108 } 1109 1110 /* get the SP thread id */ 1111 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id); 1112 if (!rc) 1113 return -EINVAL; 1114 /* get the target input terminal */ 1115 sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input; 1116 1117 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) 1118 { 1119 /* initialization */ 1120 memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t)); 1121 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0; 1122 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0; 1123 1124 if (!stream->config.isys_config[i].valid) 1125 continue; 1126 1127 /* translate the stream configuration to the Input System (2401) configuration */ 1128 rc = sh_css_translate_stream_cfg_to_isys_stream_descr( 1129 &stream->config, 1130 early_polling, 1131 &(isys_stream_descr), i); 1132 1133 if (stream->config.online) { 1134 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr( 1135 binary, 1136 &(isys_stream_descr)); 1137 } 1138 1139 if (!rc) 1140 return -EINVAL; 1141 1142 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i); 1143 1144 /* create the virtual Input System (2401) */ 1145 rc = ia_css_isys_stream_create( 1146 &(isys_stream_descr), 1147 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i], 1148 isys_stream_id); 1149 if (!rc) 1150 return -EINVAL; 1151 1152 /* calculate the configuration of the virtual Input System (2401) */ 1153 rc = ia_css_isys_stream_calculate_cfg( 1154 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i], 1155 &(isys_stream_descr), 1156 &sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]); 1157 if (!rc) { 1158 ia_css_isys_stream_destroy( 1159 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]); 1160 return -EINVAL; 1161 } 1162 } 1163 1164 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 1165 "sh_css_config_input_network() leave:\n"); 1166 1167 return 0; 1168 } 1169 1170 static inline struct ia_css_pipe *stream_get_last_pipe( 1171 struct ia_css_stream *stream) 1172 { 1173 struct ia_css_pipe *last_pipe = NULL; 1174 1175 if (stream) 1176 last_pipe = stream->last_pipe; 1177 1178 return last_pipe; 1179 } 1180 1181 static inline struct ia_css_pipe *stream_get_copy_pipe( 1182 struct ia_css_stream *stream) 1183 { 1184 struct ia_css_pipe *copy_pipe = NULL; 1185 struct ia_css_pipe *last_pipe = NULL; 1186 enum ia_css_pipe_id pipe_id; 1187 1188 last_pipe = stream_get_last_pipe(stream); 1189 1190 if ((stream) && 1191 (last_pipe) && 1192 (stream->config.continuous)) { 1193 pipe_id = last_pipe->mode; 1194 switch (pipe_id) { 1195 case IA_CSS_PIPE_ID_PREVIEW: 1196 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe; 1197 break; 1198 case IA_CSS_PIPE_ID_VIDEO: 1199 copy_pipe = last_pipe->pipe_settings.video.copy_pipe; 1200 break; 1201 default: 1202 copy_pipe = NULL; 1203 break; 1204 } 1205 } 1206 1207 return copy_pipe; 1208 } 1209 1210 static inline struct ia_css_pipe *stream_get_target_pipe( 1211 struct ia_css_stream *stream) 1212 { 1213 struct ia_css_pipe *target_pipe; 1214 1215 /* get the pipe that consumes the stream */ 1216 if (stream->config.continuous) { 1217 target_pipe = stream_get_copy_pipe(stream); 1218 } else { 1219 target_pipe = stream_get_last_pipe(stream); 1220 } 1221 1222 return target_pipe; 1223 } 1224 1225 static int stream_csi_rx_helper( 1226 struct ia_css_stream *stream, 1227 int (*func)(enum mipi_port_id, uint32_t)) 1228 { 1229 int retval = -EINVAL; 1230 u32 sp_thread_id, stream_id; 1231 bool rc; 1232 struct ia_css_pipe *target_pipe = NULL; 1233 1234 if ((!stream) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)) 1235 goto exit; 1236 1237 target_pipe = stream_get_target_pipe(stream); 1238 1239 if (!target_pipe) 1240 goto exit; 1241 1242 rc = ia_css_pipeline_get_sp_thread_id( 1243 ia_css_pipe_get_pipe_num(target_pipe), 1244 &sp_thread_id); 1245 1246 if (!rc) 1247 goto exit; 1248 1249 /* (un)register all valid "virtual isys streams" within the ia_css_stream */ 1250 stream_id = 0; 1251 do { 1252 if (stream->config.isys_config[stream_id].valid) { 1253 u32 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id); 1254 1255 retval = func(stream->config.source.port.port, isys_stream_id); 1256 } 1257 stream_id++; 1258 } while ((retval == 0) && 1259 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)); 1260 1261 exit: 1262 return retval; 1263 } 1264 1265 static inline int stream_register_with_csi_rx( 1266 struct ia_css_stream *stream) 1267 { 1268 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream); 1269 } 1270 1271 static inline int stream_unregister_with_csi_rx( 1272 struct ia_css_stream *stream) 1273 { 1274 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream); 1275 } 1276 #endif 1277 1278 #if WITH_PC_MONITORING 1279 static struct task_struct *my_kthread; /* Handle for the monitoring thread */ 1280 static int sh_binary_running; /* Enable sampling in the thread */ 1281 1282 static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist) 1283 { 1284 unsigned int i; 1285 unsigned int cnt_run = 0; 1286 unsigned int cnt_stall = 0; 1287 1288 if (!hist) 1289 return; 1290 1291 sh_css_print("%s histogram length = %d\n", core_name, hist->length); 1292 sh_css_print("%s PC\turn\tstall\n", core_name); 1293 1294 for (i = 0; i < hist->length; i++) { 1295 if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i])) 1296 continue; 1297 sh_css_print("%s %d\t%d\t%d\n", 1298 core_name, i, hist->run[i], hist->stall[i]); 1299 cnt_run += hist->run[i]; 1300 cnt_stall += hist->stall[i]; 1301 } 1302 1303 sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, hist->length = %d\n", 1304 core_name, cnt_run, cnt_stall, hist->length); 1305 } 1306 1307 static void print_pc_histogram(void) 1308 { 1309 struct ia_css_binary_metrics *metrics; 1310 1311 for (metrics = sh_css_metrics.binary_metrics; 1312 metrics; 1313 metrics = metrics->next) { 1314 if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW || 1315 metrics->mode == IA_CSS_BINARY_MODE_VF_PP) { 1316 sh_css_print("pc_histogram for binary %d is SKIPPED\n", 1317 metrics->id); 1318 continue; 1319 } 1320 1321 sh_css_print(" pc_histogram for binary %d\n", metrics->id); 1322 print_pc_histo(" ISP", &metrics->isp_histogram); 1323 print_pc_histo(" SP", &metrics->sp_histogram); 1324 sh_css_print("print_pc_histogram() done for binary->id = %d, done.\n", 1325 metrics->id); 1326 } 1327 1328 sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n"); 1329 } 1330 1331 static int pc_monitoring(void *data) 1332 { 1333 int i = 0; 1334 1335 (void)data; 1336 while (true) { 1337 if (sh_binary_running) { 1338 sh_css_metrics_sample_pcs(); 1339 #if MULTIPLE_SAMPLES 1340 for (i = 0; i < NOF_SAMPLES; i++) 1341 sh_css_metrics_sample_pcs(); 1342 #endif 1343 } 1344 usleep_range(10, 50); 1345 } 1346 return 0; 1347 } 1348 1349 static void spying_thread_create(void) 1350 { 1351 my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor"); 1352 sh_css_metrics_enable_pc_histogram(1); 1353 } 1354 1355 static void input_frame_info(struct ia_css_frame_info frame_info) 1356 { 1357 sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, frame->info.res.height = %d, format = %d\n", 1358 frame_info.res.width, frame_info.res.height, frame_info.format); 1359 } 1360 #endif /* WITH_PC_MONITORING */ 1361 1362 static void 1363 start_binary(struct ia_css_pipe *pipe, 1364 struct ia_css_binary *binary) 1365 { 1366 struct ia_css_stream *stream; 1367 1368 assert(pipe); 1369 /* Acceleration uses firmware, the binary thus can be NULL */ 1370 /* assert(binary != NULL); */ 1371 1372 (void)binary; 1373 1374 stream = pipe->stream; 1375 1376 if (binary) 1377 sh_css_metrics_start_binary(&binary->metrics); 1378 1379 #if WITH_PC_MONITORING 1380 sh_css_print("PC_MONITORING: %s() -- binary id = %d , enable_dvs_envelope = %d\n", 1381 __func__, binary->info->sp.id, 1382 binary->info->sp.enable.dvs_envelope); 1383 input_frame_info(binary->in_frame_info); 1384 1385 if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO) 1386 sh_binary_running = true; 1387 #endif 1388 1389 #if !defined(USE_INPUT_SYSTEM_VERSION_2401) 1390 if (stream->reconfigure_css_rx) { 1391 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, 1392 pipe->stream->config.mode); 1393 stream->reconfigure_css_rx = false; 1394 } 1395 #endif 1396 } 1397 1398 /* start the copy function on the SP */ 1399 static int 1400 start_copy_on_sp(struct ia_css_pipe *pipe, 1401 struct ia_css_frame *out_frame) { 1402 (void)out_frame; 1403 assert(pipe); 1404 assert(pipe->stream); 1405 1406 if ((!pipe) || (!pipe->stream)) 1407 return -EINVAL; 1408 1409 #if !defined(USE_INPUT_SYSTEM_VERSION_2401) 1410 if (pipe->stream->reconfigure_css_rx) 1411 ia_css_isys_rx_disable(); 1412 #endif 1413 1414 if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8) 1415 return -EINVAL; 1416 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2); 1417 1418 #if !defined(USE_INPUT_SYSTEM_VERSION_2401) 1419 if (pipe->stream->reconfigure_css_rx) 1420 { 1421 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, 1422 pipe->stream->config.mode); 1423 pipe->stream->reconfigure_css_rx = false; 1424 } 1425 #endif 1426 1427 return 0; 1428 } 1429 1430 void sh_css_binary_args_reset(struct sh_css_binary_args *args) 1431 { 1432 unsigned int i; 1433 1434 for (i = 0; i < NUM_TNR_FRAMES; i++) 1435 args->tnr_frames[i] = NULL; 1436 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++) 1437 args->delay_frames[i] = NULL; 1438 args->in_frame = NULL; 1439 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) 1440 args->out_frame[i] = NULL; 1441 args->out_vf_frame = NULL; 1442 args->copy_vf = false; 1443 args->copy_output = true; 1444 args->vf_downscale_log2 = 0; 1445 } 1446 1447 static void start_pipe( 1448 struct ia_css_pipe *me, 1449 enum sh_css_pipe_config_override copy_ovrd, 1450 enum ia_css_input_mode input_mode) 1451 { 1452 const struct ia_css_coordinate *coord = NULL; 1453 const struct ia_css_isp_parameters *params = NULL; 1454 1455 1456 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d", 1457 me, copy_ovrd, input_mode); 1458 1459 assert(me); /* all callers are in this file and call with non null argument */ 1460 1461 if (!IS_ISP2401) { 1462 coord = &me->config.internal_frame_origin_bqs_on_sctbl; 1463 params = me->stream->isp_params_configs; 1464 } 1465 1466 sh_css_sp_init_pipeline(&me->pipeline, 1467 me->mode, 1468 (uint8_t)ia_css_pipe_get_pipe_num(me), 1469 me->config.default_capture_config.enable_xnr != 0, 1470 me->stream->config.pixels_per_clock == 2, 1471 me->stream->config.continuous, 1472 false, 1473 me->required_bds_factor, 1474 copy_ovrd, 1475 input_mode, 1476 &me->stream->config.metadata_config, 1477 &me->stream->info.metadata_info 1478 , (input_mode == IA_CSS_INPUT_MODE_MEMORY) ? 1479 (enum mipi_port_id)0 : 1480 me->stream->config.source.port.port, 1481 coord, 1482 params); 1483 1484 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) { 1485 struct ia_css_pipeline_stage *stage; 1486 1487 stage = me->pipeline.stages; 1488 if (stage) { 1489 me->pipeline.current_stage = stage; 1490 start_binary(me, stage->binary); 1491 } 1492 } 1493 IA_CSS_LEAVE_PRIVATE("void"); 1494 } 1495 1496 void 1497 sh_css_invalidate_shading_tables(struct ia_css_stream *stream) 1498 { 1499 int i; 1500 1501 assert(stream); 1502 1503 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1504 "sh_css_invalidate_shading_tables() enter:\n"); 1505 1506 for (i = 0; i < stream->num_pipes; i++) { 1507 assert(stream->pipes[i]); 1508 sh_css_pipe_free_shading_table(stream->pipes[i]); 1509 } 1510 1511 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1512 "sh_css_invalidate_shading_tables() leave: return_void\n"); 1513 } 1514 1515 static void 1516 enable_interrupts(enum ia_css_irq_type irq_type) 1517 { 1518 #ifdef USE_INPUT_SYSTEM_VERSION_2 1519 enum mipi_port_id port; 1520 #endif 1521 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE; 1522 1523 IA_CSS_ENTER_PRIVATE(""); 1524 /* Enable IRQ on the SP which signals that SP goes to idle 1525 * (aka ready state) */ 1526 cnd_sp_irq_enable(SP0_ID, true); 1527 /* Set the IRQ device 0 to either level or pulse */ 1528 irq_enable_pulse(IRQ0_ID, enable_pulse); 1529 1530 cnd_virq_enable_channel(virq_sp, true); 1531 1532 /* Enable SW interrupt 0, this is used to signal ISYS events */ 1533 cnd_virq_enable_channel( 1534 (enum virq_id)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET), 1535 true); 1536 /* Enable SW interrupt 1, this is used to signal PSYS events */ 1537 cnd_virq_enable_channel( 1538 (enum virq_id)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET), 1539 true); 1540 1541 #ifdef USE_INPUT_SYSTEM_VERSION_2 1542 for (port = 0; port < N_MIPI_PORT_ID; port++) 1543 ia_css_isys_rx_enable_all_interrupts(port); 1544 #endif 1545 1546 IA_CSS_LEAVE_PRIVATE(""); 1547 } 1548 1549 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw, 1550 const char *program, 1551 ia_css_spctrl_cfg *spctrl_cfg) 1552 { 1553 if ((!fw) || (!spctrl_cfg)) 1554 return false; 1555 spctrl_cfg->sp_entry = 0; 1556 spctrl_cfg->program_name = (char *)(program); 1557 1558 spctrl_cfg->ddr_data_offset = fw->blob.data_source; 1559 spctrl_cfg->dmem_data_addr = fw->blob.data_target; 1560 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target; 1561 spctrl_cfg->data_size = fw->blob.data_size; 1562 spctrl_cfg->bss_size = fw->blob.bss_size; 1563 1564 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data; 1565 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state; 1566 1567 spctrl_cfg->code_size = fw->blob.size; 1568 spctrl_cfg->code = fw->blob.code; 1569 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */ 1570 1571 return true; 1572 } 1573 1574 void 1575 ia_css_unload_firmware(void) 1576 { 1577 if (sh_css_num_binaries) { 1578 /* we have already loaded before so get rid of the old stuff */ 1579 ia_css_binary_uninit(); 1580 sh_css_unload_firmware(); 1581 } 1582 fw_explicitly_loaded = false; 1583 } 1584 1585 static void 1586 ia_css_reset_defaults(struct sh_css *css) 1587 { 1588 struct sh_css default_css; 1589 1590 /* Reset everything to zero */ 1591 memset(&default_css, 0, sizeof(default_css)); 1592 1593 /* Initialize the non zero values*/ 1594 default_css.check_system_idle = true; 1595 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES; 1596 1597 /* All should be 0: but memset does it already. 1598 * default_css.num_mipi_frames[N_CSI_PORTS] = 0; 1599 */ 1600 1601 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE; 1602 1603 /*Set the defaults to the output */ 1604 *css = default_css; 1605 } 1606 1607 int 1608 ia_css_load_firmware(struct device *dev, const struct ia_css_env *env, 1609 const struct ia_css_fw *fw) { 1610 int err; 1611 1612 if (!env) 1613 return -EINVAL; 1614 if (!fw) 1615 return -EINVAL; 1616 1617 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n"); 1618 1619 /* make sure we initialize my_css */ 1620 if (my_css.flush != env->cpu_mem_env.flush) 1621 { 1622 ia_css_reset_defaults(&my_css); 1623 my_css.flush = env->cpu_mem_env.flush; 1624 } 1625 1626 ia_css_unload_firmware(); /* in case we are called twice */ 1627 err = sh_css_load_firmware(dev, fw->data, fw->bytes); 1628 if (!err) 1629 { 1630 err = ia_css_binary_init_infos(); 1631 if (!err) 1632 fw_explicitly_loaded = true; 1633 } 1634 1635 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave\n"); 1636 return err; 1637 } 1638 1639 int 1640 ia_css_init(struct device *dev, const struct ia_css_env *env, 1641 const struct ia_css_fw *fw, 1642 u32 mmu_l1_base, 1643 enum ia_css_irq_type irq_type) { 1644 int err; 1645 ia_css_spctrl_cfg spctrl_cfg; 1646 1647 void (*flush_func)(struct ia_css_acc_fw *fw); 1648 hrt_data select, enable; 1649 1650 /* 1651 * The C99 standard does not specify the exact object representation of structs; 1652 * the representation is compiler dependent. 1653 * 1654 * The structs that are communicated between host and SP/ISP should have the 1655 * exact same object representation. The compiler that is used to compile the 1656 * firmware is hivecc. 1657 * 1658 * To check if a different compiler, used to compile a host application, uses 1659 * another object representation, macros are defined specifying the size of 1660 * the structs as expected by the firmware. 1661 * 1662 * A host application shall verify that a sizeof( ) of the struct is equal to 1663 * the SIZE_OF_XXX macro of the corresponding struct. If they are not 1664 * equal, functionality will break. 1665 */ 1666 /* Check struct sh_css_ddr_address_map */ 1667 COMPILATION_ERROR_IF(sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT); 1668 /* Check struct host_sp_queues */ 1669 COMPILATION_ERROR_IF(sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT); 1670 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT); 1671 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT); 1672 1673 /* Check struct host_sp_communication */ 1674 COMPILATION_ERROR_IF(sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT); 1675 COMPILATION_ERROR_IF(sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT); 1676 1677 /* Check struct sh_css_hmm_buffer */ 1678 COMPILATION_ERROR_IF(sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT); 1679 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT); 1680 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT); 1681 COMPILATION_ERROR_IF(sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT); 1682 1683 /* Check struct ia_css_init_dmem_cfg */ 1684 COMPILATION_ERROR_IF(sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT); 1685 1686 if (!fw && !fw_explicitly_loaded) 1687 return -EINVAL; 1688 if (!env) 1689 return -EINVAL; 1690 1691 sh_css_printf = env->print_env.debug_print; 1692 1693 IA_CSS_ENTER("void"); 1694 1695 flush_func = env->cpu_mem_env.flush; 1696 1697 pipe_global_init(); 1698 ia_css_pipeline_init(); 1699 ia_css_queue_map_init(); 1700 1701 ia_css_device_access_init(&env->hw_access_env); 1702 1703 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select) 1704 & (~GPIO_FLASH_PIN_MASK); 1705 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e) 1706 | GPIO_FLASH_PIN_MASK; 1707 sh_css_mmu_set_page_table_base_index(mmu_l1_base); 1708 1709 my_css_save.mmu_base = mmu_l1_base; 1710 1711 ia_css_reset_defaults(&my_css); 1712 1713 my_css_save.driver_env = *env; 1714 my_css.flush = flush_func; 1715 1716 err = ia_css_rmgr_init(); 1717 if (err) 1718 { 1719 IA_CSS_LEAVE_ERR(err); 1720 return err; 1721 } 1722 1723 IA_CSS_LOG("init: %d", my_css_save_initialized); 1724 1725 if (!my_css_save_initialized) 1726 { 1727 my_css_save_initialized = true; 1728 my_css_save.mode = sh_css_mode_working; 1729 memset(my_css_save.stream_seeds, 0, 1730 sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS); 1731 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode); 1732 } 1733 1734 mipi_init(); 1735 1736 #ifndef ISP2401 1737 /* In case this has been programmed already, update internal 1738 data structure ... DEPRECATED */ 1739 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID); 1740 1741 #endif 1742 my_css.irq_type = irq_type; 1743 1744 my_css_save.irq_type = irq_type; 1745 1746 enable_interrupts(my_css.irq_type); 1747 1748 /* configure GPIO to output mode */ 1749 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select); 1750 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable); 1751 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0); 1752 1753 err = ia_css_refcount_init(REFCOUNT_SIZE); 1754 if (err) 1755 { 1756 IA_CSS_LEAVE_ERR(err); 1757 return err; 1758 } 1759 err = sh_css_params_init(); 1760 if (err) 1761 { 1762 IA_CSS_LEAVE_ERR(err); 1763 return err; 1764 } 1765 if (fw) 1766 { 1767 ia_css_unload_firmware(); /* in case we already had firmware loaded */ 1768 err = sh_css_load_firmware(dev, fw->data, fw->bytes); 1769 if (err) { 1770 IA_CSS_LEAVE_ERR(err); 1771 return err; 1772 } 1773 err = ia_css_binary_init_infos(); 1774 if (err) { 1775 IA_CSS_LEAVE_ERR(err); 1776 return err; 1777 } 1778 fw_explicitly_loaded = false; 1779 #ifndef ISP2401 1780 my_css_save.loaded_fw = (struct ia_css_fw *)fw; 1781 #endif 1782 } 1783 if (!sh_css_setup_spctrl_config(&sh_css_sp_fw, SP_PROG_NAME, &spctrl_cfg)) 1784 return -EINVAL; 1785 1786 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg); 1787 if (err) 1788 { 1789 IA_CSS_LEAVE_ERR(err); 1790 return err; 1791 } 1792 1793 #if WITH_PC_MONITORING 1794 if (!thread_alive) 1795 { 1796 thread_alive++; 1797 sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n", 1798 __func__); 1799 spying_thread_create(); 1800 } 1801 #endif 1802 if (!sh_css_hrt_system_is_idle()) 1803 { 1804 IA_CSS_LEAVE_ERR(-EBUSY); 1805 return -EBUSY; 1806 } 1807 /* can be called here, queuing works, but: 1808 - when sp is started later, it will wipe queued items 1809 so for now we leave it for later and make sure 1810 updates are not called to frequently. 1811 sh_css_init_buffer_queues(); 1812 */ 1813 1814 #if defined(HAS_INPUT_SYSTEM_VERSION_2401) 1815 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1); 1816 #endif 1817 1818 1819 if (!IS_ISP2401) 1820 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, 1821 ISP2400_DMA_MAX_BURST_LENGTH); 1822 else 1823 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, 1824 ISP2401_DMA_MAX_BURST_LENGTH); 1825 1826 if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR) 1827 err = -EINVAL; 1828 1829 sh_css_params_map_and_store_default_gdc_lut(); 1830 1831 IA_CSS_LEAVE_ERR(err); 1832 return err; 1833 } 1834 1835 int 1836 ia_css_enable_isys_event_queue(bool enable) { 1837 if (sh_css_sp_is_running()) 1838 return -EBUSY; 1839 sh_css_sp_enable_isys_event_queue(enable); 1840 return 0; 1841 } 1842 1843 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */ 1844 void 1845 sh_css_flush(struct ia_css_acc_fw *fw) 1846 { 1847 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n"); 1848 if ((fw) && (my_css.flush)) 1849 my_css.flush(fw); 1850 } 1851 1852 /* Mapping sp threads. Currently, this is done when a stream is created and 1853 * pipelines are ready to be converted to sp pipelines. Be careful if you are 1854 * doing it from stream_create since we could run out of sp threads due to 1855 * allocation on inactive pipelines. */ 1856 static int 1857 map_sp_threads(struct ia_css_stream *stream, bool map) { 1858 struct ia_css_pipe *main_pipe = NULL; 1859 struct ia_css_pipe *copy_pipe = NULL; 1860 struct ia_css_pipe *capture_pipe = NULL; 1861 struct ia_css_pipe *acc_pipe = NULL; 1862 int err = 0; 1863 enum ia_css_pipe_id pipe_id; 1864 1865 assert(stream); 1866 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s", 1867 stream, map ? "true" : "false"); 1868 1869 if (!stream) 1870 { 1871 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 1872 return -EINVAL; 1873 } 1874 1875 main_pipe = stream->last_pipe; 1876 pipe_id = main_pipe->mode; 1877 1878 ia_css_pipeline_map(main_pipe->pipe_num, map); 1879 1880 switch (pipe_id) 1881 { 1882 case IA_CSS_PIPE_ID_PREVIEW: 1883 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 1884 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; 1885 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe; 1886 break; 1887 1888 case IA_CSS_PIPE_ID_VIDEO: 1889 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 1890 capture_pipe = main_pipe->pipe_settings.video.capture_pipe; 1891 break; 1892 1893 case IA_CSS_PIPE_ID_CAPTURE: 1894 case IA_CSS_PIPE_ID_ACC: 1895 default: 1896 break; 1897 } 1898 1899 if (acc_pipe) 1900 { 1901 ia_css_pipeline_map(acc_pipe->pipe_num, map); 1902 } 1903 1904 if (capture_pipe) 1905 { 1906 ia_css_pipeline_map(capture_pipe->pipe_num, map); 1907 } 1908 1909 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */ 1910 if (copy_pipe) 1911 { 1912 ia_css_pipeline_map(copy_pipe->pipe_num, map); 1913 } 1914 /* DH regular multi pipe - not continuous mode: map the next pipes too */ 1915 if (!stream->config.continuous) 1916 { 1917 int i; 1918 1919 for (i = 1; i < stream->num_pipes; i++) 1920 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map); 1921 } 1922 1923 IA_CSS_LEAVE_ERR_PRIVATE(err); 1924 return err; 1925 } 1926 1927 /* creates a host pipeline skeleton for all pipes in a stream. Called during 1928 * stream_create. */ 1929 static int 1930 create_host_pipeline_structure(struct ia_css_stream *stream) { 1931 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL; 1932 struct ia_css_pipe *acc_pipe = NULL; 1933 enum ia_css_pipe_id pipe_id; 1934 struct ia_css_pipe *main_pipe = NULL; 1935 int err = 0; 1936 unsigned int copy_pipe_delay = 0, 1937 capture_pipe_delay = 0; 1938 1939 assert(stream); 1940 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 1941 1942 if (!stream) 1943 { 1944 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 1945 return -EINVAL; 1946 } 1947 1948 main_pipe = stream->last_pipe; 1949 assert(main_pipe); 1950 if (!main_pipe) 1951 { 1952 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 1953 return -EINVAL; 1954 } 1955 1956 pipe_id = main_pipe->mode; 1957 1958 switch (pipe_id) 1959 { 1960 case IA_CSS_PIPE_ID_PREVIEW: 1961 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 1962 copy_pipe_delay = main_pipe->dvs_frame_delay; 1963 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; 1964 capture_pipe_delay = IA_CSS_FRAME_DELAY_0; 1965 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe; 1966 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, 1967 main_pipe->pipe_num, main_pipe->dvs_frame_delay); 1968 break; 1969 1970 case IA_CSS_PIPE_ID_VIDEO: 1971 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 1972 copy_pipe_delay = main_pipe->dvs_frame_delay; 1973 capture_pipe = main_pipe->pipe_settings.video.capture_pipe; 1974 capture_pipe_delay = IA_CSS_FRAME_DELAY_0; 1975 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, 1976 main_pipe->pipe_num, main_pipe->dvs_frame_delay); 1977 break; 1978 1979 case IA_CSS_PIPE_ID_CAPTURE: 1980 capture_pipe = main_pipe; 1981 capture_pipe_delay = main_pipe->dvs_frame_delay; 1982 break; 1983 1984 case IA_CSS_PIPE_ID_YUVPP: 1985 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, 1986 main_pipe->pipe_num, main_pipe->dvs_frame_delay); 1987 break; 1988 1989 case IA_CSS_PIPE_ID_ACC: 1990 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, 1991 main_pipe->pipe_num, main_pipe->dvs_frame_delay); 1992 break; 1993 1994 default: 1995 err = -EINVAL; 1996 } 1997 1998 if (!(err) && copy_pipe) 1999 { 2000 err = ia_css_pipeline_create(©_pipe->pipeline, 2001 copy_pipe->mode, 2002 copy_pipe->pipe_num, 2003 copy_pipe_delay); 2004 } 2005 2006 if (!(err) && capture_pipe) 2007 { 2008 err = ia_css_pipeline_create(&capture_pipe->pipeline, 2009 capture_pipe->mode, 2010 capture_pipe->pipe_num, 2011 capture_pipe_delay); 2012 } 2013 2014 if (!(err) && acc_pipe) 2015 { 2016 err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode, 2017 acc_pipe->pipe_num, main_pipe->dvs_frame_delay); 2018 } 2019 2020 /* DH regular multi pipe - not continuous mode: create the next pipelines too */ 2021 if (!stream->config.continuous) 2022 { 2023 int i; 2024 2025 for (i = 1; i < stream->num_pipes && 0 == err; i++) { 2026 main_pipe = stream->pipes[i]; 2027 err = ia_css_pipeline_create(&main_pipe->pipeline, 2028 main_pipe->mode, 2029 main_pipe->pipe_num, 2030 main_pipe->dvs_frame_delay); 2031 } 2032 } 2033 2034 IA_CSS_LEAVE_ERR_PRIVATE(err); 2035 return err; 2036 } 2037 2038 /* creates a host pipeline for all pipes in a stream. Called during 2039 * stream_start. */ 2040 static int 2041 create_host_pipeline(struct ia_css_stream *stream) { 2042 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL; 2043 struct ia_css_pipe *acc_pipe = NULL; 2044 enum ia_css_pipe_id pipe_id; 2045 struct ia_css_pipe *main_pipe = NULL; 2046 int err = 0; 2047 unsigned int max_input_width = 0; 2048 2049 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 2050 if (!stream) 2051 { 2052 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 2053 return -EINVAL; 2054 } 2055 2056 main_pipe = stream->last_pipe; 2057 pipe_id = main_pipe->mode; 2058 2059 /* No continuous frame allocation for capture pipe. It uses the 2060 * "main" pipe's frames. */ 2061 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) || 2062 (pipe_id == IA_CSS_PIPE_ID_VIDEO)) 2063 { 2064 /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY: 2065 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory 2066 * based input frames) there is no continuous mode and thus no need for allocated continuous frames 2067 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this 2068 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added. 2069 */ 2070 if (stream->config.continuous || 2071 (pipe_id == IA_CSS_PIPE_ID_PREVIEW && 2072 stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) { 2073 err = alloc_continuous_frames(main_pipe, true); 2074 if (err) 2075 goto ERR; 2076 } 2077 } 2078 2079 #if defined(USE_INPUT_SYSTEM_VERSION_2) 2080 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */ 2081 if (pipe_id != IA_CSS_PIPE_ID_ACC) 2082 { 2083 err = allocate_mipi_frames(main_pipe, &stream->info); 2084 if (err) 2085 goto ERR; 2086 } 2087 #elif defined(USE_INPUT_SYSTEM_VERSION_2401) 2088 if ((pipe_id != IA_CSS_PIPE_ID_ACC) && 2089 (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) 2090 { 2091 err = allocate_mipi_frames(main_pipe, &stream->info); 2092 if (err) 2093 goto ERR; 2094 } 2095 #endif 2096 2097 switch (pipe_id) 2098 { 2099 case IA_CSS_PIPE_ID_PREVIEW: 2100 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 2101 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; 2102 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe; 2103 max_input_width = 2104 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width; 2105 2106 err = create_host_preview_pipeline(main_pipe); 2107 if (err) 2108 goto ERR; 2109 2110 break; 2111 2112 case IA_CSS_PIPE_ID_VIDEO: 2113 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 2114 capture_pipe = main_pipe->pipe_settings.video.capture_pipe; 2115 max_input_width = 2116 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width; 2117 2118 err = create_host_video_pipeline(main_pipe); 2119 if (err) 2120 goto ERR; 2121 2122 break; 2123 2124 case IA_CSS_PIPE_ID_CAPTURE: 2125 capture_pipe = main_pipe; 2126 2127 break; 2128 2129 case IA_CSS_PIPE_ID_YUVPP: 2130 err = create_host_yuvpp_pipeline(main_pipe); 2131 if (err) 2132 goto ERR; 2133 2134 break; 2135 2136 case IA_CSS_PIPE_ID_ACC: 2137 err = create_host_acc_pipeline(main_pipe); 2138 if (err) 2139 goto ERR; 2140 2141 break; 2142 default: 2143 err = -EINVAL; 2144 } 2145 if (err) 2146 goto ERR; 2147 2148 if (copy_pipe) 2149 { 2150 err = create_host_copy_pipeline(copy_pipe, max_input_width, 2151 main_pipe->continuous_frames[0]); 2152 if (err) 2153 goto ERR; 2154 } 2155 2156 if (capture_pipe) 2157 { 2158 err = create_host_capture_pipeline(capture_pipe); 2159 if (err) 2160 goto ERR; 2161 } 2162 2163 if (acc_pipe) 2164 { 2165 err = create_host_acc_pipeline(acc_pipe); 2166 if (err) 2167 goto ERR; 2168 } 2169 2170 /* DH regular multi pipe - not continuous mode: create the next pipelines too */ 2171 if (!stream->config.continuous) 2172 { 2173 int i; 2174 2175 for (i = 1; i < stream->num_pipes && 0 == err; i++) { 2176 switch (stream->pipes[i]->mode) { 2177 case IA_CSS_PIPE_ID_PREVIEW: 2178 err = create_host_preview_pipeline(stream->pipes[i]); 2179 break; 2180 case IA_CSS_PIPE_ID_VIDEO: 2181 err = create_host_video_pipeline(stream->pipes[i]); 2182 break; 2183 case IA_CSS_PIPE_ID_CAPTURE: 2184 err = create_host_capture_pipeline(stream->pipes[i]); 2185 break; 2186 case IA_CSS_PIPE_ID_YUVPP: 2187 err = create_host_yuvpp_pipeline(stream->pipes[i]); 2188 break; 2189 case IA_CSS_PIPE_ID_ACC: 2190 err = create_host_acc_pipeline(stream->pipes[i]); 2191 break; 2192 default: 2193 err = -EINVAL; 2194 } 2195 if (err) 2196 goto ERR; 2197 } 2198 } 2199 2200 ERR: 2201 IA_CSS_LEAVE_ERR_PRIVATE(err); 2202 return err; 2203 } 2204 2205 static const struct ia_css_pipe default_pipe = IA_CSS_DEFAULT_PIPE; 2206 static const struct ia_css_preview_settings preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS; 2207 static const struct ia_css_capture_settings capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS; 2208 static const struct ia_css_video_settings video = IA_CSS_DEFAULT_VIDEO_SETTINGS; 2209 static const struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS; 2210 2211 static int 2212 init_pipe_defaults(enum ia_css_pipe_mode mode, 2213 struct ia_css_pipe *pipe, 2214 bool copy_pipe) { 2215 2216 if (!pipe) 2217 { 2218 IA_CSS_ERROR("NULL pipe parameter"); 2219 return -EINVAL; 2220 } 2221 2222 /* Initialize pipe to pre-defined defaults */ 2223 memcpy(pipe, &default_pipe, sizeof(default_pipe)); 2224 2225 /* TODO: JB should not be needed, but temporary backward reference */ 2226 switch (mode) 2227 { 2228 case IA_CSS_PIPE_MODE_PREVIEW: 2229 pipe->mode = IA_CSS_PIPE_ID_PREVIEW; 2230 memcpy(&pipe->pipe_settings.preview, &preview, sizeof(preview)); 2231 break; 2232 case IA_CSS_PIPE_MODE_CAPTURE: 2233 if (copy_pipe) { 2234 pipe->mode = IA_CSS_PIPE_ID_COPY; 2235 } else { 2236 pipe->mode = IA_CSS_PIPE_ID_CAPTURE; 2237 } 2238 memcpy(&pipe->pipe_settings.capture, &capture, sizeof(capture)); 2239 break; 2240 case IA_CSS_PIPE_MODE_VIDEO: 2241 pipe->mode = IA_CSS_PIPE_ID_VIDEO; 2242 memcpy(&pipe->pipe_settings.video, &video, sizeof(video)); 2243 break; 2244 case IA_CSS_PIPE_MODE_ACC: 2245 pipe->mode = IA_CSS_PIPE_ID_ACC; 2246 break; 2247 case IA_CSS_PIPE_MODE_COPY: 2248 pipe->mode = IA_CSS_PIPE_ID_CAPTURE; 2249 break; 2250 case IA_CSS_PIPE_MODE_YUVPP: 2251 pipe->mode = IA_CSS_PIPE_ID_YUVPP; 2252 memcpy(&pipe->pipe_settings.yuvpp, &yuvpp, sizeof(yuvpp)); 2253 break; 2254 default: 2255 return -EINVAL; 2256 } 2257 2258 return 0; 2259 } 2260 2261 static void 2262 pipe_global_init(void) 2263 { 2264 u8 i; 2265 2266 my_css.pipe_counter = 0; 2267 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { 2268 my_css.all_pipes[i] = NULL; 2269 } 2270 } 2271 2272 static int 2273 pipe_generate_pipe_num(const struct ia_css_pipe *pipe, 2274 unsigned int *pipe_number) { 2275 const u8 INVALID_PIPE_NUM = (uint8_t)~(0); 2276 u8 pipe_num = INVALID_PIPE_NUM; 2277 u8 i; 2278 2279 if (!pipe) 2280 { 2281 IA_CSS_ERROR("NULL pipe parameter"); 2282 return -EINVAL; 2283 } 2284 2285 /* Assign a new pipe_num .... search for empty place */ 2286 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) 2287 { 2288 if (!my_css.all_pipes[i]) { 2289 /*position is reserved */ 2290 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe; 2291 pipe_num = i; 2292 break; 2293 } 2294 } 2295 if (pipe_num == INVALID_PIPE_NUM) 2296 { 2297 /* Max number of pipes already allocated */ 2298 IA_CSS_ERROR("Max number of pipes already created"); 2299 return -ENOSPC; 2300 } 2301 2302 my_css.pipe_counter++; 2303 2304 IA_CSS_LOG("pipe_num (%d)", pipe_num); 2305 2306 *pipe_number = pipe_num; 2307 return 0; 2308 } 2309 2310 static void 2311 pipe_release_pipe_num(unsigned int pipe_num) 2312 { 2313 my_css.all_pipes[pipe_num] = NULL; 2314 my_css.pipe_counter--; 2315 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2316 "pipe_release_pipe_num (%d)\n", pipe_num); 2317 } 2318 2319 static int 2320 create_pipe(enum ia_css_pipe_mode mode, 2321 struct ia_css_pipe **pipe, 2322 bool copy_pipe) { 2323 int err = 0; 2324 struct ia_css_pipe *me; 2325 2326 if (!pipe) 2327 { 2328 IA_CSS_ERROR("NULL pipe parameter"); 2329 return -EINVAL; 2330 } 2331 2332 me = kmalloc(sizeof(*me), GFP_KERNEL); 2333 if (!me) 2334 return -ENOMEM; 2335 2336 err = init_pipe_defaults(mode, me, copy_pipe); 2337 if (err) 2338 { 2339 kfree(me); 2340 return err; 2341 } 2342 2343 err = pipe_generate_pipe_num(me, &me->pipe_num); 2344 if (err) 2345 { 2346 kfree(me); 2347 return err; 2348 } 2349 2350 *pipe = me; 2351 return 0; 2352 } 2353 2354 struct ia_css_pipe * 2355 find_pipe_by_num(uint32_t pipe_num) 2356 { 2357 unsigned int i; 2358 2359 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { 2360 if (my_css.all_pipes[i] && 2361 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) { 2362 return my_css.all_pipes[i]; 2363 } 2364 } 2365 return NULL; 2366 } 2367 2368 static void sh_css_pipe_free_acc_binaries( 2369 struct ia_css_pipe *pipe) 2370 { 2371 struct ia_css_pipeline *pipeline; 2372 struct ia_css_pipeline_stage *stage; 2373 2374 assert(pipe); 2375 if (!pipe) { 2376 IA_CSS_ERROR("NULL input pointer"); 2377 return; 2378 } 2379 pipeline = &pipe->pipeline; 2380 2381 /* loop through the stages and unload them */ 2382 for (stage = pipeline->stages; stage; stage = stage->next) { 2383 struct ia_css_fw_info *firmware = (struct ia_css_fw_info *) 2384 stage->firmware; 2385 if (firmware) 2386 ia_css_pipe_unload_extension(pipe, firmware); 2387 } 2388 } 2389 2390 int 2391 ia_css_pipe_destroy(struct ia_css_pipe *pipe) { 2392 int err = 0; 2393 2394 IA_CSS_ENTER("pipe = %p", pipe); 2395 2396 if (!pipe) 2397 { 2398 IA_CSS_LEAVE_ERR(-EINVAL); 2399 return -EINVAL; 2400 } 2401 2402 if (pipe->stream) 2403 { 2404 IA_CSS_LOG("ia_css_stream_destroy not called!"); 2405 IA_CSS_LEAVE_ERR(-EINVAL); 2406 return -EINVAL; 2407 } 2408 2409 switch (pipe->config.mode) 2410 { 2411 case IA_CSS_PIPE_MODE_PREVIEW: 2412 /* need to take into account that this function is also called 2413 on the internal copy pipe */ 2414 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) { 2415 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES, 2416 pipe->continuous_frames); 2417 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES, 2418 pipe->cont_md_buffers); 2419 if (pipe->pipe_settings.preview.copy_pipe) { 2420 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe); 2421 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2422 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n", 2423 err); 2424 } 2425 } 2426 break; 2427 case IA_CSS_PIPE_MODE_VIDEO: 2428 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) { 2429 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES, 2430 pipe->continuous_frames); 2431 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES, 2432 pipe->cont_md_buffers); 2433 if (pipe->pipe_settings.video.copy_pipe) { 2434 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe); 2435 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2436 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n", 2437 err); 2438 } 2439 } 2440 #ifndef ISP2401 2441 ia_css_frame_free_multiple(NUM_TNR_FRAMES, 2442 pipe->pipe_settings.video.tnr_frames); 2443 #else 2444 ia_css_frame_free_multiple(NUM_TNR_FRAMES, 2445 pipe->pipe_settings.video.tnr_frames); 2446 #endif 2447 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, 2448 pipe->pipe_settings.video.delay_frames); 2449 break; 2450 case IA_CSS_PIPE_MODE_CAPTURE: 2451 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, 2452 pipe->pipe_settings.capture.delay_frames); 2453 break; 2454 case IA_CSS_PIPE_MODE_ACC: 2455 sh_css_pipe_free_acc_binaries(pipe); 2456 break; 2457 case IA_CSS_PIPE_MODE_COPY: 2458 break; 2459 case IA_CSS_PIPE_MODE_YUVPP: 2460 break; 2461 } 2462 2463 sh_css_params_free_gdc_lut(pipe->scaler_pp_lut); 2464 pipe->scaler_pp_lut = mmgr_NULL; 2465 2466 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL; 2467 sh_css_pipe_free_shading_table(pipe); 2468 2469 ia_css_pipeline_destroy(&pipe->pipeline); 2470 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe)); 2471 2472 /* Temporarily, not every sh_css_pipe has an acc_extension. */ 2473 if (pipe->config.acc_extension) 2474 { 2475 ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension); 2476 } 2477 kfree(pipe); 2478 IA_CSS_LEAVE("err = %d", err); 2479 return err; 2480 } 2481 2482 void 2483 ia_css_uninit(void) 2484 { 2485 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n"); 2486 #if WITH_PC_MONITORING 2487 sh_css_print("PC_MONITORING: %s() -- started\n", __func__); 2488 print_pc_histogram(); 2489 #endif 2490 2491 sh_css_params_free_default_gdc_lut(); 2492 2493 /* TODO: JB: implement decent check and handling of freeing mipi frames */ 2494 //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed 2495 /* cleanup generic data */ 2496 sh_css_params_uninit(); 2497 ia_css_refcount_uninit(); 2498 2499 ia_css_rmgr_uninit(); 2500 2501 #if !defined(HAS_NO_INPUT_FORMATTER) 2502 /* needed for reprogramming the inputformatter after power cycle of css */ 2503 ifmtr_set_if_blocking_mode_reset = true; 2504 #endif 2505 2506 if (!fw_explicitly_loaded) { 2507 ia_css_unload_firmware(); 2508 } 2509 ia_css_spctrl_unload_fw(SP0_ID); 2510 sh_css_sp_set_sp_running(false); 2511 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 2512 /* check and free any remaining mipi frames */ 2513 free_mipi_frames(NULL); 2514 #endif 2515 2516 sh_css_sp_reset_global_vars(); 2517 2518 ia_css_isys_uninit(); 2519 2520 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n"); 2521 } 2522 2523 int ia_css_irq_translate( 2524 unsigned int *irq_infos) 2525 { 2526 enum virq_id irq; 2527 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs; 2528 unsigned int infos = 0; 2529 2530 /* irq_infos can be NULL, but that would make the function useless */ 2531 /* assert(irq_infos != NULL); */ 2532 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2533 "ia_css_irq_translate() enter: irq_infos=%p\n", irq_infos); 2534 2535 while (status == hrt_isp_css_irq_status_more_irqs) { 2536 status = virq_get_channel_id(&irq); 2537 if (status == hrt_isp_css_irq_status_error) 2538 return -EINVAL; 2539 2540 #if WITH_PC_MONITORING 2541 sh_css_print("PC_MONITORING: %s() irq = %d, sh_binary_running set to 0\n", 2542 __func__, irq); 2543 sh_binary_running = 0; 2544 #endif 2545 2546 switch (irq) { 2547 case virq_sp: 2548 /* When SP goes to idle, info is available in the 2549 * event queue. */ 2550 infos |= IA_CSS_IRQ_INFO_EVENTS_READY; 2551 break; 2552 case virq_isp: 2553 break; 2554 case virq_isys_sof: 2555 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF; 2556 break; 2557 case virq_isys_eof: 2558 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF; 2559 break; 2560 case virq_isys_csi: 2561 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR; 2562 break; 2563 #if !defined(HAS_NO_INPUT_FORMATTER) 2564 case virq_ifmt0_id: 2565 infos |= IA_CSS_IRQ_INFO_IF_ERROR; 2566 break; 2567 #endif 2568 case virq_dma: 2569 infos |= IA_CSS_IRQ_INFO_DMA_ERROR; 2570 break; 2571 case virq_sw_pin_0: 2572 infos |= sh_css_get_sw_interrupt_value(0); 2573 break; 2574 case virq_sw_pin_1: 2575 infos |= sh_css_get_sw_interrupt_value(1); 2576 /* pqiao TODO: also assumption here */ 2577 break; 2578 default: 2579 break; 2580 } 2581 } 2582 2583 if (irq_infos) 2584 *irq_infos = infos; 2585 2586 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2587 "ia_css_irq_translate() leave: irq_infos=%u\n", 2588 infos); 2589 2590 return 0; 2591 } 2592 2593 int ia_css_irq_enable( 2594 enum ia_css_irq_info info, 2595 bool enable) 2596 { 2597 enum virq_id irq = N_virq_id; 2598 2599 IA_CSS_ENTER("info=%d, enable=%d", info, enable); 2600 2601 switch (info) { 2602 #if !defined(HAS_NO_INPUT_FORMATTER) 2603 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF: 2604 irq = virq_isys_sof; 2605 break; 2606 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF: 2607 irq = virq_isys_eof; 2608 break; 2609 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR: 2610 irq = virq_isys_csi; 2611 break; 2612 case IA_CSS_IRQ_INFO_IF_ERROR: 2613 irq = virq_ifmt0_id; 2614 break; 2615 #else 2616 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF: 2617 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF: 2618 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR: 2619 case IA_CSS_IRQ_INFO_IF_ERROR: 2620 /* Just ignore those unused IRQs without printing errors */ 2621 return 0; 2622 #endif 2623 case IA_CSS_IRQ_INFO_DMA_ERROR: 2624 irq = virq_dma; 2625 break; 2626 case IA_CSS_IRQ_INFO_SW_0: 2627 irq = virq_sw_pin_0; 2628 break; 2629 case IA_CSS_IRQ_INFO_SW_1: 2630 irq = virq_sw_pin_1; 2631 break; 2632 default: 2633 IA_CSS_LEAVE_ERR(-EINVAL); 2634 return -EINVAL; 2635 } 2636 2637 cnd_virq_enable_channel(irq, enable); 2638 2639 IA_CSS_LEAVE_ERR(0); 2640 return 0; 2641 } 2642 2643 2644 static unsigned int 2645 sh_css_get_sw_interrupt_value(unsigned int irq) 2646 { 2647 unsigned int irq_value; 2648 2649 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2650 "sh_css_get_sw_interrupt_value() enter: irq=%d\n", irq); 2651 irq_value = sh_css_sp_get_sw_interrupt_value(irq); 2652 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2653 "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n", irq_value); 2654 return irq_value; 2655 } 2656 2657 /* configure and load the copy binary, the next binary is used to 2658 determine whether the copy binary needs to do left padding. */ 2659 static int load_copy_binary( 2660 struct ia_css_pipe *pipe, 2661 struct ia_css_binary *copy_binary, 2662 struct ia_css_binary *next_binary) 2663 { 2664 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info; 2665 unsigned int left_padding; 2666 int err; 2667 struct ia_css_binary_descr copy_descr; 2668 2669 /* next_binary can be NULL */ 2670 assert(pipe); 2671 assert(copy_binary); 2672 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 2673 "load_copy_binary() enter:\n"); 2674 2675 if (next_binary) { 2676 copy_out_info = next_binary->in_frame_info; 2677 left_padding = next_binary->left_padding; 2678 } else { 2679 copy_out_info = pipe->output_info[0]; 2680 copy_vf_info = pipe->vf_output_info[0]; 2681 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); 2682 left_padding = 0; 2683 } 2684 2685 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr, 2686 ©_in_info, ©_out_info, 2687 (next_binary) ? NULL : NULL/*TODO: ©_vf_info*/); 2688 err = ia_css_binary_find(©_descr, copy_binary); 2689 if (err) 2690 return err; 2691 copy_binary->left_padding = left_padding; 2692 return 0; 2693 } 2694 2695 static int 2696 alloc_continuous_frames( 2697 struct ia_css_pipe *pipe, bool init_time) { 2698 int err = 0; 2699 struct ia_css_frame_info ref_info; 2700 enum ia_css_pipe_id pipe_id; 2701 bool continuous; 2702 unsigned int i, idx; 2703 unsigned int num_frames; 2704 struct ia_css_pipe *capture_pipe = NULL; 2705 2706 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time); 2707 2708 if ((!pipe) || (!pipe->stream)) 2709 { 2710 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 2711 return -EINVAL; 2712 } 2713 2714 pipe_id = pipe->mode; 2715 continuous = pipe->stream->config.continuous; 2716 2717 if (continuous) 2718 { 2719 if (init_time) { 2720 num_frames = pipe->stream->config.init_num_cont_raw_buf; 2721 pipe->stream->continuous_pipe = pipe; 2722 } else 2723 num_frames = pipe->stream->config.target_num_cont_raw_buf; 2724 } else 2725 { 2726 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES; 2727 } 2728 2729 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 2730 { 2731 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info; 2732 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) 2733 { 2734 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info; 2735 } else 2736 { 2737 /* should not happen */ 2738 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 2739 return -EINVAL; 2740 } 2741 2742 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 2743 /* For CSI2+, the continuous frame will hold the full input frame */ 2744 ref_info.res.width = pipe->stream->config.input_config.input_res.width; 2745 ref_info.res.height = pipe->stream->config.input_config.input_res.height; 2746 2747 /* Ensure padded width is aligned for 2401 */ 2748 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS); 2749 #endif 2750 2751 #if !defined(HAS_NO_PACKED_RAW_PIXELS) 2752 if (pipe->stream->config.pack_raw_pixels) 2753 { 2754 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 2755 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n"); 2756 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED; 2757 } else 2758 #endif 2759 { 2760 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 2761 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n"); 2762 ref_info.format = IA_CSS_FRAME_FORMAT_RAW; 2763 } 2764 2765 /* Write format back to binary */ 2766 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 2767 { 2768 pipe->pipe_settings.preview.preview_binary.in_frame_info.format = 2769 ref_info.format; 2770 capture_pipe = pipe->pipe_settings.preview.capture_pipe; 2771 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) 2772 { 2773 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format; 2774 capture_pipe = pipe->pipe_settings.video.capture_pipe; 2775 } else 2776 { 2777 /* should not happen */ 2778 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 2779 return -EINVAL; 2780 } 2781 2782 if (init_time) 2783 idx = 0; 2784 else 2785 idx = pipe->stream->config.init_num_cont_raw_buf; 2786 2787 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) 2788 { 2789 /* free previous frame */ 2790 if (pipe->continuous_frames[i]) { 2791 ia_css_frame_free(pipe->continuous_frames[i]); 2792 pipe->continuous_frames[i] = NULL; 2793 } 2794 /* free previous metadata buffer */ 2795 ia_css_metadata_free(pipe->cont_md_buffers[i]); 2796 pipe->cont_md_buffers[i] = NULL; 2797 2798 /* check if new frame needed */ 2799 if (i < num_frames) { 2800 /* allocate new frame */ 2801 err = ia_css_frame_allocate_from_info( 2802 &pipe->continuous_frames[i], 2803 &ref_info); 2804 if (err) { 2805 IA_CSS_LEAVE_ERR_PRIVATE(err); 2806 return err; 2807 } 2808 /* allocate metadata buffer */ 2809 pipe->cont_md_buffers[i] = ia_css_metadata_allocate( 2810 &pipe->stream->info.metadata_info); 2811 } 2812 } 2813 IA_CSS_LEAVE_ERR_PRIVATE(0); 2814 return 0; 2815 } 2816 2817 int 2818 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) { 2819 if (!stream) 2820 return -EINVAL; 2821 return alloc_continuous_frames(stream->continuous_pipe, false); 2822 } 2823 2824 static int 2825 load_preview_binaries(struct ia_css_pipe *pipe) { 2826 struct ia_css_frame_info prev_in_info, 2827 prev_bds_out_info, 2828 prev_out_info, 2829 prev_vf_info; 2830 struct ia_css_binary_descr preview_descr; 2831 bool online; 2832 int err = 0; 2833 bool continuous, need_vf_pp = false; 2834 bool need_isp_copy_binary = false; 2835 #ifdef USE_INPUT_SYSTEM_VERSION_2401 2836 bool sensor = false; 2837 #endif 2838 /* preview only have 1 output pin now */ 2839 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0]; 2840 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview; 2841 2842 IA_CSS_ENTER_PRIVATE(""); 2843 assert(pipe); 2844 assert(pipe->stream); 2845 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW); 2846 2847 online = pipe->stream->config.online; 2848 continuous = pipe->stream->config.continuous; 2849 #ifdef USE_INPUT_SYSTEM_VERSION_2401 2850 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 2851 #endif 2852 2853 if (mycs->preview_binary.info) 2854 return 0; 2855 2856 err = ia_css_util_check_input(&pipe->stream->config, false, false); 2857 if (err) 2858 return err; 2859 err = ia_css_frame_check_info(pipe_out_info); 2860 if (err) 2861 return err; 2862 2863 /* Note: the current selection of vf_pp binary and 2864 * parameterization of the preview binary contains a few pieces 2865 * of hardcoded knowledge. This needs to be cleaned up such that 2866 * the binary selection becomes more generic. 2867 * The vf_pp binary is needed if one or more of the following features 2868 * are required: 2869 * 1. YUV downscaling. 2870 * 2. Digital zoom. 2871 * 3. An output format that is not supported by the preview binary. 2872 * In practice this means something other than yuv_line or nv12. 2873 * The decision if the vf_pp binary is needed for YUV downscaling is 2874 * made after the preview binary selection, since some preview binaries 2875 * can perform the requested YUV downscaling. 2876 * */ 2877 need_vf_pp = pipe->config.enable_dz; 2878 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE && 2879 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 || 2880 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 || 2881 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY); 2882 2883 /* Preview step 1 */ 2884 if (pipe->vf_yuv_ds_input_info.res.width) 2885 prev_vf_info = pipe->vf_yuv_ds_input_info; 2886 else 2887 prev_vf_info = *pipe_out_info; 2888 /* If vf_pp is needed, then preview must output yuv_line. 2889 * The exception is when vf_pp is manually disabled, that is only 2890 * used in combination with a pipeline extension that requires 2891 * yuv_line as input. 2892 * */ 2893 if (need_vf_pp) 2894 ia_css_frame_info_set_format(&prev_vf_info, 2895 IA_CSS_FRAME_FORMAT_YUV_LINE); 2896 2897 err = ia_css_pipe_get_preview_binarydesc( 2898 pipe, 2899 &preview_descr, 2900 &prev_in_info, 2901 &prev_bds_out_info, 2902 &prev_out_info, 2903 &prev_vf_info); 2904 if (err) 2905 return err; 2906 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary); 2907 if (err) 2908 return err; 2909 2910 if (IS_ISP2401) { 2911 /* The delay latency determines the number of invalid frames after 2912 * a stream is started. */ 2913 pipe->num_invalid_frames = pipe->dvs_frame_delay; 2914 pipe->info.num_invalid_frames = pipe->num_invalid_frames; 2915 2916 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2917 "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n", 2918 pipe->num_invalid_frames, pipe->dvs_frame_delay); 2919 } 2920 2921 /* The vf_pp binary is needed when (further) YUV downscaling is required */ 2922 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width; 2923 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height; 2924 2925 /* When vf_pp is needed, then the output format of the selected 2926 * preview binary must be yuv_line. If this is not the case, 2927 * then the preview binary selection is done again. 2928 */ 2929 if (need_vf_pp && 2930 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) 2931 { 2932 /* Preview step 2 */ 2933 if (pipe->vf_yuv_ds_input_info.res.width) 2934 prev_vf_info = pipe->vf_yuv_ds_input_info; 2935 else 2936 prev_vf_info = *pipe_out_info; 2937 2938 ia_css_frame_info_set_format(&prev_vf_info, 2939 IA_CSS_FRAME_FORMAT_YUV_LINE); 2940 2941 err = ia_css_pipe_get_preview_binarydesc( 2942 pipe, 2943 &preview_descr, 2944 &prev_in_info, 2945 &prev_bds_out_info, 2946 &prev_out_info, 2947 &prev_vf_info); 2948 if (err) 2949 return err; 2950 err = ia_css_binary_find(&preview_descr, 2951 &mycs->preview_binary); 2952 if (err) 2953 return err; 2954 } 2955 2956 if (need_vf_pp) 2957 { 2958 struct ia_css_binary_descr vf_pp_descr; 2959 2960 /* Viewfinder post-processing */ 2961 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr, 2962 &mycs->preview_binary.out_frame_info[0], 2963 pipe_out_info); 2964 err = ia_css_binary_find(&vf_pp_descr, 2965 &mycs->vf_pp_binary); 2966 if (err) 2967 return err; 2968 } 2969 2970 #ifdef USE_INPUT_SYSTEM_VERSION_2401 2971 /* When the input system is 2401, only the Direct Sensor Mode 2972 * Offline Preview uses the ISP copy binary. 2973 */ 2974 need_isp_copy_binary = !online && sensor; 2975 #else 2976 /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY: 2977 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases 2978 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical 2979 * copies sensor data to DDR) does not have much use. 2980 */ 2981 if (!IS_ISP2401) 2982 need_isp_copy_binary = !online && !continuous; 2983 else 2984 need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY); 2985 #endif 2986 2987 /* Copy */ 2988 if (need_isp_copy_binary) 2989 { 2990 err = load_copy_binary(pipe, 2991 &mycs->copy_binary, 2992 &mycs->preview_binary); 2993 if (err) 2994 return err; 2995 } 2996 2997 if (pipe->shading_table) 2998 { 2999 ia_css_shading_table_free(pipe->shading_table); 3000 pipe->shading_table = NULL; 3001 } 3002 3003 return 0; 3004 } 3005 3006 static void 3007 ia_css_binary_unload(struct ia_css_binary *binary) 3008 { 3009 ia_css_binary_destroy_isp_parameters(binary); 3010 } 3011 3012 static int 3013 unload_preview_binaries(struct ia_css_pipe *pipe) { 3014 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 3015 3016 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) 3017 { 3018 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 3019 return -EINVAL; 3020 } 3021 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary); 3022 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary); 3023 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary); 3024 3025 IA_CSS_LEAVE_ERR_PRIVATE(0); 3026 return 0; 3027 } 3028 3029 static const struct ia_css_fw_info *last_output_firmware( 3030 const struct ia_css_fw_info *fw) 3031 { 3032 const struct ia_css_fw_info *last_fw = NULL; 3033 /* fw can be NULL */ 3034 IA_CSS_ENTER_LEAVE_PRIVATE(""); 3035 3036 for (; fw; fw = fw->next) { 3037 const struct ia_css_fw_info *info = fw; 3038 3039 if (info->info.isp.sp.enable.output) 3040 last_fw = fw; 3041 } 3042 return last_fw; 3043 } 3044 3045 static int add_firmwares( 3046 struct ia_css_pipeline *me, 3047 struct ia_css_binary *binary, 3048 const struct ia_css_fw_info *fw, 3049 const struct ia_css_fw_info *last_fw, 3050 unsigned int binary_mode, 3051 struct ia_css_frame *in_frame, 3052 struct ia_css_frame *out_frame, 3053 struct ia_css_frame *vf_frame, 3054 struct ia_css_pipeline_stage **my_stage, 3055 struct ia_css_pipeline_stage **vf_stage) 3056 { 3057 int err = 0; 3058 struct ia_css_pipeline_stage *extra_stage = NULL; 3059 struct ia_css_pipeline_stage_desc stage_desc; 3060 3061 /* all args can be NULL ??? */ 3062 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 3063 "add_firmwares() enter:\n"); 3064 3065 for (; fw; fw = fw->next) { 3066 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL}; 3067 struct ia_css_frame *in = NULL; 3068 struct ia_css_frame *vf = NULL; 3069 3070 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) { 3071 out[0] = out_frame; 3072 } 3073 if (fw->info.isp.sp.enable.in_frame != 0) { 3074 in = in_frame; 3075 } 3076 if (fw->info.isp.sp.enable.out_frame != 0) { 3077 vf = vf_frame; 3078 } 3079 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary, 3080 out, in, vf, fw, binary_mode); 3081 err = ia_css_pipeline_create_and_add_stage(me, 3082 &stage_desc, 3083 &extra_stage); 3084 if (err) 3085 return err; 3086 if (fw->info.isp.sp.enable.output != 0) 3087 in_frame = extra_stage->args.out_frame[0]; 3088 if (my_stage && !*my_stage && extra_stage) 3089 *my_stage = extra_stage; 3090 if (vf_stage && !*vf_stage && extra_stage && 3091 fw->info.isp.sp.enable.vf_veceven) 3092 *vf_stage = extra_stage; 3093 } 3094 return err; 3095 } 3096 3097 static int add_vf_pp_stage( 3098 struct ia_css_pipe *pipe, 3099 struct ia_css_frame *in_frame, 3100 struct ia_css_frame *out_frame, 3101 struct ia_css_binary *vf_pp_binary, 3102 struct ia_css_pipeline_stage **vf_pp_stage) 3103 { 3104 struct ia_css_pipeline *me = NULL; 3105 const struct ia_css_fw_info *last_fw = NULL; 3106 int err = 0; 3107 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 3108 struct ia_css_pipeline_stage_desc stage_desc; 3109 3110 /* out_frame can be NULL ??? */ 3111 3112 if (!pipe) 3113 return -EINVAL; 3114 if (!in_frame) 3115 return -EINVAL; 3116 if (!vf_pp_binary) 3117 return -EINVAL; 3118 if (!vf_pp_stage) 3119 return -EINVAL; 3120 3121 ia_css_pipe_util_create_output_frames(out_frames); 3122 me = &pipe->pipeline; 3123 3124 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 3125 "add_vf_pp_stage() enter:\n"); 3126 3127 *vf_pp_stage = NULL; 3128 3129 last_fw = last_output_firmware(pipe->vf_stage); 3130 if (!pipe->extra_config.disable_vf_pp) { 3131 if (last_fw) { 3132 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 3133 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary, 3134 out_frames, in_frame, NULL); 3135 } else { 3136 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 3137 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary, 3138 out_frames, in_frame, NULL); 3139 } 3140 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage); 3141 if (err) 3142 return err; 3143 in_frame = (*vf_pp_stage)->args.out_frame[0]; 3144 } 3145 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw, 3146 IA_CSS_BINARY_MODE_VF_PP, 3147 in_frame, out_frame, NULL, 3148 vf_pp_stage, NULL); 3149 return err; 3150 } 3151 3152 static int add_yuv_scaler_stage( 3153 struct ia_css_pipe *pipe, 3154 struct ia_css_pipeline *me, 3155 struct ia_css_frame *in_frame, 3156 struct ia_css_frame *out_frame, 3157 struct ia_css_frame *internal_out_frame, 3158 struct ia_css_binary *yuv_scaler_binary, 3159 struct ia_css_pipeline_stage **pre_vf_pp_stage) 3160 { 3161 const struct ia_css_fw_info *last_fw; 3162 int err = 0; 3163 struct ia_css_frame *vf_frame = NULL; 3164 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 3165 struct ia_css_pipeline_stage_desc stage_desc; 3166 3167 /* out_frame can be NULL ??? */ 3168 assert(in_frame); 3169 assert(pipe); 3170 assert(me); 3171 assert(yuv_scaler_binary); 3172 assert(pre_vf_pp_stage); 3173 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 3174 "add_yuv_scaler_stage() enter:\n"); 3175 3176 *pre_vf_pp_stage = NULL; 3177 ia_css_pipe_util_create_output_frames(out_frames); 3178 3179 last_fw = last_output_firmware(pipe->output_stage); 3180 3181 if (last_fw) { 3182 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 3183 ia_css_pipe_get_generic_stage_desc(&stage_desc, 3184 yuv_scaler_binary, out_frames, in_frame, vf_frame); 3185 } else { 3186 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 3187 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame); 3188 ia_css_pipe_get_generic_stage_desc(&stage_desc, 3189 yuv_scaler_binary, out_frames, in_frame, vf_frame); 3190 } 3191 err = ia_css_pipeline_create_and_add_stage(me, 3192 &stage_desc, 3193 pre_vf_pp_stage); 3194 if (err) 3195 return err; 3196 in_frame = (*pre_vf_pp_stage)->args.out_frame[0]; 3197 3198 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw, 3199 IA_CSS_BINARY_MODE_CAPTURE_PP, 3200 in_frame, out_frame, vf_frame, 3201 NULL, pre_vf_pp_stage); 3202 /* If a firmware produce vf_pp output, we set that as vf_pp input */ 3203 (*pre_vf_pp_stage)->args.vf_downscale_log2 = 3204 yuv_scaler_binary->vf_downscale_log2; 3205 3206 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 3207 "add_yuv_scaler_stage() leave:\n"); 3208 return err; 3209 } 3210 3211 static int add_capture_pp_stage( 3212 struct ia_css_pipe *pipe, 3213 struct ia_css_pipeline *me, 3214 struct ia_css_frame *in_frame, 3215 struct ia_css_frame *out_frame, 3216 struct ia_css_binary *capture_pp_binary, 3217 struct ia_css_pipeline_stage **capture_pp_stage) 3218 { 3219 const struct ia_css_fw_info *last_fw = NULL; 3220 int err = 0; 3221 struct ia_css_frame *vf_frame = NULL; 3222 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 3223 struct ia_css_pipeline_stage_desc stage_desc; 3224 3225 /* out_frame can be NULL ??? */ 3226 assert(in_frame); 3227 assert(pipe); 3228 assert(me); 3229 assert(capture_pp_binary); 3230 assert(capture_pp_stage); 3231 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 3232 "add_capture_pp_stage() enter:\n"); 3233 3234 *capture_pp_stage = NULL; 3235 ia_css_pipe_util_create_output_frames(out_frames); 3236 3237 last_fw = last_output_firmware(pipe->output_stage); 3238 err = ia_css_frame_allocate_from_info(&vf_frame, 3239 &capture_pp_binary->vf_frame_info); 3240 if (err) 3241 return err; 3242 if (last_fw) { 3243 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 3244 ia_css_pipe_get_generic_stage_desc(&stage_desc, 3245 capture_pp_binary, out_frames, NULL, vf_frame); 3246 } else { 3247 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 3248 ia_css_pipe_get_generic_stage_desc(&stage_desc, 3249 capture_pp_binary, out_frames, NULL, vf_frame); 3250 } 3251 err = ia_css_pipeline_create_and_add_stage(me, 3252 &stage_desc, 3253 capture_pp_stage); 3254 if (err) 3255 return err; 3256 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw, 3257 IA_CSS_BINARY_MODE_CAPTURE_PP, 3258 in_frame, out_frame, vf_frame, 3259 NULL, capture_pp_stage); 3260 /* If a firmware produce vf_pp output, we set that as vf_pp input */ 3261 if (*capture_pp_stage) { 3262 (*capture_pp_stage)->args.vf_downscale_log2 = 3263 capture_pp_binary->vf_downscale_log2; 3264 } 3265 return err; 3266 } 3267 3268 static void sh_css_setup_queues(void) 3269 { 3270 const struct ia_css_fw_info *fw; 3271 unsigned int HIVE_ADDR_host_sp_queues_initialized; 3272 3273 sh_css_hmm_buffer_record_init(); 3274 3275 sh_css_event_init_irq_mask(); 3276 3277 fw = &sh_css_sp_fw; 3278 HIVE_ADDR_host_sp_queues_initialized = 3279 fw->info.sp.host_sp_queues_initialized; 3280 3281 ia_css_bufq_init(); 3282 3283 /* set "host_sp_queues_initialized" to "true" */ 3284 sp_dmem_store_uint32(SP0_ID, 3285 (unsigned int)sp_address_of(host_sp_queues_initialized), 3286 (uint32_t)(1)); 3287 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n"); 3288 } 3289 3290 static int 3291 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, 3292 struct ia_css_frame *vf_frame, unsigned int idx) { 3293 int err = 0; 3294 unsigned int thread_id; 3295 enum sh_css_queue_id queue_id; 3296 3297 assert(vf_frame); 3298 3299 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx); 3300 vf_frame->contiguous = false; 3301 vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; 3302 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 3303 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id); 3304 vf_frame->dynamic_queue_id = queue_id; 3305 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx; 3306 3307 err = ia_css_frame_init_planes(vf_frame); 3308 return err; 3309 } 3310 3311 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3312 static unsigned int 3313 get_crop_lines_for_bayer_order( 3314 const struct ia_css_stream_config *config) 3315 { 3316 assert(config); 3317 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR) 3318 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG)) 3319 return 1; 3320 3321 return 0; 3322 } 3323 3324 static unsigned int 3325 get_crop_columns_for_bayer_order( 3326 const struct ia_css_stream_config *config) 3327 { 3328 assert(config); 3329 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB) 3330 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG)) 3331 return 1; 3332 3333 return 0; 3334 } 3335 3336 /* This function is to get the sum of all extra pixels in addition to the effective 3337 * input, it includes dvs envelop and filter run-in */ 3338 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe, 3339 unsigned int *extra_row, unsigned int *extra_column) 3340 { 3341 enum ia_css_pipe_id pipe_id = pipe->mode; 3342 unsigned int left_cropping = 0, top_cropping = 0; 3343 unsigned int i; 3344 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope; 3345 3346 /* The dvs envelope info may not be correctly sent down via pipe config 3347 * The check is made and the correct value is populated in the binary info 3348 * Use this value when computing crop, else excess lines may get trimmed 3349 */ 3350 switch (pipe_id) { 3351 case IA_CSS_PIPE_ID_PREVIEW: 3352 if (pipe->pipe_settings.preview.preview_binary.info) { 3353 left_cropping = 3354 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping; 3355 top_cropping = 3356 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping; 3357 } 3358 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope; 3359 break; 3360 case IA_CSS_PIPE_ID_VIDEO: 3361 if (pipe->pipe_settings.video.video_binary.info) { 3362 left_cropping = 3363 pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping; 3364 top_cropping = 3365 pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping; 3366 } 3367 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope; 3368 break; 3369 case IA_CSS_PIPE_ID_CAPTURE: 3370 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 3371 if (pipe->pipe_settings.capture.primary_binary[i].info) { 3372 left_cropping += 3373 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping; 3374 top_cropping += 3375 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping; 3376 } 3377 dvs_env.width += 3378 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width; 3379 dvs_env.height += 3380 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height; 3381 } 3382 break; 3383 default: 3384 break; 3385 } 3386 3387 *extra_row = top_cropping + dvs_env.height; 3388 *extra_column = left_cropping + dvs_env.width; 3389 } 3390 3391 void 3392 ia_css_get_crop_offsets( 3393 struct ia_css_pipe *pipe, 3394 struct ia_css_frame_info *in_frame) 3395 { 3396 unsigned int row = 0; 3397 unsigned int column = 0; 3398 struct ia_css_resolution *input_res; 3399 struct ia_css_resolution *effective_res; 3400 unsigned int extra_row = 0, extra_col = 0; 3401 unsigned int min_reqd_height, min_reqd_width; 3402 3403 assert(pipe); 3404 assert(pipe->stream); 3405 assert(in_frame); 3406 3407 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u", 3408 pipe, pipe->config.input_effective_res.width, 3409 pipe->config.input_effective_res.height); 3410 3411 input_res = &pipe->stream->config.input_config.input_res; 3412 #ifndef ISP2401 3413 effective_res = &pipe->stream->config.input_config.effective_res; 3414 #else 3415 effective_res = &pipe->config.input_effective_res; 3416 #endif 3417 3418 get_pipe_extra_pixel(pipe, &extra_row, &extra_col); 3419 3420 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order; 3421 3422 min_reqd_height = effective_res->height + extra_row; 3423 min_reqd_width = effective_res->width + extra_col; 3424 3425 if (input_res->height > min_reqd_height) { 3426 row = (input_res->height - min_reqd_height) / 2; 3427 row &= ~0x1; 3428 } 3429 if (input_res->width > min_reqd_width) { 3430 column = (input_res->width - min_reqd_width) / 2; 3431 column &= ~0x1; 3432 } 3433 3434 /* 3435 * TODO: 3436 * 1. Require the special support for RAW10 packed mode. 3437 * 2. Require the special support for the online use cases. 3438 */ 3439 3440 /* ISP expects GRBG bayer order, we skip one line and/or one row 3441 * to correct in case the input bayer order is different. 3442 */ 3443 column += get_crop_columns_for_bayer_order(&pipe->stream->config); 3444 row += get_crop_lines_for_bayer_order(&pipe->stream->config); 3445 3446 in_frame->crop_info.start_column = column; 3447 in_frame->crop_info.start_line = row; 3448 3449 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row); 3450 3451 return; 3452 } 3453 #endif 3454 3455 static int 3456 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe, 3457 struct ia_css_frame *frame, enum ia_css_frame_format format) { 3458 struct ia_css_frame *in_frame; 3459 int err = 0; 3460 unsigned int thread_id; 3461 enum sh_css_queue_id queue_id; 3462 3463 assert(frame); 3464 in_frame = frame; 3465 3466 in_frame->info.format = format; 3467 3468 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3469 if (format == IA_CSS_FRAME_FORMAT_RAW) 3470 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ? 3471 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW; 3472 #endif 3473 3474 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width; 3475 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height; 3476 in_frame->info.raw_bit_depth = 3477 ia_css_pipe_util_pipe_input_format_bpp(pipe); 3478 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0); 3479 in_frame->contiguous = false; 3480 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; 3481 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 3482 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id); 3483 in_frame->dynamic_queue_id = queue_id; 3484 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME; 3485 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3486 ia_css_get_crop_offsets(pipe, &in_frame->info); 3487 #endif 3488 err = ia_css_frame_init_planes(in_frame); 3489 3490 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 3491 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order); 3492 3493 return err; 3494 } 3495 3496 static int 3497 init_out_frameinfo_defaults(struct ia_css_pipe *pipe, 3498 struct ia_css_frame *out_frame, unsigned int idx) { 3499 int err = 0; 3500 unsigned int thread_id; 3501 enum sh_css_queue_id queue_id; 3502 3503 assert(out_frame); 3504 3505 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx); 3506 out_frame->contiguous = false; 3507 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; 3508 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 3509 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id); 3510 out_frame->dynamic_queue_id = queue_id; 3511 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx; 3512 err = ia_css_frame_init_planes(out_frame); 3513 3514 return err; 3515 } 3516 3517 /* Create stages for video pipe */ 3518 static int create_host_video_pipeline(struct ia_css_pipe *pipe) 3519 { 3520 struct ia_css_pipeline_stage_desc stage_desc; 3521 struct ia_css_binary *copy_binary, *video_binary, 3522 *yuv_scaler_binary, *vf_pp_binary; 3523 struct ia_css_pipeline_stage *copy_stage = NULL; 3524 struct ia_css_pipeline_stage *video_stage = NULL; 3525 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL; 3526 struct ia_css_pipeline_stage *vf_pp_stage = NULL; 3527 struct ia_css_pipeline *me; 3528 struct ia_css_frame *in_frame = NULL; 3529 struct ia_css_frame *out_frame; 3530 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 3531 struct ia_css_frame *vf_frame = NULL; 3532 int err = 0; 3533 bool need_copy = false; 3534 bool need_vf_pp = false; 3535 bool need_yuv_pp = false; 3536 unsigned int num_output_pins; 3537 bool need_in_frameinfo_memory = false; 3538 3539 unsigned int i, num_yuv_scaler; 3540 bool *is_output_stage = NULL; 3541 3542 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 3543 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { 3544 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 3545 return -EINVAL; 3546 } 3547 ia_css_pipe_util_create_output_frames(out_frames); 3548 out_frame = &pipe->out_frame_struct; 3549 3550 /* pipeline already created as part of create_host_pipeline_structure */ 3551 me = &pipe->pipeline; 3552 ia_css_pipeline_clean(me); 3553 3554 me->dvs_frame_delay = pipe->dvs_frame_delay; 3555 3556 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3557 /* When the input system is 2401, always enable 'in_frameinfo_memory' 3558 * except for the following: online or continuous 3559 */ 3560 need_in_frameinfo_memory = !(pipe->stream->config.online || 3561 pipe->stream->config.continuous); 3562 #else 3563 /* Construct in_frame info (only in case we have dynamic input */ 3564 need_in_frameinfo_memory = pipe->stream->config.mode == 3565 IA_CSS_INPUT_MODE_MEMORY; 3566 #endif 3567 3568 /* Construct in_frame info (only in case we have dynamic input */ 3569 if (need_in_frameinfo_memory) { 3570 in_frame = &pipe->in_frame_struct; 3571 err = init_in_frameinfo_memory_defaults(pipe, in_frame, 3572 IA_CSS_FRAME_FORMAT_RAW); 3573 if (err) 3574 goto ERR; 3575 } 3576 3577 out_frame->data = 0; 3578 err = init_out_frameinfo_defaults(pipe, out_frame, 0); 3579 if (err) 3580 goto ERR; 3581 3582 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 3583 vf_frame = &pipe->vf_frame_struct; 3584 vf_frame->data = 0; 3585 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0); 3586 if (err) 3587 goto ERR; 3588 } 3589 3590 copy_binary = &pipe->pipe_settings.video.copy_binary; 3591 video_binary = &pipe->pipe_settings.video.video_binary; 3592 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary; 3593 num_output_pins = video_binary->info->num_output_pins; 3594 3595 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary; 3596 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler; 3597 is_output_stage = pipe->pipe_settings.video.is_output_stage; 3598 3599 need_copy = (copy_binary && copy_binary->info); 3600 need_vf_pp = (vf_pp_binary && vf_pp_binary->info); 3601 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info); 3602 3603 if (need_copy) { 3604 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 3605 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 3606 out_frames, NULL, NULL); 3607 err = ia_css_pipeline_create_and_add_stage(me, 3608 &stage_desc, 3609 ©_stage); 3610 if (err) 3611 goto ERR; 3612 in_frame = me->stages->args.out_frame[0]; 3613 } else if (pipe->stream->config.continuous) { 3614 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3615 /* When continuous is enabled, configure in_frame with the 3616 * last pipe, which is the copy pipe. 3617 */ 3618 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 3619 #else 3620 in_frame = pipe->continuous_frames[0]; 3621 #endif 3622 } 3623 3624 ia_css_pipe_util_set_output_frames(out_frames, 0, 3625 need_yuv_pp ? NULL : out_frame); 3626 3627 /* when the video binary supports a second output pin, 3628 it can directly produce the vf_frame. */ 3629 if (need_vf_pp) { 3630 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary, 3631 out_frames, in_frame, NULL); 3632 } else { 3633 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary, 3634 out_frames, in_frame, vf_frame); 3635 } 3636 err = ia_css_pipeline_create_and_add_stage(me, 3637 &stage_desc, 3638 &video_stage); 3639 if (err) 3640 goto ERR; 3641 3642 /* If we use copy iso video, the input must be yuv iso raw */ 3643 if (video_stage) { 3644 video_stage->args.copy_vf = 3645 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY; 3646 video_stage->args.copy_output = video_stage->args.copy_vf; 3647 } 3648 3649 /* when the video binary supports only 1 output pin, vf_pp is needed to 3650 produce the vf_frame.*/ 3651 if (need_vf_pp && video_stage) { 3652 in_frame = video_stage->args.out_vf_frame; 3653 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary, 3654 &vf_pp_stage); 3655 if (err) 3656 goto ERR; 3657 } 3658 if (video_stage) { 3659 int frm; 3660 3661 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) { 3662 video_stage->args.tnr_frames[frm] = 3663 pipe->pipe_settings.video.tnr_frames[frm]; 3664 } 3665 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) { 3666 video_stage->args.delay_frames[frm] = 3667 pipe->pipe_settings.video.delay_frames[frm]; 3668 } 3669 } 3670 3671 /* Append Extension on Video out, if enabled */ 3672 if (!need_vf_pp && video_stage && pipe->config.acc_extension && 3673 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) { 3674 struct ia_css_frame *out = NULL; 3675 struct ia_css_frame *in = NULL; 3676 3677 if ((pipe->config.acc_extension->info.isp.sp.enable.output) && 3678 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) && 3679 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) { 3680 /* In/Out Frame mapping to support output frame extension.*/ 3681 out = video_stage->args.out_frame[0]; 3682 err = ia_css_frame_allocate_from_info(&in, &pipe->output_info[0]); 3683 if (err) 3684 goto ERR; 3685 video_stage->args.out_frame[0] = in; 3686 } 3687 3688 err = add_firmwares(me, video_binary, pipe->output_stage, 3689 last_output_firmware(pipe->output_stage), 3690 IA_CSS_BINARY_MODE_VIDEO, 3691 in, out, NULL, &video_stage, NULL); 3692 if (err) 3693 goto ERR; 3694 } 3695 3696 if (need_yuv_pp && video_stage) { 3697 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0]; 3698 struct ia_css_frame *tmp_out_frame = NULL; 3699 3700 for (i = 0; i < num_yuv_scaler; i++) { 3701 if (is_output_stage[i] == true) { 3702 tmp_out_frame = out_frame; 3703 } else { 3704 tmp_out_frame = NULL; 3705 } 3706 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, 3707 NULL, 3708 &yuv_scaler_binary[i], 3709 &yuv_scaler_stage); 3710 3711 if (err) { 3712 IA_CSS_LEAVE_ERR_PRIVATE(err); 3713 return err; 3714 } 3715 /* we use output port 1 as internal output port */ 3716 if (yuv_scaler_stage) 3717 tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; 3718 } 3719 } 3720 3721 pipe->pipeline.acquire_isp_each_stage = false; 3722 ia_css_pipeline_finalize_stages(&pipe->pipeline, 3723 pipe->stream->config.continuous); 3724 3725 ERR: 3726 IA_CSS_LEAVE_ERR_PRIVATE(err); 3727 return err; 3728 } 3729 3730 static int 3731 create_host_acc_pipeline(struct ia_css_pipe *pipe) { 3732 int err = 0; 3733 const struct ia_css_fw_info *fw; 3734 unsigned int i; 3735 3736 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 3737 if ((!pipe) || (!pipe->stream)) 3738 { 3739 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 3740 return -EINVAL; 3741 } 3742 3743 pipe->pipeline.num_execs = pipe->config.acc_num_execs; 3744 /* Reset pipe_qos_config to default disable all QOS extension stages */ 3745 if (pipe->config.acc_extension) 3746 pipe->pipeline.pipe_qos_config = 0; 3747 3748 fw = pipe->vf_stage; 3749 for (i = 0; fw; fw = fw->next) 3750 { 3751 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw); 3752 if (err) 3753 goto ERR; 3754 } 3755 3756 for (i = 0; i < pipe->config.num_acc_stages; i++) 3757 { 3758 struct ia_css_fw_info *fw = pipe->config.acc_stages[i]; 3759 3760 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw); 3761 if (err) 3762 goto ERR; 3763 } 3764 3765 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 3766 3767 ERR: 3768 IA_CSS_LEAVE_ERR_PRIVATE(err); 3769 return err; 3770 } 3771 3772 /* Create stages for preview */ 3773 static int 3774 create_host_preview_pipeline(struct ia_css_pipe *pipe) { 3775 struct ia_css_pipeline_stage *copy_stage = NULL; 3776 struct ia_css_pipeline_stage *preview_stage = NULL; 3777 struct ia_css_pipeline_stage *vf_pp_stage = NULL; 3778 struct ia_css_pipeline_stage_desc stage_desc; 3779 struct ia_css_pipeline *me = NULL; 3780 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL; 3781 struct ia_css_frame *in_frame = NULL; 3782 int err = 0; 3783 struct ia_css_frame *out_frame; 3784 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 3785 bool need_in_frameinfo_memory = false; 3786 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3787 bool sensor = false; 3788 bool buffered_sensor = false; 3789 bool online = false; 3790 bool continuous = false; 3791 #endif 3792 3793 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 3794 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) 3795 { 3796 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 3797 return -EINVAL; 3798 } 3799 3800 ia_css_pipe_util_create_output_frames(out_frames); 3801 /* pipeline already created as part of create_host_pipeline_structure */ 3802 me = &pipe->pipeline; 3803 ia_css_pipeline_clean(me); 3804 3805 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3806 /* When the input system is 2401, always enable 'in_frameinfo_memory' 3807 * except for the following: 3808 * - Direct Sensor Mode Online Preview 3809 * - Buffered Sensor Mode Online Preview 3810 * - Direct Sensor Mode Continuous Preview 3811 * - Buffered Sensor Mode Continuous Preview 3812 */ 3813 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); 3814 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 3815 online = pipe->stream->config.online; 3816 continuous = pipe->stream->config.continuous; 3817 need_in_frameinfo_memory = 3818 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); 3819 #else 3820 /* Construct in_frame info (only in case we have dynamic input */ 3821 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 3822 #endif 3823 if (need_in_frameinfo_memory) 3824 { 3825 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, 3826 IA_CSS_FRAME_FORMAT_RAW); 3827 if (err) 3828 goto ERR; 3829 3830 in_frame = &me->in_frame; 3831 } else 3832 { 3833 in_frame = NULL; 3834 } 3835 3836 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); 3837 if (err) 3838 goto ERR; 3839 out_frame = &me->out_frame[0]; 3840 3841 copy_binary = &pipe->pipe_settings.preview.copy_binary; 3842 preview_binary = &pipe->pipe_settings.preview.preview_binary; 3843 if (pipe->pipe_settings.preview.vf_pp_binary.info) 3844 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary; 3845 3846 if (pipe->pipe_settings.preview.copy_binary.info) 3847 { 3848 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 3849 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 3850 out_frames, NULL, NULL); 3851 err = ia_css_pipeline_create_and_add_stage(me, 3852 &stage_desc, 3853 ©_stage); 3854 if (err) 3855 goto ERR; 3856 in_frame = me->stages->args.out_frame[0]; 3857 #ifndef ISP2401 3858 } else 3859 { 3860 #else 3861 } else if (pipe->stream->config.continuous) 3862 { 3863 #endif 3864 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3865 /* When continuous is enabled, configure in_frame with the 3866 * last pipe, which is the copy pipe. 3867 */ 3868 if (continuous || !online) { 3869 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 3870 } 3871 #else 3872 in_frame = pipe->continuous_frames[0]; 3873 #endif 3874 } 3875 3876 if (vf_pp_binary) 3877 { 3878 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 3879 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, 3880 out_frames, in_frame, NULL); 3881 } else 3882 { 3883 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 3884 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, 3885 out_frames, in_frame, NULL); 3886 } 3887 err = ia_css_pipeline_create_and_add_stage(me, 3888 &stage_desc, 3889 &preview_stage); 3890 if (err) 3891 goto ERR; 3892 /* If we use copy iso preview, the input must be yuv iso raw */ 3893 preview_stage->args.copy_vf = 3894 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY; 3895 preview_stage->args.copy_output = !preview_stage->args.copy_vf; 3896 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) 3897 { 3898 /* in case of copy, use the vf frame as output frame */ 3899 preview_stage->args.out_vf_frame = 3900 preview_stage->args.out_frame[0]; 3901 } 3902 if (vf_pp_binary) 3903 { 3904 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY) 3905 in_frame = preview_stage->args.out_vf_frame; 3906 else 3907 in_frame = preview_stage->args.out_frame[0]; 3908 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary, 3909 &vf_pp_stage); 3910 if (err) 3911 goto ERR; 3912 } 3913 3914 pipe->pipeline.acquire_isp_each_stage = false; 3915 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 3916 3917 ERR: 3918 IA_CSS_LEAVE_ERR_PRIVATE(err); 3919 return err; 3920 } 3921 3922 static void send_raw_frames(struct ia_css_pipe *pipe) 3923 { 3924 if (pipe->stream->config.continuous) { 3925 unsigned int i; 3926 3927 sh_css_update_host2sp_cont_num_raw_frames 3928 (pipe->stream->config.init_num_cont_raw_buf, true); 3929 sh_css_update_host2sp_cont_num_raw_frames 3930 (pipe->stream->config.target_num_cont_raw_buf, false); 3931 3932 /* Hand-over all the SP-internal buffers */ 3933 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) { 3934 sh_css_update_host2sp_offline_frame(i, 3935 pipe->continuous_frames[i], pipe->cont_md_buffers[i]); 3936 } 3937 } 3938 3939 return; 3940 } 3941 3942 static int 3943 preview_start(struct ia_css_pipe *pipe) { 3944 struct ia_css_pipeline *me; 3945 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL; 3946 int err = 0; 3947 struct ia_css_pipe *copy_pipe, *capture_pipe; 3948 struct ia_css_pipe *acc_pipe; 3949 enum sh_css_pipe_config_override copy_ovrd; 3950 enum ia_css_input_mode preview_pipe_input_mode; 3951 const struct ia_css_coordinate *coord = NULL; 3952 const struct ia_css_isp_parameters *params = NULL; 3953 3954 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 3955 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) 3956 { 3957 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 3958 return -EINVAL; 3959 } 3960 3961 me = &pipe->pipeline; 3962 3963 preview_pipe_input_mode = pipe->stream->config.mode; 3964 3965 copy_pipe = pipe->pipe_settings.preview.copy_pipe; 3966 capture_pipe = pipe->pipe_settings.preview.capture_pipe; 3967 acc_pipe = pipe->pipe_settings.preview.acc_pipe; 3968 3969 copy_binary = &pipe->pipe_settings.preview.copy_binary; 3970 preview_binary = &pipe->pipe_settings.preview.preview_binary; 3971 if (pipe->pipe_settings.preview.vf_pp_binary.info) 3972 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary; 3973 3974 sh_css_metrics_start_frame(); 3975 3976 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 3977 /* multi stream video needs mipi buffers */ 3978 err = send_mipi_frames(pipe); 3979 if (err) { 3980 IA_CSS_LEAVE_ERR_PRIVATE(err); 3981 return err; 3982 } 3983 #endif 3984 send_raw_frames(pipe); 3985 3986 { 3987 unsigned int thread_id; 3988 3989 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 3990 copy_ovrd = 1 << thread_id; 3991 3992 if (pipe->stream->cont_capt) 3993 { 3994 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), 3995 &thread_id); 3996 copy_ovrd |= 1 << thread_id; 3997 } 3998 } 3999 4000 if (IS_ISP2401) { 4001 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl; 4002 params = pipe->stream->isp_params_configs; 4003 } 4004 4005 /* Construct and load the copy pipe */ 4006 if (pipe->stream->config.continuous) 4007 { 4008 sh_css_sp_init_pipeline(©_pipe->pipeline, 4009 IA_CSS_PIPE_ID_COPY, 4010 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe), 4011 false, 4012 pipe->stream->config.pixels_per_clock == 2, false, 4013 false, pipe->required_bds_factor, 4014 copy_ovrd, 4015 pipe->stream->config.mode, 4016 &pipe->stream->config.metadata_config, 4017 &pipe->stream->info.metadata_info, 4018 pipe->stream->config.source.port.port, 4019 coord, 4020 params); 4021 4022 /* make the preview pipe start with mem mode input, copy handles 4023 the actual mode */ 4024 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; 4025 } 4026 4027 /* Construct and load the capture pipe */ 4028 if (pipe->stream->cont_capt) 4029 { 4030 sh_css_sp_init_pipeline(&capture_pipe->pipeline, 4031 IA_CSS_PIPE_ID_CAPTURE, 4032 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe), 4033 capture_pipe->config.default_capture_config.enable_xnr != 0, 4034 capture_pipe->stream->config.pixels_per_clock == 2, 4035 true, /* continuous */ 4036 false, /* offline */ 4037 capture_pipe->required_bds_factor, 4038 0, 4039 IA_CSS_INPUT_MODE_MEMORY, 4040 &pipe->stream->config.metadata_config, 4041 &pipe->stream->info.metadata_info, 4042 (enum mipi_port_id)0, 4043 coord, 4044 params); 4045 } 4046 4047 if (acc_pipe) 4048 { 4049 sh_css_sp_init_pipeline(&acc_pipe->pipeline, 4050 IA_CSS_PIPE_ID_ACC, 4051 (uint8_t)ia_css_pipe_get_pipe_num(acc_pipe), 4052 false, 4053 pipe->stream->config.pixels_per_clock == 2, 4054 false, /* continuous */ 4055 false, /* offline */ 4056 pipe->required_bds_factor, 4057 0, 4058 IA_CSS_INPUT_MODE_MEMORY, 4059 NULL, 4060 NULL, 4061 (enum mipi_port_id)0, 4062 coord, 4063 params); 4064 } 4065 4066 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode); 4067 4068 IA_CSS_LEAVE_ERR_PRIVATE(err); 4069 return err; 4070 } 4071 4072 int 4073 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, 4074 const struct ia_css_buffer *buffer) { 4075 int return_err = 0; 4076 unsigned int thread_id; 4077 enum sh_css_queue_id queue_id; 4078 struct ia_css_pipeline *pipeline; 4079 struct ia_css_pipeline_stage *stage; 4080 struct ia_css_rmgr_vbuf_handle p_vbuf; 4081 struct ia_css_rmgr_vbuf_handle *h_vbuf; 4082 struct sh_css_hmm_buffer ddr_buffer; 4083 enum ia_css_buffer_type buf_type; 4084 enum ia_css_pipe_id pipe_id; 4085 bool ret_err; 4086 4087 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer); 4088 4089 if ((!pipe) || (!buffer)) 4090 { 4091 IA_CSS_LEAVE_ERR(-EINVAL); 4092 return -EINVAL; 4093 } 4094 4095 buf_type = buffer->type; 4096 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME 4097 is removed */ 4098 #if 0 4099 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 4100 { 4101 bool found_pipe = false; 4102 4103 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 4104 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) && 4105 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) { 4106 buf_type += i; 4107 found_pipe = true; 4108 break; 4109 } 4110 } 4111 if (!found_pipe) 4112 return -EINVAL; 4113 } 4114 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) 4115 { 4116 bool found_pipe = false; 4117 4118 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 4119 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) && 4120 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) { 4121 buf_type += i; 4122 found_pipe = true; 4123 break; 4124 } 4125 } 4126 if (!found_pipe) 4127 return -EINVAL; 4128 } 4129 #endif 4130 pipe_id = pipe->mode; 4131 4132 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type); 4133 4134 assert(pipe_id < IA_CSS_PIPE_ID_NUM); 4135 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE); 4136 if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) || 4137 (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) || 4138 (pipe_id >= IA_CSS_PIPE_ID_NUM)) 4139 { 4140 IA_CSS_LEAVE_ERR(-EINVAL); 4141 return -EINVAL; 4142 } 4143 4144 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 4145 if (!ret_err) 4146 { 4147 IA_CSS_LEAVE_ERR(-EINVAL); 4148 return -EINVAL; 4149 } 4150 4151 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id); 4152 if (!ret_err) 4153 { 4154 IA_CSS_LEAVE_ERR(-EINVAL); 4155 return -EINVAL; 4156 } 4157 4158 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) 4159 { 4160 IA_CSS_LEAVE_ERR(-EINVAL); 4161 return -EINVAL; 4162 } 4163 4164 if (!sh_css_sp_is_running()) 4165 { 4166 IA_CSS_LOG("SP is not running!"); 4167 IA_CSS_LEAVE_ERR(-EBUSY); 4168 /* SP is not running. The queues are not valid */ 4169 return -EBUSY; 4170 } 4171 4172 pipeline = &pipe->pipeline; 4173 4174 assert(pipeline || 4175 pipe_id == IA_CSS_PIPE_ID_COPY || 4176 pipe_id == IA_CSS_PIPE_ID_ACC); 4177 4178 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr)); 4179 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL); 4180 ddr_buffer.cookie_ptr = buffer->driver_cookie; 4181 ddr_buffer.timing_data = buffer->timing_data; 4182 4183 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) 4184 { 4185 if (!buffer->data.stats_3a) { 4186 IA_CSS_LEAVE_ERR(-EINVAL); 4187 return -EINVAL; 4188 } 4189 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a); 4190 ddr_buffer.payload.s3a = *buffer->data.stats_3a; 4191 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) 4192 { 4193 if (!buffer->data.stats_dvs) { 4194 IA_CSS_LEAVE_ERR(-EINVAL); 4195 return -EINVAL; 4196 } 4197 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs); 4198 ddr_buffer.payload.dis = *buffer->data.stats_dvs; 4199 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) 4200 { 4201 if (!buffer->data.metadata) { 4202 IA_CSS_LEAVE_ERR(-EINVAL); 4203 return -EINVAL; 4204 } 4205 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata); 4206 ddr_buffer.payload.metadata = *buffer->data.metadata; 4207 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME) 4208 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 4209 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) 4210 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME) 4211 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)) 4212 { 4213 if (!buffer->data.frame) { 4214 IA_CSS_LEAVE_ERR(-EINVAL); 4215 return -EINVAL; 4216 } 4217 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame); 4218 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data; 4219 ddr_buffer.payload.frame.flashed = 0; 4220 4221 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 4222 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n", 4223 buf_type, buffer->data.frame->data); 4224 4225 #if CONFIG_ON_FRAME_ENQUEUE() 4226 return_err = set_config_on_frame_enqueue( 4227 &buffer->data.frame->info, 4228 &ddr_buffer.payload.frame); 4229 if (return_err) { 4230 IA_CSS_LEAVE_ERR(return_err); 4231 return return_err; 4232 } 4233 #endif 4234 } 4235 4236 /* start of test for using rmgr for acq/rel memory */ 4237 p_vbuf.vptr = 0; 4238 p_vbuf.count = 0; 4239 p_vbuf.size = sizeof(struct sh_css_hmm_buffer); 4240 h_vbuf = &p_vbuf; 4241 /* TODO: change next to correct pool for optimization */ 4242 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf); 4243 4244 assert(h_vbuf); 4245 assert(h_vbuf->vptr != 0x0); 4246 4247 if ((!h_vbuf) || (h_vbuf->vptr == 0x0)) 4248 { 4249 IA_CSS_LEAVE_ERR(-EINVAL); 4250 return -EINVAL; 4251 } 4252 4253 hmm_store(h_vbuf->vptr, 4254 (void *)(&ddr_buffer), 4255 sizeof(struct sh_css_hmm_buffer)); 4256 if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) 4257 || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) 4258 || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) 4259 { 4260 if (!pipeline) { 4261 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf); 4262 IA_CSS_LOG("pipeline is empty!"); 4263 IA_CSS_LEAVE_ERR(-EINVAL); 4264 return -EINVAL; 4265 } 4266 4267 for (stage = pipeline->stages; stage; stage = stage->next) { 4268 /* The SP will read the params 4269 after it got empty 3a and dis */ 4270 if (STATS_ENABLED(stage)) { 4271 /* there is a stage that needs it */ 4272 return_err = ia_css_bufq_enqueue_buffer(thread_id, 4273 queue_id, 4274 (uint32_t)h_vbuf->vptr); 4275 } 4276 } 4277 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME) 4278 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 4279 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) 4280 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME) 4281 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME) 4282 || (buf_type == IA_CSS_BUFFER_TYPE_METADATA)) 4283 { 4284 return_err = ia_css_bufq_enqueue_buffer(thread_id, 4285 queue_id, 4286 (uint32_t)h_vbuf->vptr); 4287 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) 4288 if (!(return_err) && 4289 (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)) { 4290 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d", 4291 ddr_buffer.payload.frame.frame_data, 4292 queue_id, thread_id); 4293 } 4294 #endif 4295 } 4296 4297 if (!return_err) 4298 { 4299 if (sh_css_hmm_buffer_record_acquire( 4300 h_vbuf, buf_type, 4301 HOST_ADDRESS(ddr_buffer.kernel_ptr))) { 4302 IA_CSS_LOG("send vbuf=%p", h_vbuf); 4303 } else { 4304 return_err = -EINVAL; 4305 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n"); 4306 } 4307 } 4308 4309 /* 4310 * Tell the SP which queues are not empty, 4311 * by sending the software event. 4312 */ 4313 if (!return_err) 4314 { 4315 if (!sh_css_sp_is_running()) { 4316 /* SP is not running. The queues are not valid */ 4317 IA_CSS_LOG("SP is not running!"); 4318 IA_CSS_LEAVE_ERR(-EBUSY); 4319 return -EBUSY; 4320 } 4321 return_err = ia_css_bufq_enqueue_psys_event( 4322 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED, 4323 (uint8_t)thread_id, 4324 queue_id, 4325 0); 4326 } else 4327 { 4328 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf); 4329 IA_CSS_ERROR("buffer not enqueued"); 4330 } 4331 4332 IA_CSS_LEAVE("return value = %d", return_err); 4333 4334 return return_err; 4335 } 4336 4337 /* 4338 * TODO: Free up the hmm memory space. 4339 */ 4340 int 4341 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, 4342 struct ia_css_buffer *buffer) { 4343 int return_err; 4344 enum sh_css_queue_id queue_id; 4345 ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0; 4346 struct sh_css_hmm_buffer ddr_buffer; 4347 enum ia_css_buffer_type buf_type; 4348 enum ia_css_pipe_id pipe_id; 4349 unsigned int thread_id; 4350 hrt_address kernel_ptr = 0; 4351 bool ret_err; 4352 4353 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer); 4354 4355 if ((!pipe) || (!buffer)) 4356 { 4357 IA_CSS_LEAVE_ERR(-EINVAL); 4358 return -EINVAL; 4359 } 4360 4361 pipe_id = pipe->mode; 4362 4363 buf_type = buffer->type; 4364 4365 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type); 4366 4367 ddr_buffer.kernel_ptr = 0; 4368 4369 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 4370 if (!ret_err) 4371 { 4372 IA_CSS_LEAVE_ERR(-EINVAL); 4373 return -EINVAL; 4374 } 4375 4376 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id); 4377 if (!ret_err) 4378 { 4379 IA_CSS_LEAVE_ERR(-EINVAL); 4380 return -EINVAL; 4381 } 4382 4383 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) 4384 { 4385 IA_CSS_LEAVE_ERR(-EINVAL); 4386 return -EINVAL; 4387 } 4388 4389 if (!sh_css_sp_is_running()) 4390 { 4391 IA_CSS_LOG("SP is not running!"); 4392 IA_CSS_LEAVE_ERR(-EBUSY); 4393 /* SP is not running. The queues are not valid */ 4394 return -EBUSY; 4395 } 4396 4397 return_err = ia_css_bufq_dequeue_buffer(queue_id, 4398 (uint32_t *)&ddr_buffer_addr); 4399 4400 if (!return_err) 4401 { 4402 struct ia_css_frame *frame; 4403 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL; 4404 4405 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr); 4406 4407 /* Validate the ddr_buffer_addr and buf_type */ 4408 hmm_buffer_record = sh_css_hmm_buffer_record_validate( 4409 ddr_buffer_addr, buf_type); 4410 if (hmm_buffer_record) { 4411 /* valid hmm_buffer_record found. Save the kernel_ptr 4412 * for validation after performing hmm_load. The 4413 * vbuf handle and buffer_record can be released. 4414 */ 4415 kernel_ptr = hmm_buffer_record->kernel_ptr; 4416 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf); 4417 sh_css_hmm_buffer_record_reset(hmm_buffer_record); 4418 } else { 4419 IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)", 4420 ddr_buffer_addr, buf_type); 4421 IA_CSS_LEAVE_ERR(-EINVAL); 4422 return -EINVAL; 4423 } 4424 4425 hmm_load(ddr_buffer_addr, 4426 &ddr_buffer, 4427 sizeof(struct sh_css_hmm_buffer)); 4428 4429 /* if the kernel_ptr is 0 or an invalid, return an error. 4430 * do not access the buffer via the kernal_ptr. 4431 */ 4432 if ((ddr_buffer.kernel_ptr == 0) || 4433 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) { 4434 IA_CSS_ERROR("kernel_ptr invalid"); 4435 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr); 4436 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr)); 4437 IA_CSS_ERROR("buf_type: %d\n", buf_type); 4438 IA_CSS_LEAVE_ERR(-EINVAL); 4439 return -EINVAL; 4440 } 4441 4442 if (ddr_buffer.kernel_ptr != 0) { 4443 /* buffer->exp_id : all instances to be removed later once the driver change 4444 * is completed. See patch #5758 for reference */ 4445 buffer->exp_id = 0; 4446 buffer->driver_cookie = ddr_buffer.cookie_ptr; 4447 buffer->timing_data = ddr_buffer.timing_data; 4448 4449 if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) || 4450 (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) { 4451 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick; 4452 } 4453 4454 switch (buf_type) { 4455 case IA_CSS_BUFFER_TYPE_INPUT_FRAME: 4456 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: 4457 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: 4458 if ((pipe) && (pipe->stop_requested == true)) { 4459 #if defined(USE_INPUT_SYSTEM_VERSION_2) 4460 /* free mipi frames only for old input system 4461 * for 2401 it is done in ia_css_stream_destroy call 4462 */ 4463 return_err = free_mipi_frames(pipe); 4464 if (return_err) { 4465 IA_CSS_LOG("free_mipi_frames() failed"); 4466 IA_CSS_LEAVE_ERR(return_err); 4467 return return_err; 4468 } 4469 #endif 4470 pipe->stop_requested = false; 4471 } 4472 /* fall through */ 4473 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME: 4474 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME: 4475 frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr); 4476 buffer->data.frame = frame; 4477 buffer->exp_id = ddr_buffer.payload.frame.exp_id; 4478 frame->exp_id = ddr_buffer.payload.frame.exp_id; 4479 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id; 4480 if (ddr_buffer.payload.frame.flashed == 1) 4481 frame->flash_state = 4482 IA_CSS_FRAME_FLASH_STATE_PARTIAL; 4483 if (ddr_buffer.payload.frame.flashed == 2) 4484 frame->flash_state = 4485 IA_CSS_FRAME_FLASH_STATE_FULL; 4486 frame->valid = pipe->num_invalid_frames == 0; 4487 if (!frame->valid) 4488 pipe->num_invalid_frames--; 4489 4490 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) { 4491 #ifdef USE_INPUT_SYSTEM_VERSION_2401 4492 frame->planes.binary.size = frame->data_bytes; 4493 #else 4494 frame->planes.binary.size = 4495 sh_css_sp_get_binary_copy_size(); 4496 #endif 4497 } 4498 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) 4499 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { 4500 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d", 4501 frame->data, frame->isp_config_id, thread_id); 4502 } 4503 #endif 4504 4505 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 4506 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n", 4507 buf_type, buffer->data.frame->data); 4508 4509 break; 4510 case IA_CSS_BUFFER_TYPE_3A_STATISTICS: 4511 buffer->data.stats_3a = 4512 (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr); 4513 buffer->exp_id = ddr_buffer.payload.s3a.exp_id; 4514 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id; 4515 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id; 4516 break; 4517 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS: 4518 buffer->data.stats_dvs = 4519 (struct ia_css_isp_dvs_statistics *) 4520 HOST_ADDRESS(ddr_buffer.kernel_ptr); 4521 buffer->exp_id = ddr_buffer.payload.dis.exp_id; 4522 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id; 4523 break; 4524 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS: 4525 break; 4526 case IA_CSS_BUFFER_TYPE_METADATA: 4527 buffer->data.metadata = 4528 (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr); 4529 buffer->exp_id = ddr_buffer.payload.metadata.exp_id; 4530 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id; 4531 break; 4532 default: 4533 return_err = -EINVAL; 4534 break; 4535 } 4536 } 4537 } 4538 4539 /* 4540 * Tell the SP which queues are not full, 4541 * by sending the software event. 4542 */ 4543 if (!return_err) 4544 { 4545 if (!sh_css_sp_is_running()) { 4546 IA_CSS_LOG("SP is not running!"); 4547 IA_CSS_LEAVE_ERR(-EBUSY); 4548 /* SP is not running. The queues are not valid */ 4549 return -EBUSY; 4550 } 4551 ia_css_bufq_enqueue_psys_event( 4552 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED, 4553 0, 4554 queue_id, 4555 0); 4556 } 4557 IA_CSS_LEAVE("buffer=%p", buffer); 4558 4559 return return_err; 4560 } 4561 4562 /* 4563 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h 4564 * TODO: modify and move it if possible. 4565 * 4566 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC: 4567 * 1) "enum ia_css_event_type" (ia_css_event_public.h) 4568 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h) 4569 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c) 4570 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c) 4571 */ 4572 static enum ia_css_event_type convert_event_sp_to_host_domain[] = { 4573 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */ 4574 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */ 4575 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */ 4576 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */ 4577 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */ 4578 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */ 4579 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */ 4580 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */ 4581 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */ 4582 IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */ 4583 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */ 4584 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */ 4585 IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */ 4586 IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */ 4587 IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */ 4588 IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */ 4589 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */ 4590 }; 4591 4592 int 4593 ia_css_dequeue_event(struct ia_css_event *event) { 4594 return ia_css_dequeue_psys_event(event); 4595 } 4596 4597 int 4598 ia_css_dequeue_psys_event(struct ia_css_event *event) { 4599 enum ia_css_pipe_id pipe_id = 0; 4600 u8 payload[4] = {0, 0, 0, 0}; 4601 int ret_err; 4602 4603 /*TODO: 4604 * a) use generic decoding function , same as the one used by sp. 4605 * b) group decode and dequeue into eventQueue module 4606 * 4607 * We skip the IA_CSS_ENTER logging call 4608 * to avoid flooding the logs when the host application 4609 * uses polling. */ 4610 if (!event) 4611 return -EINVAL; 4612 4613 if (!sh_css_sp_is_running()) 4614 { 4615 /* SP is not running. The queues are not valid */ 4616 return -EBUSY; 4617 } 4618 4619 /* dequeue the event (if any) from the psys event queue */ 4620 ret_err = ia_css_bufq_dequeue_psys_event(payload); 4621 if (ret_err) 4622 return ret_err; 4623 4624 IA_CSS_LOG("event dequeued from psys event queue"); 4625 4626 /* Tell the SP that we dequeued an event from the event queue. */ 4627 ia_css_bufq_enqueue_psys_event( 4628 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0); 4629 4630 /* Events are decoded into 4 bytes of payload, the first byte 4631 * contains the sp event type. This is converted to a host enum. 4632 * TODO: can this enum conversion be eliminated */ 4633 event->type = convert_event_sp_to_host_domain[payload[0]]; 4634 /* Some sane default values since not all events use all fields. */ 4635 event->pipe = NULL; 4636 event->port = MIPI_PORT0_ID; 4637 event->exp_id = 0; 4638 event->fw_warning = IA_CSS_FW_WARNING_NONE; 4639 event->fw_handle = 0; 4640 event->timer_data = 0; 4641 event->timer_code = 0; 4642 event->timer_subcode = 0; 4643 4644 if (event->type == IA_CSS_EVENT_TYPE_TIMER) 4645 { 4646 /* timer event ??? get the 2nd event and decode the data into the event struct */ 4647 u32 tmp_data; 4648 /* 1st event: LSB 16-bit timer data and code */ 4649 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8)); 4650 event->timer_code = payload[2]; 4651 payload[0] = payload[1] = payload[2] = payload[3] = 0; 4652 ret_err = ia_css_bufq_dequeue_psys_event(payload); 4653 if (ret_err) { 4654 /* no 2nd event ??? an error */ 4655 /* Putting IA_CSS_ERROR is resulting in failures in 4656 * Merrifield smoke testing */ 4657 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n"); 4658 return ret_err; 4659 } 4660 ia_css_bufq_enqueue_psys_event( 4661 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0); 4662 event->type = convert_event_sp_to_host_domain[payload[0]]; 4663 /* It's a timer */ 4664 if (event->type == IA_CSS_EVENT_TYPE_TIMER) { 4665 /* 2nd event data: MSB 16-bit timer and subcode */ 4666 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8)); 4667 event->timer_data |= (tmp_data << 16); 4668 event->timer_subcode = payload[2]; 4669 } 4670 /* It's a non timer event. So clear first half of the timer event data. 4671 * If the second part of the TIMER event is not received, we discard 4672 * the first half of the timer data and process the non timer event without 4673 * affecting the flow. So the non timer event falls through 4674 * the code. */ 4675 else { 4676 event->timer_data = 0; 4677 event->timer_code = 0; 4678 event->timer_subcode = 0; 4679 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded"); 4680 } 4681 } 4682 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) 4683 { 4684 event->port = (enum mipi_port_id)payload[1]; 4685 event->exp_id = payload[3]; 4686 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) 4687 { 4688 event->fw_warning = (enum ia_css_fw_warning)payload[1]; 4689 /* exp_id is only available in these warning types */ 4690 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED || 4691 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED) 4692 event->exp_id = payload[3]; 4693 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) 4694 { 4695 event->fw_assert_module_id = payload[1]; /* module */ 4696 event->fw_assert_line_no = (payload[2] << 8) + payload[3]; 4697 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */ 4698 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) 4699 { 4700 /* pipe related events. 4701 * payload[1] contains the pipe_num, 4702 * payload[2] contains the pipe_id. These are different. */ 4703 event->pipe = find_pipe_by_num(payload[1]); 4704 pipe_id = (enum ia_css_pipe_id)payload[2]; 4705 /* Check to see if pipe still exists */ 4706 if (!event->pipe) 4707 return -EBUSY; 4708 4709 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) { 4710 /* find the capture pipe that goes with this */ 4711 int i, n; 4712 4713 n = event->pipe->stream->num_pipes; 4714 for (i = 0; i < n; i++) { 4715 struct ia_css_pipe *p = 4716 event->pipe->stream->pipes[i]; 4717 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { 4718 event->pipe = p; 4719 break; 4720 } 4721 } 4722 event->exp_id = payload[3]; 4723 } 4724 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) { 4725 /* payload[3] contains the acc fw handle. */ 4726 u32 stage_num = (uint32_t)payload[3]; 4727 4728 ret_err = ia_css_pipeline_get_fw_from_stage( 4729 &event->pipe->pipeline, 4730 stage_num, 4731 &event->fw_handle); 4732 if (ret_err) { 4733 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u", 4734 stage_num); 4735 return ret_err; 4736 } 4737 } 4738 } 4739 4740 if (event->pipe) 4741 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id); 4742 else 4743 IA_CSS_LEAVE("event_id=%d", event->type); 4744 4745 return 0; 4746 } 4747 4748 int 4749 ia_css_dequeue_isys_event(struct ia_css_event *event) { 4750 u8 payload[4] = {0, 0, 0, 0}; 4751 int err = 0; 4752 4753 /* We skip the IA_CSS_ENTER logging call 4754 * to avoid flooding the logs when the host application 4755 * uses polling. */ 4756 if (!event) 4757 return -EINVAL; 4758 4759 if (!sh_css_sp_is_running()) 4760 { 4761 /* SP is not running. The queues are not valid */ 4762 return -EBUSY; 4763 } 4764 4765 err = ia_css_bufq_dequeue_isys_event(payload); 4766 if (err) 4767 return err; 4768 4769 IA_CSS_LOG("event dequeued from isys event queue"); 4770 4771 /* Update SP state to indicate that element was dequeued. */ 4772 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED); 4773 4774 /* Fill return struct with appropriate info */ 4775 event->type = IA_CSS_EVENT_TYPE_PORT_EOF; 4776 /* EOF events are associated with a CSI port, not with a pipe */ 4777 event->pipe = NULL; 4778 event->port = payload[1]; 4779 event->exp_id = payload[3]; 4780 4781 IA_CSS_LEAVE_ERR(err); 4782 return err; 4783 } 4784 4785 static void 4786 acc_start(struct ia_css_pipe *pipe) 4787 { 4788 assert(pipe); 4789 assert(pipe->stream); 4790 4791 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD, 4792 pipe->stream->config.mode); 4793 } 4794 4795 static int 4796 sh_css_pipe_start(struct ia_css_stream *stream) { 4797 int err = 0; 4798 4799 struct ia_css_pipe *pipe; 4800 enum ia_css_pipe_id pipe_id; 4801 unsigned int thread_id; 4802 4803 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 4804 4805 if (!stream) 4806 { 4807 IA_CSS_LEAVE_ERR(-EINVAL); 4808 return -EINVAL; 4809 } 4810 pipe = stream->last_pipe; 4811 if (!pipe) 4812 { 4813 IA_CSS_LEAVE_ERR(-EINVAL); 4814 return -EINVAL; 4815 } 4816 4817 pipe_id = pipe->mode; 4818 4819 if (stream->started == true) 4820 { 4821 IA_CSS_WARNING("Cannot start stream that is already started"); 4822 IA_CSS_LEAVE_ERR(err); 4823 return err; 4824 } 4825 4826 pipe->stop_requested = false; 4827 4828 switch (pipe_id) 4829 { 4830 case IA_CSS_PIPE_ID_PREVIEW: 4831 err = preview_start(pipe); 4832 break; 4833 case IA_CSS_PIPE_ID_VIDEO: 4834 err = video_start(pipe); 4835 break; 4836 case IA_CSS_PIPE_ID_CAPTURE: 4837 err = capture_start(pipe); 4838 break; 4839 case IA_CSS_PIPE_ID_YUVPP: 4840 err = yuvpp_start(pipe); 4841 break; 4842 case IA_CSS_PIPE_ID_ACC: 4843 acc_start(pipe); 4844 break; 4845 default: 4846 err = -EINVAL; 4847 } 4848 /* DH regular multi pipe - not continuous mode: start the next pipes too */ 4849 if (!stream->config.continuous) 4850 { 4851 int i; 4852 4853 for (i = 1; i < stream->num_pipes && 0 == err ; i++) { 4854 switch (stream->pipes[i]->mode) { 4855 case IA_CSS_PIPE_ID_PREVIEW: 4856 stream->pipes[i]->stop_requested = false; 4857 err = preview_start(stream->pipes[i]); 4858 break; 4859 case IA_CSS_PIPE_ID_VIDEO: 4860 stream->pipes[i]->stop_requested = false; 4861 err = video_start(stream->pipes[i]); 4862 break; 4863 case IA_CSS_PIPE_ID_CAPTURE: 4864 stream->pipes[i]->stop_requested = false; 4865 err = capture_start(stream->pipes[i]); 4866 break; 4867 case IA_CSS_PIPE_ID_YUVPP: 4868 stream->pipes[i]->stop_requested = false; 4869 err = yuvpp_start(stream->pipes[i]); 4870 break; 4871 case IA_CSS_PIPE_ID_ACC: 4872 stream->pipes[i]->stop_requested = false; 4873 acc_start(stream->pipes[i]); 4874 break; 4875 default: 4876 err = -EINVAL; 4877 } 4878 } 4879 } 4880 if (err) 4881 { 4882 IA_CSS_LEAVE_ERR_PRIVATE(err); 4883 return err; 4884 } 4885 4886 /* Force ISP parameter calculation after a mode change 4887 * Acceleration API examples pass NULL for stream but they 4888 * don't use ISP parameters anyway. So this should be okay. 4889 * The SP binary (jpeg) copy does not use any parameters. 4890 */ 4891 if (!copy_on_sp(pipe)) 4892 { 4893 sh_css_invalidate_params(stream); 4894 err = sh_css_param_update_isp_params(pipe, 4895 stream->isp_params_configs, true, NULL); 4896 if (err) { 4897 IA_CSS_LEAVE_ERR_PRIVATE(err); 4898 return err; 4899 } 4900 } 4901 4902 ia_css_debug_pipe_graph_dump_epilogue(); 4903 4904 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 4905 4906 if (!sh_css_sp_is_running()) 4907 { 4908 IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY); 4909 /* SP is not running. The queues are not valid */ 4910 return -EBUSY; 4911 } 4912 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM, 4913 (uint8_t)thread_id, 0, 0); 4914 4915 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */ 4916 if (!stream->config.continuous) 4917 { 4918 int i; 4919 4920 for (i = 1; i < stream->num_pipes; i++) { 4921 ia_css_pipeline_get_sp_thread_id( 4922 ia_css_pipe_get_pipe_num(stream->pipes[i]), 4923 &thread_id); 4924 ia_css_bufq_enqueue_psys_event( 4925 IA_CSS_PSYS_SW_EVENT_START_STREAM, 4926 (uint8_t)thread_id, 0, 0); 4927 } 4928 } 4929 4930 /* in case of continuous capture mode, we also start capture thread and copy thread*/ 4931 if (pipe->stream->config.continuous) 4932 { 4933 struct ia_css_pipe *copy_pipe = NULL; 4934 4935 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 4936 copy_pipe = pipe->pipe_settings.preview.copy_pipe; 4937 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) 4938 copy_pipe = pipe->pipe_settings.video.copy_pipe; 4939 4940 if (!copy_pipe) { 4941 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 4942 return -EINVAL; 4943 } 4944 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe), 4945 &thread_id); 4946 /* by the time we reach here q is initialized and handle is available.*/ 4947 ia_css_bufq_enqueue_psys_event( 4948 IA_CSS_PSYS_SW_EVENT_START_STREAM, 4949 (uint8_t)thread_id, 0, 0); 4950 } 4951 if (pipe->stream->cont_capt) 4952 { 4953 struct ia_css_pipe *capture_pipe = NULL; 4954 4955 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 4956 capture_pipe = pipe->pipe_settings.preview.capture_pipe; 4957 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) 4958 capture_pipe = pipe->pipe_settings.video.capture_pipe; 4959 4960 if (!capture_pipe) { 4961 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 4962 return -EINVAL; 4963 } 4964 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), 4965 &thread_id); 4966 /* by the time we reach here q is initialized and handle is available.*/ 4967 ia_css_bufq_enqueue_psys_event( 4968 IA_CSS_PSYS_SW_EVENT_START_STREAM, 4969 (uint8_t)thread_id, 0, 0); 4970 } 4971 4972 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */ 4973 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 4974 { 4975 struct ia_css_pipe *acc_pipe = NULL; 4976 4977 acc_pipe = pipe->pipe_settings.preview.acc_pipe; 4978 4979 if (acc_pipe) { 4980 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe), 4981 &thread_id); 4982 /* by the time we reach here q is initialized and handle is available.*/ 4983 ia_css_bufq_enqueue_psys_event( 4984 IA_CSS_PSYS_SW_EVENT_START_STREAM, 4985 (uint8_t)thread_id, 0, 0); 4986 } 4987 } 4988 4989 stream->started = true; 4990 4991 IA_CSS_LEAVE_ERR_PRIVATE(err); 4992 return err; 4993 } 4994 4995 /* ISP2400 */ 4996 void 4997 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview) 4998 { 4999 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5000 "sh_css_enable_cont_capt() enter: enable=%d\n", enable); 5001 //my_css.cont_capt = enable; 5002 my_css.stop_copy_preview = stop_copy_preview; 5003 } 5004 5005 bool 5006 sh_css_continuous_is_enabled(uint8_t pipe_num) 5007 { 5008 struct ia_css_pipe *pipe; 5009 bool continuous; 5010 5011 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5012 "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num); 5013 5014 pipe = find_pipe_by_num(pipe_num); 5015 continuous = pipe && pipe->stream->config.continuous; 5016 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5017 "sh_css_continuous_is_enabled() leave: enable=%d\n", 5018 continuous); 5019 return continuous; 5020 } 5021 5022 /* ISP2400 */ 5023 int 5024 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, 5025 int *buffer_depth) { 5026 if (!buffer_depth) 5027 return -EINVAL; 5028 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n"); 5029 (void)stream; 5030 *buffer_depth = NUM_CONTINUOUS_FRAMES; 5031 return 0; 5032 } 5033 5034 int 5035 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) { 5036 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth); 5037 (void)stream; 5038 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1) 5039 return -EINVAL; 5040 /* ok, value allowed */ 5041 stream->config.target_num_cont_raw_buf = buffer_depth; 5042 /* TODO: check what to regarding initialization */ 5043 return 0; 5044 } 5045 5046 /* ISP2401 */ 5047 int 5048 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, 5049 int *buffer_depth) { 5050 if (!buffer_depth) 5051 return -EINVAL; 5052 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n"); 5053 (void)stream; 5054 *buffer_depth = stream->config.target_num_cont_raw_buf; 5055 return 0; 5056 } 5057 5058 /* 5059 * @brief Stop all "ia_css_pipe" instances in the target 5060 * "ia_css_stream" instance. 5061 * 5062 * Refer to "Local prototypes" for more info. 5063 */ 5064 /* ISP2401 */ 5065 static int 5066 sh_css_pipes_stop(struct ia_css_stream *stream) 5067 { 5068 int err = 0; 5069 struct ia_css_pipe *main_pipe; 5070 enum ia_css_pipe_id main_pipe_id; 5071 int i; 5072 5073 assert(stream); 5074 if (!stream) 5075 { 5076 IA_CSS_LOG("stream does NOT exist!"); 5077 err = -EINVAL; 5078 goto ERR; 5079 } 5080 5081 main_pipe = stream->last_pipe; 5082 assert(main_pipe); 5083 if (!main_pipe) 5084 { 5085 IA_CSS_LOG("main_pipe does NOT exist!"); 5086 err = -EINVAL; 5087 goto ERR; 5088 } 5089 5090 main_pipe_id = main_pipe->mode; 5091 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id); 5092 5093 /* 5094 * Stop all "ia_css_pipe" instances in this target 5095 * "ia_css_stream" instance. 5096 */ 5097 for (i = 0; i < stream->num_pipes; i++) 5098 { 5099 /* send the "stop" request to the "ia_css_pipe" instance */ 5100 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", 5101 stream->pipes[i]->pipeline.pipe_id); 5102 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline); 5103 5104 /* 5105 * Exit this loop if "ia_css_pipeline_request_stop()" 5106 * returns the error code. 5107 * 5108 * The error code would be generated in the following 5109 * two cases: 5110 * (1) The Scalar Processor has already been stopped. 5111 * (2) The "Host->SP" event queue is full. 5112 * 5113 * As the convention of using CSS API 2.0/2.1, such CSS 5114 * error code would be propogated from the CSS-internal 5115 * API returned value to the CSS API returned value. Then 5116 * the CSS driver should capture these error code and 5117 * handle it in the driver exception handling mechanism. 5118 */ 5119 if (err) { 5120 goto ERR; 5121 } 5122 } 5123 5124 /* 5125 * In the CSS firmware use scenario "Continuous Preview" 5126 * as well as "Continuous Video", the "ia_css_pipe" instance 5127 * "Copy Pipe" is activated. This "Copy Pipe" is private to 5128 * the CSS firmware so that it is not listed in the target 5129 * "ia_css_stream" instance. 5130 * 5131 * We need to stop this "Copy Pipe", as well. 5132 */ 5133 if (main_pipe->stream->config.continuous) 5134 { 5135 struct ia_css_pipe *copy_pipe = NULL; 5136 5137 /* get the reference to "Copy Pipe" */ 5138 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW) 5139 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 5140 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO) 5141 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 5142 5143 /* return the error code if "Copy Pipe" does NOT exist */ 5144 assert(copy_pipe); 5145 if (!copy_pipe) { 5146 IA_CSS_LOG("Copy Pipe does NOT exist!"); 5147 err = -EINVAL; 5148 goto ERR; 5149 } 5150 5151 /* send the "stop" request to "Copy Pipe" */ 5152 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", 5153 copy_pipe->pipeline.pipe_id); 5154 err = ia_css_pipeline_request_stop(©_pipe->pipeline); 5155 } 5156 5157 ERR: 5158 IA_CSS_LEAVE_ERR_PRIVATE(err); 5159 return err; 5160 } 5161 5162 /* 5163 * @brief Check if all "ia_css_pipe" instances in the target 5164 * "ia_css_stream" instance have stopped. 5165 * 5166 * Refer to "Local prototypes" for more info. 5167 */ 5168 /* ISP2401 */ 5169 static bool 5170 sh_css_pipes_have_stopped(struct ia_css_stream *stream) 5171 { 5172 bool rval = true; 5173 5174 struct ia_css_pipe *main_pipe; 5175 enum ia_css_pipe_id main_pipe_id; 5176 5177 int i; 5178 5179 assert(stream); 5180 if (!stream) { 5181 IA_CSS_LOG("stream does NOT exist!"); 5182 rval = false; 5183 goto RET; 5184 } 5185 5186 main_pipe = stream->last_pipe; 5187 assert(main_pipe); 5188 5189 if (!main_pipe) { 5190 IA_CSS_LOG("main_pipe does NOT exist!"); 5191 rval = false; 5192 goto RET; 5193 } 5194 5195 main_pipe_id = main_pipe->mode; 5196 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id); 5197 5198 /* 5199 * Check if every "ia_css_pipe" instance in this target 5200 * "ia_css_stream" instance has stopped. 5201 */ 5202 for (i = 0; i < stream->num_pipes; i++) { 5203 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline); 5204 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d", 5205 stream->pipes[i]->pipeline.pipe_id, 5206 rval); 5207 } 5208 5209 /* 5210 * In the CSS firmware use scenario "Continuous Preview" 5211 * as well as "Continuous Video", the "ia_css_pipe" instance 5212 * "Copy Pipe" is activated. This "Copy Pipe" is private to 5213 * the CSS firmware so that it is not listed in the target 5214 * "ia_css_stream" instance. 5215 * 5216 * We need to check if this "Copy Pipe" has stopped, as well. 5217 */ 5218 if (main_pipe->stream->config.continuous) { 5219 struct ia_css_pipe *copy_pipe = NULL; 5220 5221 /* get the reference to "Copy Pipe" */ 5222 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW) 5223 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 5224 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO) 5225 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 5226 5227 /* return if "Copy Pipe" does NOT exist */ 5228 assert(copy_pipe); 5229 if (!copy_pipe) { 5230 IA_CSS_LOG("Copy Pipe does NOT exist!"); 5231 5232 rval = false; 5233 goto RET; 5234 } 5235 5236 /* check if "Copy Pipe" has stopped or not */ 5237 rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline); 5238 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d", 5239 copy_pipe->pipeline.pipe_id, 5240 rval); 5241 } 5242 5243 RET: 5244 IA_CSS_LEAVE_PRIVATE("rval=%d", rval); 5245 return rval; 5246 } 5247 5248 #if defined(USE_INPUT_SYSTEM_VERSION_2) 5249 unsigned int 5250 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx) 5251 { 5252 OP___assert(port < N_CSI_PORTS); 5253 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT); 5254 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5255 "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n", 5256 port, idx, my_css.mipi_sizes_for_check[port][idx]); 5257 return my_css.mipi_sizes_for_check[port][idx]; 5258 } 5259 #endif 5260 5261 static int sh_css_pipe_configure_output( 5262 struct ia_css_pipe *pipe, 5263 unsigned int width, 5264 unsigned int height, 5265 unsigned int padded_width, 5266 enum ia_css_frame_format format, 5267 unsigned int idx) 5268 { 5269 int err = 0; 5270 5271 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, padded width = %d, format = %d, idx = %d", 5272 pipe, width, height, padded_width, format, idx); 5273 if (!pipe) { 5274 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 5275 return -EINVAL; 5276 } 5277 5278 err = ia_css_util_check_res(width, height); 5279 if (err) { 5280 IA_CSS_LEAVE_ERR_PRIVATE(err); 5281 return err; 5282 } 5283 if (pipe->output_info[idx].res.width != width || 5284 pipe->output_info[idx].res.height != height || 5285 pipe->output_info[idx].format != format) { 5286 ia_css_frame_info_init( 5287 &pipe->output_info[idx], 5288 width, 5289 height, 5290 format, 5291 padded_width); 5292 } 5293 IA_CSS_LEAVE_ERR_PRIVATE(0); 5294 return 0; 5295 } 5296 5297 static int 5298 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe, 5299 struct ia_css_shading_info *shading_info, 5300 struct ia_css_pipe_config *pipe_config) 5301 { 5302 int err = 0; 5303 struct ia_css_binary *binary = NULL; 5304 5305 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5306 "sh_css_pipe_get_shading_info() enter:\n"); 5307 5308 binary = ia_css_pipe_get_shading_correction_binary(pipe); 5309 5310 if (binary) 5311 { 5312 err = ia_css_binary_get_shading_info(binary, 5313 IA_CSS_SHADING_CORRECTION_TYPE_1, 5314 pipe->required_bds_factor, 5315 (const struct ia_css_stream_config *)&pipe->stream->config, 5316 shading_info, pipe_config); 5317 5318 /* Other function calls can be added here when other shading correction types will be added 5319 * in the future. 5320 */ 5321 } else 5322 { 5323 /* When the pipe does not have a binary which has the shading 5324 * correction, this function does not need to fill the shading 5325 * information. It is not a error case, and then 5326 * this function should return 0. 5327 */ 5328 memset(shading_info, 0, sizeof(*shading_info)); 5329 } 5330 return err; 5331 } 5332 5333 static int 5334 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe, 5335 struct ia_css_grid_info *info) { 5336 int err = 0; 5337 struct ia_css_binary *binary = NULL; 5338 5339 assert(pipe); 5340 assert(info); 5341 5342 IA_CSS_ENTER_PRIVATE(""); 5343 5344 binary = ia_css_pipe_get_s3a_binary(pipe); 5345 5346 if (binary) 5347 { 5348 err = ia_css_binary_3a_grid_info(binary, info, pipe); 5349 if (err) 5350 goto ERR; 5351 } else 5352 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid)); 5353 5354 binary = ia_css_pipe_get_sdis_binary(pipe); 5355 5356 if (binary) 5357 { 5358 ia_css_binary_dvs_grid_info(binary, info, pipe); 5359 ia_css_binary_dvs_stat_grid_info(binary, info, pipe); 5360 } else 5361 { 5362 memset(&info->dvs_grid.dvs_grid_info, 0, 5363 sizeof(info->dvs_grid.dvs_grid_info)); 5364 memset(&info->dvs_grid.dvs_stat_grid_info, 0, 5365 sizeof(info->dvs_grid.dvs_stat_grid_info)); 5366 } 5367 5368 if (binary) 5369 { 5370 /* copy pipe does not have ISP binary*/ 5371 info->isp_in_width = binary->internal_frame_info.res.width; 5372 info->isp_in_height = binary->internal_frame_info.res.height; 5373 } 5374 5375 info->vamem_type = IA_CSS_VAMEM_TYPE_2; 5376 5377 ERR : 5378 IA_CSS_LEAVE_ERR_PRIVATE(err); 5379 return err; 5380 } 5381 5382 /* ISP2401 */ 5383 /* 5384 * @brief Check if a format is supported by the pipe. 5385 * 5386 */ 5387 static int 5388 ia_css_pipe_check_format(struct ia_css_pipe *pipe, 5389 enum ia_css_frame_format format) { 5390 const enum ia_css_frame_format *supported_formats; 5391 int number_of_formats; 5392 int found = 0; 5393 int i; 5394 5395 IA_CSS_ENTER_PRIVATE(""); 5396 5397 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) 5398 { 5399 IA_CSS_ERROR("Pipe or binary info is not set"); 5400 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 5401 return -EINVAL; 5402 } 5403 5404 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats; 5405 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format); 5406 5407 for (i = 0; i < number_of_formats && !found; i++) 5408 { 5409 if (supported_formats[i] == format) { 5410 found = 1; 5411 break; 5412 } 5413 } 5414 if (!found) 5415 { 5416 IA_CSS_ERROR("Requested format is not supported by binary"); 5417 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 5418 return -EINVAL; 5419 } else 5420 { 5421 IA_CSS_LEAVE_ERR_PRIVATE(0); 5422 return 0; 5423 } 5424 } 5425 5426 static int load_video_binaries(struct ia_css_pipe *pipe) 5427 { 5428 struct ia_css_frame_info video_in_info, tnr_info, 5429 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info; 5430 bool online; 5431 int err = 0; 5432 bool continuous = pipe->stream->config.continuous; 5433 unsigned int i; 5434 unsigned int num_output_pins; 5435 struct ia_css_frame_info video_bin_out_info; 5436 bool need_scaler = false; 5437 bool vf_res_different_than_output = false; 5438 bool need_vf_pp = false; 5439 int vf_ds_log2; 5440 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video; 5441 5442 IA_CSS_ENTER_PRIVATE(""); 5443 assert(pipe); 5444 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO); 5445 /* we only test the video_binary because offline video doesn't need a 5446 * vf_pp binary and online does not (always use) the copy_binary. 5447 * All are always reset at the same time anyway. 5448 */ 5449 if (mycs->video_binary.info) 5450 return 0; 5451 5452 online = pipe->stream->config.online; 5453 pipe_out_info = &pipe->output_info[0]; 5454 pipe_vf_out_info = &pipe->vf_output_info[0]; 5455 5456 assert(pipe_out_info); 5457 5458 /* 5459 * There is no explicit input format requirement for raw or yuv 5460 * What matters is that there is a binary that supports the stream format. 5461 * This is checked in the binary_find(), so no need to check it here 5462 */ 5463 err = ia_css_util_check_input(&pipe->stream->config, false, false); 5464 if (err) 5465 return err; 5466 /* cannot have online video and input_mode memory */ 5467 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY) 5468 return -EINVAL; 5469 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 5470 err = ia_css_util_check_vf_out_info(pipe_out_info, 5471 pipe_vf_out_info); 5472 if (err) 5473 return err; 5474 } else { 5475 err = ia_css_frame_check_info(pipe_out_info); 5476 if (err) 5477 return err; 5478 } 5479 5480 if (pipe->out_yuv_ds_input_info.res.width) 5481 video_bin_out_info = pipe->out_yuv_ds_input_info; 5482 else 5483 video_bin_out_info = *pipe_out_info; 5484 5485 /* Video */ 5486 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 5487 video_vf_info = pipe_vf_out_info; 5488 vf_res_different_than_output = (video_vf_info->res.width != 5489 video_bin_out_info.res.width) || 5490 (video_vf_info->res.height != video_bin_out_info.res.height); 5491 } else { 5492 video_vf_info = NULL; 5493 } 5494 5495 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res); 5496 5497 /* we build up the pipeline starting at the end */ 5498 /* YUV post-processing if needed */ 5499 if (need_scaler) { 5500 struct ia_css_cas_binary_descr cas_scaler_descr = { }; 5501 5502 /* NV12 is the common format that is supported by both */ 5503 /* yuv_scaler and the video_xx_isp2_min binaries. */ 5504 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12; 5505 5506 err = ia_css_pipe_create_cas_scaler_desc_single_output( 5507 &video_bin_out_info, 5508 pipe_out_info, 5509 NULL, 5510 &cas_scaler_descr); 5511 if (err) 5512 return err; 5513 mycs->num_yuv_scaler = cas_scaler_descr.num_stage; 5514 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * 5515 sizeof(struct ia_css_binary), GFP_KERNEL); 5516 if (!mycs->yuv_scaler_binary) { 5517 err = -ENOMEM; 5518 return err; 5519 } 5520 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage 5521 * sizeof(bool), GFP_KERNEL); 5522 if (!mycs->is_output_stage) { 5523 err = -ENOMEM; 5524 return err; 5525 } 5526 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 5527 struct ia_css_binary_descr yuv_scaler_descr; 5528 5529 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 5530 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 5531 &yuv_scaler_descr, &cas_scaler_descr.in_info[i], 5532 &cas_scaler_descr.out_info[i], 5533 &cas_scaler_descr.internal_out_info[i], 5534 &cas_scaler_descr.vf_info[i]); 5535 err = ia_css_binary_find(&yuv_scaler_descr, 5536 &mycs->yuv_scaler_binary[i]); 5537 if (err) { 5538 kfree(mycs->is_output_stage); 5539 mycs->is_output_stage = NULL; 5540 return err; 5541 } 5542 } 5543 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 5544 } 5545 5546 { 5547 struct ia_css_binary_descr video_descr; 5548 enum ia_css_frame_format vf_info_format; 5549 5550 err = ia_css_pipe_get_video_binarydesc(pipe, 5551 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info, 5552 video_vf_info, 5553 pipe->stream->config.left_padding); 5554 if (err) 5555 return err; 5556 5557 /* In the case where video_vf_info is not NULL, this allows 5558 * us to find a potential video library with desired vf format. 5559 * If success, no vf_pp binary is needed. 5560 * If failed, we will look up video binary with YUV_LINE vf format 5561 */ 5562 err = ia_css_binary_find(&video_descr, 5563 &mycs->video_binary); 5564 5565 if (err) { 5566 if (video_vf_info) { 5567 /* This will do another video binary lookup later for YUV_LINE format*/ 5568 need_vf_pp = true; 5569 } else 5570 return err; 5571 } else if (video_vf_info) { 5572 /* The first video binary lookup is successful, but we may 5573 * still need vf_pp binary based on additiona check */ 5574 num_output_pins = mycs->video_binary.info->num_output_pins; 5575 vf_ds_log2 = mycs->video_binary.vf_downscale_log2; 5576 5577 /* If the binary has dual output pins, we need vf_pp if the resolution 5578 * is different. */ 5579 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output); 5580 5581 /* If the binary has single output pin, we need vf_pp if additional 5582 * scaling is needed for vf */ 5583 need_vf_pp |= ((num_output_pins == 1) && 5584 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) || 5585 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height))); 5586 } 5587 5588 if (need_vf_pp) { 5589 /* save the current vf_info format for restoration later */ 5590 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5591 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n"); 5592 5593 vf_info_format = video_vf_info->format; 5594 5595 if (!pipe->config.enable_vfpp_bci) 5596 ia_css_frame_info_set_format(video_vf_info, 5597 IA_CSS_FRAME_FORMAT_YUV_LINE); 5598 5599 ia_css_binary_destroy_isp_parameters(&mycs->video_binary); 5600 5601 err = ia_css_binary_find(&video_descr, 5602 &mycs->video_binary); 5603 5604 /* restore original vf_info format */ 5605 ia_css_frame_info_set_format(video_vf_info, 5606 vf_info_format); 5607 if (err) 5608 return err; 5609 } 5610 } 5611 5612 /* If a video binary does not use a ref_frame, we set the frame delay 5613 * to 0. This is the case for the 1-stage low-power video binary. */ 5614 if (!mycs->video_binary.info->sp.enable.ref_frame) 5615 pipe->dvs_frame_delay = 0; 5616 5617 /* The delay latency determines the number of invalid frames after 5618 * a stream is started. */ 5619 pipe->num_invalid_frames = pipe->dvs_frame_delay; 5620 pipe->info.num_invalid_frames = pipe->num_invalid_frames; 5621 5622 /* Viewfinder frames also decrement num_invalid_frames. If the pipe 5623 * outputs a viewfinder output, then we need double the number of 5624 * invalid frames */ 5625 if (video_vf_info) 5626 pipe->num_invalid_frames *= 2; 5627 5628 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5629 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n", 5630 pipe->num_invalid_frames, pipe->dvs_frame_delay); 5631 5632 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */ 5633 #if !defined(USE_INPUT_SYSTEM_VERSION_2401) 5634 /* Copy */ 5635 if (!online && !continuous) { 5636 /* TODO: what exactly needs doing, prepend the copy binary to 5637 * video base this only on !online? 5638 */ 5639 err = load_copy_binary(pipe, 5640 &mycs->copy_binary, 5641 &mycs->video_binary); 5642 if (err) 5643 return err; 5644 } 5645 #else 5646 (void)continuous; 5647 #endif 5648 5649 #if !defined(HAS_OUTPUT_SYSTEM) 5650 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) { 5651 struct ia_css_binary_descr vf_pp_descr; 5652 5653 if (mycs->video_binary.vf_frame_info.format 5654 == IA_CSS_FRAME_FORMAT_YUV_LINE) { 5655 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr, 5656 &mycs->video_binary.vf_frame_info, 5657 pipe_vf_out_info); 5658 } else { 5659 /* output from main binary is not yuv line. currently this is 5660 * possible only when bci is enabled on vfpp output */ 5661 assert(pipe->config.enable_vfpp_bci == true); 5662 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr, 5663 &mycs->video_binary.vf_frame_info, 5664 pipe_vf_out_info, NULL, NULL); 5665 } 5666 5667 err = ia_css_binary_find(&vf_pp_descr, 5668 &mycs->vf_pp_binary); 5669 if (err) 5670 return err; 5671 } 5672 #endif 5673 5674 err = allocate_delay_frames(pipe); 5675 5676 if (err) 5677 return err; 5678 5679 if (mycs->video_binary.info->sp.enable.block_output) { 5680 unsigned int tnr_width; 5681 unsigned int tnr_height; 5682 5683 tnr_info = mycs->video_binary.out_frame_info[0]; 5684 5685 if (IS_ISP2401) { 5686 /* Select resolution for TNR. If 5687 * output_system_in_resolution(GDC_out_resolution) is 5688 * being used, then select that as it will also be in resolution for 5689 * TNR. At present, it only make sense for Skycam */ 5690 if (pipe->config.output_system_in_res.width && 5691 pipe->config.output_system_in_res.height) { 5692 tnr_width = pipe->config.output_system_in_res.width; 5693 tnr_height = pipe->config.output_system_in_res.height; 5694 } else { 5695 tnr_width = tnr_info.res.width; 5696 tnr_height = tnr_info.res.height; 5697 } 5698 5699 /* Make tnr reference buffers output block width(in pix) align */ 5700 tnr_info.res.width = CEIL_MUL(tnr_width, 5701 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY)); 5702 tnr_info.padded_width = tnr_info.res.width; 5703 } else { 5704 tnr_height = tnr_info.res.height; 5705 } 5706 5707 /* Make tnr reference buffers output block height align */ 5708 tnr_info.res.height = CEIL_MUL(tnr_height, 5709 mycs->video_binary.info->sp.block.output_block_height); 5710 } else { 5711 tnr_info = mycs->video_binary.internal_frame_info; 5712 } 5713 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE; 5714 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH; 5715 5716 for (i = 0; i < NUM_TNR_FRAMES; i++) { 5717 if (mycs->tnr_frames[i]) { 5718 ia_css_frame_free(mycs->tnr_frames[i]); 5719 mycs->tnr_frames[i] = NULL; 5720 } 5721 err = ia_css_frame_allocate_from_info( 5722 &mycs->tnr_frames[i], 5723 &tnr_info); 5724 if (err) 5725 return err; 5726 } 5727 IA_CSS_LEAVE_PRIVATE(""); 5728 return 0; 5729 } 5730 5731 static int 5732 unload_video_binaries(struct ia_css_pipe *pipe) { 5733 unsigned int i; 5734 5735 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 5736 5737 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) 5738 { 5739 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 5740 return -EINVAL; 5741 } 5742 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary); 5743 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary); 5744 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary); 5745 5746 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++) 5747 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]); 5748 5749 kfree(pipe->pipe_settings.video.is_output_stage); 5750 pipe->pipe_settings.video.is_output_stage = NULL; 5751 kfree(pipe->pipe_settings.video.yuv_scaler_binary); 5752 pipe->pipe_settings.video.yuv_scaler_binary = NULL; 5753 5754 IA_CSS_LEAVE_ERR_PRIVATE(0); 5755 return 0; 5756 } 5757 5758 static int video_start(struct ia_css_pipe *pipe) 5759 { 5760 struct ia_css_binary *copy_binary; 5761 int err = 0; 5762 struct ia_css_pipe *copy_pipe, *capture_pipe; 5763 enum sh_css_pipe_config_override copy_ovrd; 5764 enum ia_css_input_mode video_pipe_input_mode; 5765 5766 const struct ia_css_coordinate *coord = NULL; 5767 const struct ia_css_isp_parameters *params = NULL; 5768 5769 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 5770 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { 5771 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 5772 return -EINVAL; 5773 } 5774 5775 video_pipe_input_mode = pipe->stream->config.mode; 5776 5777 copy_pipe = pipe->pipe_settings.video.copy_pipe; 5778 capture_pipe = pipe->pipe_settings.video.capture_pipe; 5779 5780 copy_binary = &pipe->pipe_settings.video.copy_binary; 5781 5782 sh_css_metrics_start_frame(); 5783 5784 /* multi stream video needs mipi buffers */ 5785 5786 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 5787 err = send_mipi_frames(pipe); 5788 if (err) 5789 return err; 5790 #endif 5791 5792 send_raw_frames(pipe); 5793 { 5794 unsigned int thread_id; 5795 5796 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 5797 copy_ovrd = 1 << thread_id; 5798 5799 if (pipe->stream->cont_capt) { 5800 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), 5801 &thread_id); 5802 copy_ovrd |= 1 << thread_id; 5803 } 5804 } 5805 5806 if (IS_ISP2401) { 5807 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl; 5808 params = pipe->stream->isp_params_configs; 5809 } 5810 5811 /* Construct and load the copy pipe */ 5812 if (pipe->stream->config.continuous) { 5813 sh_css_sp_init_pipeline(©_pipe->pipeline, 5814 IA_CSS_PIPE_ID_COPY, 5815 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe), 5816 false, 5817 pipe->stream->config.pixels_per_clock == 2, false, 5818 false, pipe->required_bds_factor, 5819 copy_ovrd, 5820 pipe->stream->config.mode, 5821 &pipe->stream->config.metadata_config, 5822 &pipe->stream->info.metadata_info, 5823 pipe->stream->config.source.port.port, 5824 coord, 5825 params); 5826 5827 /* make the video pipe start with mem mode input, copy handles 5828 the actual mode */ 5829 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; 5830 } 5831 5832 /* Construct and load the capture pipe */ 5833 if (pipe->stream->cont_capt) { 5834 sh_css_sp_init_pipeline(&capture_pipe->pipeline, 5835 IA_CSS_PIPE_ID_CAPTURE, 5836 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe), 5837 capture_pipe->config.default_capture_config.enable_xnr != 0, 5838 capture_pipe->stream->config.pixels_per_clock == 2, 5839 true, /* continuous */ 5840 false, /* offline */ 5841 capture_pipe->required_bds_factor, 5842 0, 5843 IA_CSS_INPUT_MODE_MEMORY, 5844 &pipe->stream->config.metadata_config, 5845 &pipe->stream->info.metadata_info, 5846 (enum mipi_port_id)0, 5847 coord, 5848 params); 5849 } 5850 5851 start_pipe(pipe, copy_ovrd, video_pipe_input_mode); 5852 5853 IA_CSS_LEAVE_ERR_PRIVATE(err); 5854 return err; 5855 } 5856 5857 static 5858 int sh_css_pipe_get_viewfinder_frame_info( 5859 struct ia_css_pipe *pipe, 5860 struct ia_css_frame_info *info, 5861 unsigned int idx) 5862 { 5863 assert(pipe); 5864 assert(info); 5865 5866 /* We could print the pointer as input arg, and the values as output */ 5867 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5868 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n"); 5869 5870 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE && 5871 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || 5872 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)) 5873 return -EINVAL; 5874 /* offline video does not generate viewfinder output */ 5875 *info = pipe->vf_output_info[idx]; 5876 5877 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5878 "sh_css_pipe_get_viewfinder_frame_info() leave: \ 5879 info.res.width=%d, info.res.height=%d, \ 5880 info.padded_width=%d, info.format=%d, \ 5881 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n", 5882 info->res.width, info->res.height, 5883 info->padded_width, info->format, 5884 info->raw_bit_depth, info->raw_bayer_order); 5885 5886 return 0; 5887 } 5888 5889 static int 5890 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width, 5891 unsigned int height, unsigned int min_width, 5892 enum ia_css_frame_format format, 5893 unsigned int idx) { 5894 int err = 0; 5895 5896 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n", 5897 pipe, width, height, min_width, format, idx); 5898 5899 if (!pipe) 5900 { 5901 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 5902 return -EINVAL; 5903 } 5904 5905 err = ia_css_util_check_res(width, height); 5906 if (err) 5907 { 5908 IA_CSS_LEAVE_ERR_PRIVATE(err); 5909 return err; 5910 } 5911 if (pipe->vf_output_info[idx].res.width != width || 5912 pipe->vf_output_info[idx].res.height != height || 5913 pipe->vf_output_info[idx].format != format) 5914 { 5915 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height, 5916 format, min_width); 5917 } 5918 IA_CSS_LEAVE_ERR_PRIVATE(0); 5919 return 0; 5920 } 5921 5922 static int load_copy_binaries(struct ia_css_pipe *pipe) 5923 { 5924 int err = 0; 5925 5926 assert(pipe); 5927 IA_CSS_ENTER_PRIVATE(""); 5928 5929 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 5930 pipe->mode == IA_CSS_PIPE_ID_COPY); 5931 if (pipe->pipe_settings.capture.copy_binary.info) 5932 return 0; 5933 5934 err = ia_css_frame_check_info(&pipe->output_info[0]); 5935 if (err) 5936 goto ERR; 5937 5938 err = verify_copy_out_frame_format(pipe); 5939 if (err) 5940 goto ERR; 5941 5942 err = load_copy_binary(pipe, 5943 &pipe->pipe_settings.capture.copy_binary, 5944 NULL); 5945 5946 ERR: 5947 IA_CSS_LEAVE_ERR_PRIVATE(err); 5948 return err; 5949 } 5950 5951 static bool need_capture_pp( 5952 const struct ia_css_pipe *pipe) 5953 { 5954 const struct ia_css_frame_info *out_info = &pipe->output_info[0]; 5955 5956 IA_CSS_ENTER_LEAVE_PRIVATE(""); 5957 assert(pipe); 5958 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 5959 5960 if (IS_ISP2401) { 5961 /* ldc and capture_pp are not supported in the same pipeline */ 5962 if (need_capt_ldc(pipe) == true) 5963 return false; 5964 } 5965 5966 /* determine whether we need to use the capture_pp binary. 5967 * This is needed for: 5968 * 1. XNR or 5969 * 2. Digital Zoom or 5970 * 3. YUV downscaling 5971 */ 5972 if (pipe->out_yuv_ds_input_info.res.width && 5973 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) || 5974 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height))) 5975 return true; 5976 5977 if (pipe->config.default_capture_config.enable_xnr != 0) 5978 return true; 5979 5980 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) || 5981 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) || 5982 pipe->config.enable_dz) 5983 return true; 5984 5985 return false; 5986 } 5987 5988 static bool need_capt_ldc( 5989 const struct ia_css_pipe *pipe) 5990 { 5991 IA_CSS_ENTER_LEAVE_PRIVATE(""); 5992 assert(pipe); 5993 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 5994 return (pipe->extra_config.enable_dvs_6axis) ? true : false; 5995 } 5996 5997 static int set_num_primary_stages(unsigned int *num, 5998 enum ia_css_pipe_version version) 5999 { 6000 int err = 0; 6001 6002 if (!num) 6003 return -EINVAL; 6004 6005 switch (version) { 6006 case IA_CSS_PIPE_VERSION_2_6_1: 6007 *num = NUM_PRIMARY_HQ_STAGES; 6008 break; 6009 case IA_CSS_PIPE_VERSION_2_2: 6010 case IA_CSS_PIPE_VERSION_1: 6011 *num = NUM_PRIMARY_STAGES; 6012 break; 6013 default: 6014 err = -EINVAL; 6015 break; 6016 } 6017 6018 return err; 6019 } 6020 6021 static int load_primary_binaries( 6022 struct ia_css_pipe *pipe) 6023 { 6024 bool online = false; 6025 bool memory = false; 6026 bool continuous = false; 6027 bool need_pp = false; 6028 bool need_isp_copy_binary = false; 6029 bool need_ldc = false; 6030 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6031 bool sensor = false; 6032 #endif 6033 struct ia_css_frame_info prim_in_info, 6034 prim_out_info, 6035 capt_pp_out_info, vf_info, 6036 *vf_pp_in_info, *pipe_out_info, 6037 *pipe_vf_out_info, *capt_pp_in_info, 6038 capt_ldc_out_info; 6039 int err = 0; 6040 struct ia_css_capture_settings *mycs; 6041 unsigned int i; 6042 bool need_extra_yuv_scaler = false; 6043 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES]; 6044 6045 IA_CSS_ENTER_PRIVATE(""); 6046 assert(pipe); 6047 assert(pipe->stream); 6048 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6049 pipe->mode == IA_CSS_PIPE_ID_COPY); 6050 6051 online = pipe->stream->config.online; 6052 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 6053 continuous = pipe->stream->config.continuous; 6054 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6055 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); 6056 #endif 6057 6058 mycs = &pipe->pipe_settings.capture; 6059 pipe_out_info = &pipe->output_info[0]; 6060 pipe_vf_out_info = &pipe->vf_output_info[0]; 6061 6062 if (mycs->primary_binary[0].info) 6063 return 0; 6064 6065 err = set_num_primary_stages(&mycs->num_primary_stage, 6066 pipe->config.isp_pipe_version); 6067 if (err) { 6068 IA_CSS_LEAVE_ERR_PRIVATE(err); 6069 return err; 6070 } 6071 6072 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 6073 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info); 6074 if (err) { 6075 IA_CSS_LEAVE_ERR_PRIVATE(err); 6076 return err; 6077 } 6078 } else { 6079 err = ia_css_frame_check_info(pipe_out_info); 6080 if (err) { 6081 IA_CSS_LEAVE_ERR_PRIVATE(err); 6082 return err; 6083 } 6084 } 6085 need_pp = need_capture_pp(pipe); 6086 6087 /* we use the vf output info to get the primary/capture_pp binary 6088 configured for vf_veceven. It will select the closest downscaling 6089 factor. */ 6090 vf_info = *pipe_vf_out_info; 6091 6092 /* 6093 * WARNING: The #if def flag has been added below as a 6094 * temporary solution to solve the problem of enabling the 6095 * view finder in a single binary in a capture flow. The 6096 * vf-pp stage has been removed for Skycam in the solution 6097 * provided. The vf-pp stage should be re-introduced when 6098 * required. This should not be considered as a clean solution. 6099 * Proper investigation should be done to come up with the clean 6100 * solution. 6101 * */ 6102 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); 6103 6104 /* TODO: All this yuv_scaler and capturepp calculation logic 6105 * can be shared later. Capture_pp is also a yuv_scale binary 6106 * with extra XNR funcionality. Therefore, it can be made as the 6107 * first step of the cascade. */ 6108 capt_pp_out_info = pipe->out_yuv_ds_input_info; 6109 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420; 6110 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP; 6111 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP; 6112 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0); 6113 6114 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res, 6115 pipe_out_info->res); 6116 6117 if (need_extra_yuv_scaler) { 6118 struct ia_css_cas_binary_descr cas_scaler_descr = { }; 6119 6120 err = ia_css_pipe_create_cas_scaler_desc_single_output( 6121 &capt_pp_out_info, 6122 pipe_out_info, 6123 NULL, 6124 &cas_scaler_descr); 6125 if (err) { 6126 IA_CSS_LEAVE_ERR_PRIVATE(err); 6127 return err; 6128 } 6129 mycs->num_yuv_scaler = cas_scaler_descr.num_stage; 6130 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * 6131 sizeof(struct ia_css_binary), GFP_KERNEL); 6132 if (!mycs->yuv_scaler_binary) { 6133 err = -ENOMEM; 6134 IA_CSS_LEAVE_ERR_PRIVATE(err); 6135 return err; 6136 } 6137 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage * 6138 sizeof(bool), GFP_KERNEL); 6139 if (!mycs->is_output_stage) { 6140 err = -ENOMEM; 6141 IA_CSS_LEAVE_ERR_PRIVATE(err); 6142 return err; 6143 } 6144 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 6145 struct ia_css_binary_descr yuv_scaler_descr; 6146 6147 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 6148 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 6149 &yuv_scaler_descr, &cas_scaler_descr.in_info[i], 6150 &cas_scaler_descr.out_info[i], 6151 &cas_scaler_descr.internal_out_info[i], 6152 &cas_scaler_descr.vf_info[i]); 6153 err = ia_css_binary_find(&yuv_scaler_descr, 6154 &mycs->yuv_scaler_binary[i]); 6155 if (err) { 6156 IA_CSS_LEAVE_ERR_PRIVATE(err); 6157 return err; 6158 } 6159 } 6160 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 6161 6162 } else { 6163 capt_pp_out_info = pipe->output_info[0]; 6164 } 6165 6166 /* TODO Do we disable ldc for skycam */ 6167 need_ldc = need_capt_ldc(pipe); 6168 if (IS_ISP2401 && need_ldc) { 6169 /* ldc and capt_pp are not supported in the same pipeline */ 6170 struct ia_css_binary_descr capt_ldc_descr; 6171 6172 ia_css_pipe_get_ldc_binarydesc(pipe, 6173 &capt_ldc_descr, &prim_out_info, 6174 &capt_pp_out_info); 6175 6176 err = ia_css_binary_find(&capt_ldc_descr, 6177 &mycs->capture_ldc_binary); 6178 if (err) { 6179 IA_CSS_LEAVE_ERR_PRIVATE(err); 6180 return err; 6181 } 6182 need_pp = 0; 6183 need_ldc = 0; 6184 } 6185 6186 /* we build up the pipeline starting at the end */ 6187 /* Capture post-processing */ 6188 if (need_pp) { 6189 struct ia_css_binary_descr capture_pp_descr; 6190 6191 if (!IS_ISP2401) 6192 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info; 6193 else 6194 capt_pp_in_info = &prim_out_info; 6195 6196 ia_css_pipe_get_capturepp_binarydesc(pipe, 6197 &capture_pp_descr, capt_pp_in_info, 6198 &capt_pp_out_info, &vf_info); 6199 err = ia_css_binary_find(&capture_pp_descr, 6200 &mycs->capture_pp_binary); 6201 if (err) { 6202 IA_CSS_LEAVE_ERR_PRIVATE(err); 6203 return err; 6204 } 6205 6206 if (need_ldc) { 6207 struct ia_css_binary_descr capt_ldc_descr; 6208 6209 ia_css_pipe_get_ldc_binarydesc(pipe, 6210 &capt_ldc_descr, &prim_out_info, 6211 &capt_ldc_out_info); 6212 6213 err = ia_css_binary_find(&capt_ldc_descr, 6214 &mycs->capture_ldc_binary); 6215 if (err) { 6216 IA_CSS_LEAVE_ERR_PRIVATE(err); 6217 return err; 6218 } 6219 } 6220 } else { 6221 prim_out_info = *pipe_out_info; 6222 } 6223 6224 /* Primary */ 6225 for (i = 0; i < mycs->num_primary_stage; i++) { 6226 struct ia_css_frame_info *local_vf_info = NULL; 6227 6228 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && 6229 (i == mycs->num_primary_stage - 1)) 6230 local_vf_info = &vf_info; 6231 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info, 6232 &prim_out_info, local_vf_info, i); 6233 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]); 6234 if (err) { 6235 IA_CSS_LEAVE_ERR_PRIVATE(err); 6236 return err; 6237 } 6238 } 6239 6240 /* Viewfinder post-processing */ 6241 if (need_pp) 6242 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info; 6243 else 6244 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info; 6245 6246 /* 6247 * WARNING: The #if def flag has been added below as a 6248 * temporary solution to solve the problem of enabling the 6249 * view finder in a single binary in a capture flow. The 6250 * vf-pp stage has been removed for Skycam in the solution 6251 * provided. The vf-pp stage should be re-introduced when 6252 * required. Thisshould not be considered as a clean solution. 6253 * Proper * investigation should be done to come up with the clean 6254 * solution. 6255 * */ 6256 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 6257 struct ia_css_binary_descr vf_pp_descr; 6258 6259 ia_css_pipe_get_vfpp_binarydesc(pipe, 6260 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); 6261 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary); 6262 if (err) { 6263 IA_CSS_LEAVE_ERR_PRIVATE(err); 6264 return err; 6265 } 6266 } 6267 err = allocate_delay_frames(pipe); 6268 6269 if (err) 6270 return err; 6271 6272 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6273 /* When the input system is 2401, only the Direct Sensor Mode 6274 * Offline Capture uses the ISP copy binary. 6275 */ 6276 need_isp_copy_binary = !online && sensor; 6277 #else 6278 need_isp_copy_binary = !online && !continuous && !memory; 6279 #endif 6280 6281 /* ISP Copy */ 6282 if (need_isp_copy_binary) { 6283 err = load_copy_binary(pipe, 6284 &mycs->copy_binary, 6285 &mycs->primary_binary[0]); 6286 if (err) { 6287 IA_CSS_LEAVE_ERR_PRIVATE(err); 6288 return err; 6289 } 6290 } 6291 6292 return 0; 6293 } 6294 6295 static int 6296 allocate_delay_frames(struct ia_css_pipe *pipe) { 6297 unsigned int num_delay_frames = 0, i = 0; 6298 unsigned int dvs_frame_delay = 0; 6299 struct ia_css_frame_info ref_info; 6300 int err = 0; 6301 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO; 6302 struct ia_css_frame **delay_frames = NULL; 6303 6304 IA_CSS_ENTER_PRIVATE(""); 6305 6306 if (!pipe) 6307 { 6308 IA_CSS_ERROR("Invalid args - pipe %p", pipe); 6309 return -EINVAL; 6310 } 6311 6312 mode = pipe->mode; 6313 dvs_frame_delay = pipe->dvs_frame_delay; 6314 6315 if (dvs_frame_delay > 0) 6316 num_delay_frames = dvs_frame_delay + 1; 6317 6318 switch (mode) 6319 { 6320 case IA_CSS_PIPE_ID_CAPTURE: { 6321 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture; 6322 (void)mycs_capture; 6323 return err; 6324 } 6325 break; 6326 case IA_CSS_PIPE_ID_VIDEO: { 6327 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video; 6328 6329 ref_info = mycs_video->video_binary.internal_frame_info; 6330 /*The ref frame expects 6331 * 1. Y plane 6332 * 2. UV plane with line interleaving, like below 6333 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) 6334 * 6335 * This format is not YUV420(which has Y, U and V planes). 6336 * Its closer to NV12, except that the UV plane has UV 6337 * interleaving, like UVUVUVUVUVUVUVUVU... 6338 * 6339 * TODO: make this ref_frame format as a separate frame format 6340 */ 6341 ref_info.format = IA_CSS_FRAME_FORMAT_NV12; 6342 delay_frames = mycs_video->delay_frames; 6343 } 6344 break; 6345 case IA_CSS_PIPE_ID_PREVIEW: { 6346 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview; 6347 6348 ref_info = mycs_preview->preview_binary.internal_frame_info; 6349 /*The ref frame expects 6350 * 1. Y plane 6351 * 2. UV plane with line interleaving, like below 6352 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) 6353 * 6354 * This format is not YUV420(which has Y, U and V planes). 6355 * Its closer to NV12, except that the UV plane has UV 6356 * interleaving, like UVUVUVUVUVUVUVUVU... 6357 * 6358 * TODO: make this ref_frame format as a separate frame format 6359 */ 6360 ref_info.format = IA_CSS_FRAME_FORMAT_NV12; 6361 delay_frames = mycs_preview->delay_frames; 6362 } 6363 break; 6364 default: 6365 return -EINVAL; 6366 } 6367 6368 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH; 6369 6370 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES); 6371 for (i = 0; i < num_delay_frames; i++) 6372 { 6373 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info); 6374 if (err) 6375 return err; 6376 } 6377 IA_CSS_LEAVE_PRIVATE(""); 6378 return 0; 6379 } 6380 6381 static int load_advanced_binaries( 6382 struct ia_css_pipe *pipe) { 6383 struct ia_css_frame_info pre_in_info, gdc_in_info, 6384 post_in_info, post_out_info, 6385 vf_info, *vf_pp_in_info, *pipe_out_info, 6386 *pipe_vf_out_info; 6387 bool need_pp; 6388 bool need_isp_copy = true; 6389 int err = 0; 6390 6391 IA_CSS_ENTER_PRIVATE(""); 6392 6393 assert(pipe); 6394 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6395 pipe->mode == IA_CSS_PIPE_ID_COPY); 6396 if (pipe->pipe_settings.capture.pre_isp_binary.info) 6397 return 0; 6398 pipe_out_info = &pipe->output_info[0]; 6399 pipe_vf_out_info = &pipe->vf_output_info[0]; 6400 6401 vf_info = *pipe_vf_out_info; 6402 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info); 6403 if (err) 6404 return err; 6405 need_pp = need_capture_pp(pipe); 6406 6407 ia_css_frame_info_set_format(&vf_info, 6408 IA_CSS_FRAME_FORMAT_YUV_LINE); 6409 6410 /* we build up the pipeline starting at the end */ 6411 /* Capture post-processing */ 6412 if (need_pp) { 6413 struct ia_css_binary_descr capture_pp_descr; 6414 6415 ia_css_pipe_get_capturepp_binarydesc(pipe, 6416 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info); 6417 err = ia_css_binary_find(&capture_pp_descr, 6418 &pipe->pipe_settings.capture.capture_pp_binary); 6419 if (err) 6420 return err; 6421 } else { 6422 post_out_info = *pipe_out_info; 6423 } 6424 6425 /* Post-gdc */ 6426 { 6427 struct ia_css_binary_descr post_gdc_descr; 6428 6429 ia_css_pipe_get_post_gdc_binarydesc(pipe, 6430 &post_gdc_descr, &post_in_info, &post_out_info, &vf_info); 6431 err = ia_css_binary_find(&post_gdc_descr, 6432 &pipe->pipe_settings.capture.post_isp_binary); 6433 if (err) 6434 return err; 6435 } 6436 6437 /* Gdc */ 6438 { 6439 struct ia_css_binary_descr gdc_descr; 6440 6441 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info, 6442 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); 6443 err = ia_css_binary_find(&gdc_descr, 6444 &pipe->pipe_settings.capture.anr_gdc_binary); 6445 if (err) 6446 return err; 6447 } 6448 pipe->pipe_settings.capture.anr_gdc_binary.left_padding = 6449 pipe->pipe_settings.capture.post_isp_binary.left_padding; 6450 6451 /* Pre-gdc */ 6452 { 6453 struct ia_css_binary_descr pre_gdc_descr; 6454 6455 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info, 6456 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); 6457 err = ia_css_binary_find(&pre_gdc_descr, 6458 &pipe->pipe_settings.capture.pre_isp_binary); 6459 if (err) 6460 return err; 6461 } 6462 pipe->pipe_settings.capture.pre_isp_binary.left_padding = 6463 pipe->pipe_settings.capture.anr_gdc_binary.left_padding; 6464 6465 /* Viewfinder post-processing */ 6466 if (need_pp) { 6467 vf_pp_in_info = 6468 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info; 6469 } else { 6470 vf_pp_in_info = 6471 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info; 6472 } 6473 6474 { 6475 struct ia_css_binary_descr vf_pp_descr; 6476 6477 ia_css_pipe_get_vfpp_binarydesc(pipe, 6478 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); 6479 err = ia_css_binary_find(&vf_pp_descr, 6480 &pipe->pipe_settings.capture.vf_pp_binary); 6481 if (err) 6482 return err; 6483 } 6484 6485 /* Copy */ 6486 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6487 /* For CSI2+, only the direct sensor mode/online requires ISP copy */ 6488 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 6489 #endif 6490 if (need_isp_copy) 6491 load_copy_binary(pipe, 6492 &pipe->pipe_settings.capture.copy_binary, 6493 &pipe->pipe_settings.capture.pre_isp_binary); 6494 6495 return err; 6496 } 6497 6498 static int load_bayer_isp_binaries( 6499 struct ia_css_pipe *pipe) { 6500 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info; 6501 int err = 0; 6502 struct ia_css_binary_descr pre_de_descr; 6503 6504 IA_CSS_ENTER_PRIVATE(""); 6505 assert(pipe); 6506 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6507 pipe->mode == IA_CSS_PIPE_ID_COPY); 6508 pipe_out_info = &pipe->output_info[0]; 6509 6510 if (pipe->pipe_settings.capture.pre_isp_binary.info) 6511 return 0; 6512 6513 err = ia_css_frame_check_info(pipe_out_info); 6514 if (err) 6515 return err; 6516 6517 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr, 6518 &pre_isp_in_info, 6519 pipe_out_info); 6520 6521 err = ia_css_binary_find(&pre_de_descr, 6522 &pipe->pipe_settings.capture.pre_isp_binary); 6523 6524 return err; 6525 } 6526 6527 static int load_low_light_binaries( 6528 struct ia_css_pipe *pipe) { 6529 struct ia_css_frame_info pre_in_info, anr_in_info, 6530 post_in_info, post_out_info, 6531 vf_info, *pipe_vf_out_info, *pipe_out_info, 6532 *vf_pp_in_info; 6533 bool need_pp; 6534 bool need_isp_copy = true; 6535 int err = 0; 6536 6537 IA_CSS_ENTER_PRIVATE(""); 6538 assert(pipe); 6539 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6540 pipe->mode == IA_CSS_PIPE_ID_COPY); 6541 6542 if (pipe->pipe_settings.capture.pre_isp_binary.info) 6543 return 0; 6544 pipe_vf_out_info = &pipe->vf_output_info[0]; 6545 pipe_out_info = &pipe->output_info[0]; 6546 6547 vf_info = *pipe_vf_out_info; 6548 err = ia_css_util_check_vf_out_info(pipe_out_info, 6549 &vf_info); 6550 if (err) 6551 return err; 6552 need_pp = need_capture_pp(pipe); 6553 6554 ia_css_frame_info_set_format(&vf_info, 6555 IA_CSS_FRAME_FORMAT_YUV_LINE); 6556 6557 /* we build up the pipeline starting at the end */ 6558 /* Capture post-processing */ 6559 if (need_pp) { 6560 struct ia_css_binary_descr capture_pp_descr; 6561 6562 ia_css_pipe_get_capturepp_binarydesc(pipe, 6563 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info); 6564 err = ia_css_binary_find(&capture_pp_descr, 6565 &pipe->pipe_settings.capture.capture_pp_binary); 6566 if (err) 6567 return err; 6568 } else { 6569 post_out_info = *pipe_out_info; 6570 } 6571 6572 /* Post-anr */ 6573 { 6574 struct ia_css_binary_descr post_anr_descr; 6575 6576 ia_css_pipe_get_post_anr_binarydesc(pipe, 6577 &post_anr_descr, &post_in_info, &post_out_info, &vf_info); 6578 err = ia_css_binary_find(&post_anr_descr, 6579 &pipe->pipe_settings.capture.post_isp_binary); 6580 if (err) 6581 return err; 6582 } 6583 6584 /* Anr */ 6585 { 6586 struct ia_css_binary_descr anr_descr; 6587 6588 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info, 6589 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); 6590 err = ia_css_binary_find(&anr_descr, 6591 &pipe->pipe_settings.capture.anr_gdc_binary); 6592 if (err) 6593 return err; 6594 } 6595 pipe->pipe_settings.capture.anr_gdc_binary.left_padding = 6596 pipe->pipe_settings.capture.post_isp_binary.left_padding; 6597 6598 /* Pre-anr */ 6599 { 6600 struct ia_css_binary_descr pre_anr_descr; 6601 6602 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info, 6603 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); 6604 err = ia_css_binary_find(&pre_anr_descr, 6605 &pipe->pipe_settings.capture.pre_isp_binary); 6606 if (err) 6607 return err; 6608 } 6609 pipe->pipe_settings.capture.pre_isp_binary.left_padding = 6610 pipe->pipe_settings.capture.anr_gdc_binary.left_padding; 6611 6612 /* Viewfinder post-processing */ 6613 if (need_pp) { 6614 vf_pp_in_info = 6615 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info; 6616 } else { 6617 vf_pp_in_info = 6618 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info; 6619 } 6620 6621 { 6622 struct ia_css_binary_descr vf_pp_descr; 6623 6624 ia_css_pipe_get_vfpp_binarydesc(pipe, 6625 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); 6626 err = ia_css_binary_find(&vf_pp_descr, 6627 &pipe->pipe_settings.capture.vf_pp_binary); 6628 if (err) 6629 return err; 6630 } 6631 6632 /* Copy */ 6633 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6634 /* For CSI2+, only the direct sensor mode/online requires ISP copy */ 6635 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 6636 #endif 6637 if (need_isp_copy) 6638 err = load_copy_binary(pipe, 6639 &pipe->pipe_settings.capture.copy_binary, 6640 &pipe->pipe_settings.capture.pre_isp_binary); 6641 6642 return err; 6643 } 6644 6645 static bool copy_on_sp(struct ia_css_pipe *pipe) 6646 { 6647 bool rval; 6648 6649 assert(pipe); 6650 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n"); 6651 6652 rval = true; 6653 6654 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 6655 6656 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW); 6657 6658 rval &= ((pipe->stream->config.input_config.format == 6659 ATOMISP_INPUT_FORMAT_BINARY_8) || 6660 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)); 6661 6662 return rval; 6663 } 6664 6665 static int load_capture_binaries( 6666 struct ia_css_pipe *pipe) { 6667 int err = 0; 6668 bool must_be_raw; 6669 6670 IA_CSS_ENTER_PRIVATE(""); 6671 assert(pipe); 6672 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6673 pipe->mode == IA_CSS_PIPE_ID_COPY); 6674 6675 if (pipe->pipe_settings.capture.primary_binary[0].info) { 6676 IA_CSS_LEAVE_ERR_PRIVATE(0); 6677 return 0; 6678 } 6679 6680 /* in primary, advanced,low light or bayer, 6681 the input format must be raw */ 6682 must_be_raw = 6683 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED || 6684 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER || 6685 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT; 6686 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false); 6687 if (err) { 6688 IA_CSS_LEAVE_ERR_PRIVATE(err); 6689 return err; 6690 } 6691 if (copy_on_sp(pipe) && 6692 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { 6693 ia_css_frame_info_init( 6694 &pipe->output_info[0], 6695 JPEG_BYTES, 6696 1, 6697 IA_CSS_FRAME_FORMAT_BINARY_8, 6698 0); 6699 IA_CSS_LEAVE_ERR_PRIVATE(0); 6700 return 0; 6701 } 6702 6703 switch (pipe->config.default_capture_config.mode) { 6704 case IA_CSS_CAPTURE_MODE_RAW: 6705 err = load_copy_binaries(pipe); 6706 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 6707 if (!err) 6708 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; 6709 #endif 6710 break; 6711 case IA_CSS_CAPTURE_MODE_BAYER: 6712 err = load_bayer_isp_binaries(pipe); 6713 break; 6714 case IA_CSS_CAPTURE_MODE_PRIMARY: 6715 err = load_primary_binaries(pipe); 6716 break; 6717 case IA_CSS_CAPTURE_MODE_ADVANCED: 6718 err = load_advanced_binaries(pipe); 6719 break; 6720 case IA_CSS_CAPTURE_MODE_LOW_LIGHT: 6721 err = load_low_light_binaries(pipe); 6722 break; 6723 } 6724 if (err) { 6725 IA_CSS_LEAVE_ERR_PRIVATE(err); 6726 return err; 6727 } 6728 6729 IA_CSS_LEAVE_ERR_PRIVATE(err); 6730 return err; 6731 } 6732 6733 static int 6734 unload_capture_binaries(struct ia_css_pipe *pipe) { 6735 unsigned int i; 6736 6737 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 6738 6739 if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY))) 6740 { 6741 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 6742 return -EINVAL; 6743 } 6744 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary); 6745 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++) 6746 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]); 6747 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary); 6748 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary); 6749 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary); 6750 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary); 6751 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary); 6752 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary); 6753 6754 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++) 6755 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]); 6756 6757 kfree(pipe->pipe_settings.capture.is_output_stage); 6758 pipe->pipe_settings.capture.is_output_stage = NULL; 6759 kfree(pipe->pipe_settings.capture.yuv_scaler_binary); 6760 pipe->pipe_settings.capture.yuv_scaler_binary = NULL; 6761 6762 IA_CSS_LEAVE_ERR_PRIVATE(0); 6763 return 0; 6764 } 6765 6766 static bool 6767 need_downscaling(const struct ia_css_resolution in_res, 6768 const struct ia_css_resolution out_res) { 6769 if (in_res.width > out_res.width || in_res.height > out_res.height) 6770 return true; 6771 6772 return false; 6773 } 6774 6775 static bool 6776 need_yuv_scaler_stage(const struct ia_css_pipe *pipe) { 6777 unsigned int i; 6778 struct ia_css_resolution in_res, out_res; 6779 6780 bool need_format_conversion = false; 6781 6782 IA_CSS_ENTER_PRIVATE(""); 6783 assert(pipe); 6784 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP); 6785 6786 /* TODO: make generic function */ 6787 need_format_conversion = 6788 ((pipe->stream->config.input_config.format == 6789 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) && 6790 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8)); 6791 6792 in_res = pipe->config.input_effective_res; 6793 6794 if (pipe->config.enable_dz) 6795 return true; 6796 6797 if ((pipe->output_info[0].res.width != 0) && need_format_conversion) 6798 return true; 6799 6800 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 6801 out_res = pipe->output_info[i].res; 6802 6803 /* A non-zero width means it is a valid output port */ 6804 if ((out_res.width != 0) && need_downscaling(in_res, out_res)) 6805 return true; 6806 } 6807 6808 return false; 6809 } 6810 6811 /* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */ 6812 /* which has some hard-coded knowledge which prevents reuse of the function. */ 6813 /* Later, merge this with ia_css_pipe_create_cas_scaler_desc */ 6814 static int ia_css_pipe_create_cas_scaler_desc_single_output( 6815 struct ia_css_frame_info *cas_scaler_in_info, 6816 struct ia_css_frame_info *cas_scaler_out_info, 6817 struct ia_css_frame_info *cas_scaler_vf_info, 6818 struct ia_css_cas_binary_descr *descr) { 6819 unsigned int i; 6820 unsigned int hor_ds_factor = 0, ver_ds_factor = 0; 6821 int err = 0; 6822 struct ia_css_frame_info tmp_in_info; 6823 6824 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP; 6825 6826 assert(cas_scaler_in_info); 6827 assert(cas_scaler_out_info); 6828 6829 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6830 "ia_css_pipe_create_cas_scaler_desc() enter:\n"); 6831 6832 /* We assume that this function is used only for single output port case. */ 6833 descr->num_output_stage = 1; 6834 6835 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width, 6836 cas_scaler_out_info->res.width); 6837 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height, 6838 cas_scaler_out_info->res.height); 6839 /* use the same horizontal and vertical downscaling factor for simplicity */ 6840 assert(hor_ds_factor == ver_ds_factor); 6841 6842 i = 1; 6843 while (i < hor_ds_factor) { 6844 descr->num_stage++; 6845 i *= max_scale_factor_per_stage; 6846 } 6847 6848 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 6849 GFP_KERNEL); 6850 if (!descr->in_info) { 6851 err = -ENOMEM; 6852 goto ERR; 6853 } 6854 descr->internal_out_info = kmalloc(descr->num_stage * sizeof( 6855 struct ia_css_frame_info), GFP_KERNEL); 6856 if (!descr->internal_out_info) { 6857 err = -ENOMEM; 6858 goto ERR; 6859 } 6860 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 6861 GFP_KERNEL); 6862 if (!descr->out_info) { 6863 err = -ENOMEM; 6864 goto ERR; 6865 } 6866 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 6867 GFP_KERNEL); 6868 if (!descr->vf_info) { 6869 err = -ENOMEM; 6870 goto ERR; 6871 } 6872 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL); 6873 if (!descr->is_output_stage) { 6874 err = -ENOMEM; 6875 goto ERR; 6876 } 6877 6878 tmp_in_info = *cas_scaler_in_info; 6879 for (i = 0; i < descr->num_stage; i++) { 6880 descr->in_info[i] = tmp_in_info; 6881 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= 6882 cas_scaler_out_info->res.width) { 6883 descr->is_output_stage[i] = true; 6884 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) { 6885 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width; 6886 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height; 6887 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width; 6888 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 6889 } else { 6890 assert(i == (descr->num_stage - 1)); 6891 descr->internal_out_info[i].res.width = 0; 6892 descr->internal_out_info[i].res.height = 0; 6893 } 6894 descr->out_info[i].res.width = cas_scaler_out_info->res.width; 6895 descr->out_info[i].res.height = cas_scaler_out_info->res.height; 6896 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width; 6897 descr->out_info[i].format = cas_scaler_out_info->format; 6898 if (cas_scaler_vf_info) { 6899 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width; 6900 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height; 6901 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width; 6902 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE); 6903 } else { 6904 descr->vf_info[i].res.width = 0; 6905 descr->vf_info[i].res.height = 0; 6906 descr->vf_info[i].padded_width = 0; 6907 } 6908 } else { 6909 descr->is_output_stage[i] = false; 6910 descr->internal_out_info[i].res.width = tmp_in_info.res.width / 6911 max_scale_factor_per_stage; 6912 descr->internal_out_info[i].res.height = tmp_in_info.res.height / 6913 max_scale_factor_per_stage; 6914 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 6915 ia_css_frame_info_init(&descr->internal_out_info[i], 6916 tmp_in_info.res.width / max_scale_factor_per_stage, 6917 tmp_in_info.res.height / max_scale_factor_per_stage, 6918 IA_CSS_FRAME_FORMAT_YUV420, 0); 6919 descr->out_info[i].res.width = 0; 6920 descr->out_info[i].res.height = 0; 6921 descr->vf_info[i].res.width = 0; 6922 descr->vf_info[i].res.height = 0; 6923 } 6924 tmp_in_info = descr->internal_out_info[i]; 6925 } 6926 ERR: 6927 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6928 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n", 6929 err); 6930 return err; 6931 } 6932 6933 /* FIXME: merge most of this and single output version */ 6934 static int ia_css_pipe_create_cas_scaler_desc( 6935 struct ia_css_pipe *pipe, 6936 struct ia_css_cas_binary_descr *descr) { 6937 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; 6938 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 6939 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 6940 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; 6941 unsigned int i, j; 6942 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE], 6943 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE], 6944 scale_factor = 0; 6945 unsigned int num_stages = 0; 6946 int err = 0; 6947 6948 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP; 6949 6950 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6951 "ia_css_pipe_create_cas_scaler_desc() enter:\n"); 6952 6953 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 6954 out_info[i] = NULL; 6955 vf_out_info[i] = NULL; 6956 hor_scale_factor[i] = 0; 6957 ver_scale_factor[i] = 0; 6958 } 6959 6960 in_info.res = pipe->config.input_effective_res; 6961 in_info.padded_width = in_info.res.width; 6962 descr->num_output_stage = 0; 6963 /* Find out how much scaling we need for each output */ 6964 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 6965 if (pipe->output_info[i].res.width != 0) { 6966 out_info[i] = &pipe->output_info[i]; 6967 if (pipe->vf_output_info[i].res.width != 0) 6968 vf_out_info[i] = &pipe->vf_output_info[i]; 6969 descr->num_output_stage += 1; 6970 } 6971 6972 if (out_info[i]) { 6973 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width); 6974 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height); 6975 /* use the same horizontal and vertical scaling factor for simplicity */ 6976 assert(hor_scale_factor[i] == ver_scale_factor[i]); 6977 scale_factor = 1; 6978 do { 6979 num_stages++; 6980 scale_factor *= max_scale_factor_per_stage; 6981 } while (scale_factor < hor_scale_factor[i]); 6982 6983 in_info.res = out_info[i]->res; 6984 } 6985 } 6986 6987 if (need_yuv_scaler_stage(pipe) && (num_stages == 0)) 6988 num_stages = 1; 6989 6990 descr->num_stage = num_stages; 6991 6992 descr->in_info = kmalloc_array(descr->num_stage, 6993 sizeof(struct ia_css_frame_info), GFP_KERNEL); 6994 if (!descr->in_info) { 6995 err = -ENOMEM; 6996 goto ERR; 6997 } 6998 descr->internal_out_info = kmalloc(descr->num_stage * sizeof( 6999 struct ia_css_frame_info), GFP_KERNEL); 7000 if (!descr->internal_out_info) { 7001 err = -ENOMEM; 7002 goto ERR; 7003 } 7004 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 7005 GFP_KERNEL); 7006 if (!descr->out_info) { 7007 err = -ENOMEM; 7008 goto ERR; 7009 } 7010 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 7011 GFP_KERNEL); 7012 if (!descr->vf_info) { 7013 err = -ENOMEM; 7014 goto ERR; 7015 } 7016 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL); 7017 if (!descr->is_output_stage) { 7018 err = -ENOMEM; 7019 goto ERR; 7020 } 7021 7022 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 7023 if (out_info[i]) { 7024 if (i > 0) { 7025 assert((out_info[i - 1]->res.width >= out_info[i]->res.width) && 7026 (out_info[i - 1]->res.height >= out_info[i]->res.height)); 7027 } 7028 } 7029 } 7030 7031 tmp_in_info.res = pipe->config.input_effective_res; 7032 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420; 7033 for (i = 0, j = 0; i < descr->num_stage; i++) { 7034 assert(j < 2); 7035 assert(out_info[j]); 7036 7037 descr->in_info[i] = tmp_in_info; 7038 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= 7039 out_info[j]->res.width) { 7040 descr->is_output_stage[i] = true; 7041 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) { 7042 descr->internal_out_info[i].res.width = out_info[j]->res.width; 7043 descr->internal_out_info[i].res.height = out_info[j]->res.height; 7044 descr->internal_out_info[i].padded_width = out_info[j]->padded_width; 7045 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 7046 } else { 7047 assert(i == (descr->num_stage - 1)); 7048 descr->internal_out_info[i].res.width = 0; 7049 descr->internal_out_info[i].res.height = 0; 7050 } 7051 descr->out_info[i].res.width = out_info[j]->res.width; 7052 descr->out_info[i].res.height = out_info[j]->res.height; 7053 descr->out_info[i].padded_width = out_info[j]->padded_width; 7054 descr->out_info[i].format = out_info[j]->format; 7055 if (vf_out_info[j]) { 7056 descr->vf_info[i].res.width = vf_out_info[j]->res.width; 7057 descr->vf_info[i].res.height = vf_out_info[j]->res.height; 7058 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width; 7059 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE); 7060 } else { 7061 descr->vf_info[i].res.width = 0; 7062 descr->vf_info[i].res.height = 0; 7063 descr->vf_info[i].padded_width = 0; 7064 } 7065 j++; 7066 } else { 7067 descr->is_output_stage[i] = false; 7068 descr->internal_out_info[i].res.width = tmp_in_info.res.width / 7069 max_scale_factor_per_stage; 7070 descr->internal_out_info[i].res.height = tmp_in_info.res.height / 7071 max_scale_factor_per_stage; 7072 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 7073 ia_css_frame_info_init(&descr->internal_out_info[i], 7074 tmp_in_info.res.width / max_scale_factor_per_stage, 7075 tmp_in_info.res.height / max_scale_factor_per_stage, 7076 IA_CSS_FRAME_FORMAT_YUV420, 0); 7077 descr->out_info[i].res.width = 0; 7078 descr->out_info[i].res.height = 0; 7079 descr->vf_info[i].res.width = 0; 7080 descr->vf_info[i].res.height = 0; 7081 } 7082 tmp_in_info = descr->internal_out_info[i]; 7083 } 7084 ERR: 7085 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7086 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n", 7087 err); 7088 return err; 7089 } 7090 7091 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr 7092 *descr) { 7093 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7094 "ia_css_pipe_destroy_cas_scaler_desc() enter:\n"); 7095 kfree(descr->in_info); 7096 descr->in_info = NULL; 7097 kfree(descr->internal_out_info); 7098 descr->internal_out_info = NULL; 7099 kfree(descr->out_info); 7100 descr->out_info = NULL; 7101 kfree(descr->vf_info); 7102 descr->vf_info = NULL; 7103 kfree(descr->is_output_stage); 7104 descr->is_output_stage = NULL; 7105 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7106 "ia_css_pipe_destroy_cas_scaler_desc() leave\n"); 7107 } 7108 7109 static int 7110 load_yuvpp_binaries(struct ia_css_pipe *pipe) { 7111 int err = 0; 7112 bool need_scaler = false; 7113 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 7114 struct ia_css_yuvpp_settings *mycs; 7115 struct ia_css_binary *next_binary; 7116 struct ia_css_cas_binary_descr cas_scaler_descr = { }; 7117 unsigned int i, j; 7118 bool need_isp_copy_binary = false; 7119 7120 IA_CSS_ENTER_PRIVATE(""); 7121 assert(pipe); 7122 assert(pipe->stream); 7123 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP); 7124 7125 if (pipe->pipe_settings.yuvpp.copy_binary.info) 7126 goto ERR; 7127 7128 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */ 7129 err = ia_css_util_check_input(&pipe->stream->config, false, false); 7130 if (err) 7131 goto ERR; 7132 7133 mycs = &pipe->pipe_settings.yuvpp; 7134 7135 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) 7136 { 7137 if (pipe->vf_output_info[i].res.width != 0) { 7138 err = ia_css_util_check_vf_out_info(&pipe->output_info[i], 7139 &pipe->vf_output_info[i]); 7140 if (err) 7141 goto ERR; 7142 } 7143 vf_pp_in_info[i] = NULL; 7144 } 7145 7146 need_scaler = need_yuv_scaler_stage(pipe); 7147 7148 /* we build up the pipeline starting at the end */ 7149 /* Capture post-processing */ 7150 if (need_scaler) 7151 { 7152 struct ia_css_binary_descr yuv_scaler_descr; 7153 7154 err = ia_css_pipe_create_cas_scaler_desc(pipe, 7155 &cas_scaler_descr); 7156 if (err) 7157 goto ERR; 7158 mycs->num_output = cas_scaler_descr.num_output_stage; 7159 mycs->num_yuv_scaler = cas_scaler_descr.num_stage; 7160 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * 7161 sizeof(struct ia_css_binary), GFP_KERNEL); 7162 if (!mycs->yuv_scaler_binary) { 7163 err = -ENOMEM; 7164 goto ERR; 7165 } 7166 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage * 7167 sizeof(bool), GFP_KERNEL); 7168 if (!mycs->is_output_stage) { 7169 err = -ENOMEM; 7170 goto ERR; 7171 } 7172 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 7173 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 7174 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 7175 &yuv_scaler_descr, &cas_scaler_descr.in_info[i], 7176 &cas_scaler_descr.out_info[i], 7177 &cas_scaler_descr.internal_out_info[i], 7178 &cas_scaler_descr.vf_info[i]); 7179 err = ia_css_binary_find(&yuv_scaler_descr, 7180 &mycs->yuv_scaler_binary[i]); 7181 if (err) 7182 goto ERR; 7183 } 7184 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 7185 } else 7186 { 7187 mycs->num_output = 1; 7188 } 7189 7190 if (need_scaler) 7191 { 7192 next_binary = &mycs->yuv_scaler_binary[0]; 7193 } else 7194 { 7195 next_binary = NULL; 7196 } 7197 7198 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 7199 /* 7200 * NOTES 7201 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when 7202 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"? 7203 * 7204 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_ 7205 * binary". However, the "yuv_scale_binary" does NOT support the input-frame 7206 * format as "IA_CSS_STREAM _FORMAT_YUV422_8". 7207 * 7208 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv 7209 * _scale_binary". It would translate the input-frame to the frame formats that 7210 * are supported by the "yuv_scale_binary". 7211 * 7212 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_ 7213 * pp_defs.h" for the list of input-frame formats that are supported by the 7214 * "yuv_scale_binary". 7215 */ 7216 need_isp_copy_binary = 7217 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); 7218 #else /* !USE_INPUT_SYSTEM_VERSION_2401 */ 7219 need_isp_copy_binary = true; 7220 #endif /* USE_INPUT_SYSTEM_VERSION_2401 */ 7221 7222 if (need_isp_copy_binary) 7223 { 7224 err = load_copy_binary(pipe, 7225 &mycs->copy_binary, 7226 next_binary); 7227 7228 if (err) 7229 goto ERR; 7230 7231 /* 7232 * NOTES 7233 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified? 7234 * 7235 * In some use cases, the first stage in the "yuvpp" pipe is the 7236 * "isp_copy_binary". The "isp_copy_binary" is designed to process 7237 * the input from either the system DDR or from the IPU internal VMEM. 7238 * So it provides the flag "online" to specify where its input is from, 7239 * i.e.: 7240 * 7241 * (1) "online <= true", the input is from the IPU internal VMEM. 7242 * (2) "online <= false", the input is from the system DDR. 7243 * 7244 * In other use cases, the first stage in the "yuvpp" pipe is the 7245 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the 7246 * input ONLY from the system DDR. So it does not provide the flag "online" 7247 * to specify where its input is from. 7248 */ 7249 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; 7250 } 7251 7252 /* Viewfinder post-processing */ 7253 if (need_scaler) 7254 { 7255 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) { 7256 if (mycs->is_output_stage[i]) { 7257 assert(j < 2); 7258 vf_pp_in_info[j] = 7259 &mycs->yuv_scaler_binary[i].vf_frame_info; 7260 j++; 7261 } 7262 } 7263 mycs->num_vf_pp = j; 7264 } else 7265 { 7266 vf_pp_in_info[0] = 7267 &mycs->copy_binary.vf_frame_info; 7268 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 7269 vf_pp_in_info[i] = NULL; 7270 } 7271 mycs->num_vf_pp = 1; 7272 } 7273 mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary), 7274 GFP_KERNEL); 7275 if (!mycs->vf_pp_binary) 7276 { 7277 err = -ENOMEM; 7278 goto ERR; 7279 } 7280 7281 { 7282 struct ia_css_binary_descr vf_pp_descr; 7283 7284 for (i = 0; i < mycs->num_vf_pp; i++) 7285 { 7286 if (pipe->vf_output_info[i].res.width != 0) { 7287 ia_css_pipe_get_vfpp_binarydesc(pipe, 7288 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]); 7289 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]); 7290 if (err) 7291 goto ERR; 7292 } 7293 } 7294 } 7295 7296 if (err) 7297 goto ERR; 7298 7299 ERR: 7300 if (need_scaler) 7301 { 7302 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 7303 } 7304 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n", 7305 err); 7306 return err; 7307 } 7308 7309 static int 7310 unload_yuvpp_binaries(struct ia_css_pipe *pipe) { 7311 unsigned int i; 7312 7313 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7314 7315 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) 7316 { 7317 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 7318 return -EINVAL; 7319 } 7320 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary); 7321 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++) 7322 { 7323 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]); 7324 } 7325 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++) 7326 { 7327 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]); 7328 } 7329 kfree(pipe->pipe_settings.yuvpp.is_output_stage); 7330 pipe->pipe_settings.yuvpp.is_output_stage = NULL; 7331 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary); 7332 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL; 7333 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary); 7334 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL; 7335 7336 IA_CSS_LEAVE_ERR_PRIVATE(0); 7337 return 0; 7338 } 7339 7340 static int yuvpp_start(struct ia_css_pipe *pipe) 7341 { 7342 struct ia_css_binary *copy_binary; 7343 int err = 0; 7344 enum sh_css_pipe_config_override copy_ovrd; 7345 enum ia_css_input_mode yuvpp_pipe_input_mode; 7346 7347 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7348 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { 7349 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 7350 return -EINVAL; 7351 } 7352 7353 yuvpp_pipe_input_mode = pipe->stream->config.mode; 7354 7355 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary; 7356 7357 sh_css_metrics_start_frame(); 7358 7359 /* multi stream video needs mipi buffers */ 7360 7361 #if (defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)) 7362 err = send_mipi_frames(pipe); 7363 if (err) { 7364 IA_CSS_LEAVE_ERR_PRIVATE(err); 7365 return err; 7366 } 7367 #endif 7368 7369 { 7370 unsigned int thread_id; 7371 7372 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 7373 copy_ovrd = 1 << thread_id; 7374 } 7375 7376 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode); 7377 7378 IA_CSS_LEAVE_ERR_PRIVATE(err); 7379 return err; 7380 } 7381 7382 static int 7383 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) { 7384 int err = 0; 7385 7386 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7387 7388 if (!pipe) 7389 { 7390 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 7391 return -EINVAL; 7392 } 7393 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ 7394 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 7395 { 7396 IA_CSS_LEAVE_ERR_PRIVATE(0); 7397 return 0; 7398 } 7399 7400 switch (pipe->mode) 7401 { 7402 case IA_CSS_PIPE_ID_PREVIEW: 7403 err = unload_preview_binaries(pipe); 7404 break; 7405 case IA_CSS_PIPE_ID_VIDEO: 7406 err = unload_video_binaries(pipe); 7407 break; 7408 case IA_CSS_PIPE_ID_CAPTURE: 7409 err = unload_capture_binaries(pipe); 7410 break; 7411 case IA_CSS_PIPE_ID_YUVPP: 7412 err = unload_yuvpp_binaries(pipe); 7413 break; 7414 default: 7415 break; 7416 } 7417 IA_CSS_LEAVE_ERR_PRIVATE(err); 7418 return err; 7419 } 7420 7421 static int 7422 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) { 7423 int err = 0; 7424 7425 assert(pipe); 7426 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n"); 7427 7428 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ 7429 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 7430 return err; 7431 7432 switch (pipe->mode) 7433 { 7434 case IA_CSS_PIPE_ID_PREVIEW: 7435 err = load_preview_binaries(pipe); 7436 break; 7437 case IA_CSS_PIPE_ID_VIDEO: 7438 err = load_video_binaries(pipe); 7439 break; 7440 case IA_CSS_PIPE_ID_CAPTURE: 7441 err = load_capture_binaries(pipe); 7442 break; 7443 case IA_CSS_PIPE_ID_YUVPP: 7444 err = load_yuvpp_binaries(pipe); 7445 break; 7446 case IA_CSS_PIPE_ID_ACC: 7447 break; 7448 default: 7449 err = -EINVAL; 7450 break; 7451 } 7452 if (err) 7453 { 7454 if (sh_css_pipe_unload_binaries(pipe)) { 7455 /* currently css does not support multiple error returns in a single function, 7456 * using -EINVAL in this case */ 7457 err = -EINVAL; 7458 } 7459 } 7460 return err; 7461 } 7462 7463 static int 7464 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) { 7465 struct ia_css_pipeline *me; 7466 int err = 0; 7467 struct ia_css_pipeline_stage *vf_pp_stage = NULL, 7468 *copy_stage = NULL, 7469 *yuv_scaler_stage = NULL; 7470 struct ia_css_binary *copy_binary, 7471 *vf_pp_binary, 7472 *yuv_scaler_binary; 7473 bool need_scaler = false; 7474 unsigned int num_stage, num_vf_pp_stage, num_output_stage; 7475 unsigned int i, j; 7476 7477 struct ia_css_frame *in_frame = NULL; 7478 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 7479 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 7480 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 7481 struct ia_css_pipeline_stage_desc stage_desc; 7482 bool need_in_frameinfo_memory = false; 7483 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7484 bool sensor = false; 7485 bool buffered_sensor = false; 7486 bool online = false; 7487 bool continuous = false; 7488 #endif 7489 7490 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7491 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) 7492 { 7493 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 7494 return -EINVAL; 7495 } 7496 me = &pipe->pipeline; 7497 ia_css_pipeline_clean(me); 7498 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) 7499 { 7500 out_frame[i] = NULL; 7501 vf_frame[i] = NULL; 7502 } 7503 ia_css_pipe_util_create_output_frames(bin_out_frame); 7504 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler; 7505 num_vf_pp_stage = pipe->pipe_settings.yuvpp.num_vf_pp; 7506 num_output_stage = pipe->pipe_settings.yuvpp.num_output; 7507 7508 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7509 /* When the input system is 2401, always enable 'in_frameinfo_memory' 7510 * except for the following: 7511 * - Direct Sensor Mode Online Capture 7512 * - Direct Sensor Mode Continuous Capture 7513 * - Buffered Sensor Mode Continuous Capture 7514 */ 7515 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 7516 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; 7517 online = pipe->stream->config.online; 7518 continuous = pipe->stream->config.continuous; 7519 need_in_frameinfo_memory = 7520 !((sensor && (online || continuous)) || (buffered_sensor && continuous)); 7521 #else 7522 /* Construct in_frame info (only in case we have dynamic input */ 7523 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 7524 #endif 7525 /* the input frame can come from: 7526 * a) memory: connect yuvscaler to me->in_frame 7527 * b) sensor, via copy binary: connect yuvscaler to copy binary later on */ 7528 if (need_in_frameinfo_memory) 7529 { 7530 /* TODO: improve for different input formats. */ 7531 7532 /* 7533 * "pipe->stream->config.input_config.format" represents the sensor output 7534 * frame format, e.g. YUV422 8-bit. 7535 * 7536 * "in_frame_format" represents the imaging pipe's input frame format, e.g. 7537 * Bayer-Quad RAW. 7538 */ 7539 int in_frame_format; 7540 7541 if (pipe->stream->config.input_config.format == 7542 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) { 7543 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8; 7544 } else if (pipe->stream->config.input_config.format == 7545 ATOMISP_INPUT_FORMAT_YUV422_8) { 7546 /* 7547 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8", 7548 * the "isp_copy_var" binary is selected as the first stage in the yuvpp 7549 * pipe. 7550 * 7551 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from 7552 * the frame buffer (at DDR) to the frame-line buffer (at VMEM). 7553 * 7554 * By now, the "isp_copy_var" binary does NOT provide a separated 7555 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores 7556 * the YUV422-8 pixels in the frame-line buffer which is designed to 7557 * store the Bayer-Quad RAW pixels. 7558 * 7559 * To direct the "isp_copy_var" binary reading from the RAW frame-line 7560 * buffer, its input frame format must be specified as "IA_CSS_FRAME_ 7561 * FORMAT_RAW". 7562 */ 7563 in_frame_format = IA_CSS_FRAME_FORMAT_RAW; 7564 } else { 7565 in_frame_format = IA_CSS_FRAME_FORMAT_NV12; 7566 } 7567 7568 err = init_in_frameinfo_memory_defaults(pipe, 7569 &me->in_frame, 7570 in_frame_format); 7571 7572 if (err) { 7573 IA_CSS_LEAVE_ERR_PRIVATE(err); 7574 return err; 7575 } 7576 7577 in_frame = &me->in_frame; 7578 } else 7579 { 7580 in_frame = NULL; 7581 } 7582 7583 for (i = 0; i < num_output_stage; i++) 7584 { 7585 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE); 7586 if (pipe->output_info[i].res.width != 0) { 7587 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i); 7588 if (err) { 7589 IA_CSS_LEAVE_ERR_PRIVATE(err); 7590 return err; 7591 } 7592 out_frame[i] = &me->out_frame[i]; 7593 } 7594 7595 /* Construct vf_frame info (only in case we have VF) */ 7596 if (pipe->vf_output_info[i].res.width != 0) { 7597 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i); 7598 if (err) { 7599 IA_CSS_LEAVE_ERR_PRIVATE(err); 7600 return err; 7601 } 7602 vf_frame[i] = &me->vf_frame[i]; 7603 } 7604 } 7605 7606 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary; 7607 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary; 7608 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary; 7609 need_scaler = need_yuv_scaler_stage(pipe); 7610 7611 if (pipe->pipe_settings.yuvpp.copy_binary.info) 7612 { 7613 struct ia_css_frame *in_frame_local = NULL; 7614 7615 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7616 /* After isp copy is enabled in_frame needs to be passed. */ 7617 if (!online) 7618 in_frame_local = in_frame; 7619 #endif 7620 7621 if (need_scaler) { 7622 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL); 7623 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7624 bin_out_frame, in_frame_local, NULL); 7625 } else { 7626 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]); 7627 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7628 bin_out_frame, in_frame_local, NULL); 7629 } 7630 7631 err = ia_css_pipeline_create_and_add_stage(me, 7632 &stage_desc, 7633 ©_stage); 7634 7635 if (err) { 7636 IA_CSS_LEAVE_ERR_PRIVATE(err); 7637 return err; 7638 } 7639 7640 if (copy_stage) { 7641 /* if we use yuv scaler binary, vf output should be from there */ 7642 copy_stage->args.copy_vf = !need_scaler; 7643 /* for yuvpp pipe, it should always be enabled */ 7644 copy_stage->args.copy_output = true; 7645 /* connect output of copy binary to input of yuv scaler */ 7646 in_frame = copy_stage->args.out_frame[0]; 7647 } 7648 } 7649 7650 if (need_scaler) 7651 { 7652 struct ia_css_frame *tmp_out_frame = NULL; 7653 struct ia_css_frame *tmp_vf_frame = NULL; 7654 struct ia_css_frame *tmp_in_frame = in_frame; 7655 7656 for (i = 0, j = 0; i < num_stage; i++) { 7657 assert(j < num_output_stage); 7658 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { 7659 tmp_out_frame = out_frame[j]; 7660 tmp_vf_frame = vf_frame[j]; 7661 } else { 7662 tmp_out_frame = NULL; 7663 tmp_vf_frame = NULL; 7664 } 7665 7666 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, 7667 NULL, 7668 &yuv_scaler_binary[i], 7669 &yuv_scaler_stage); 7670 7671 if (err) { 7672 IA_CSS_LEAVE_ERR_PRIVATE(err); 7673 return err; 7674 } 7675 /* we use output port 1 as internal output port */ 7676 tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; 7677 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { 7678 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) { 7679 in_frame = yuv_scaler_stage->args.out_vf_frame; 7680 err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j], 7681 &vf_pp_stage); 7682 7683 if (err) { 7684 IA_CSS_LEAVE_ERR_PRIVATE(err); 7685 return err; 7686 } 7687 } 7688 j++; 7689 } 7690 } 7691 } else if (copy_stage) 7692 { 7693 if (vf_frame[0] && vf_frame[0]->info.res.width != 0) { 7694 in_frame = copy_stage->args.out_vf_frame; 7695 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0], 7696 &vf_pp_stage); 7697 } 7698 if (err) { 7699 IA_CSS_LEAVE_ERR_PRIVATE(err); 7700 return err; 7701 } 7702 } 7703 7704 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 7705 7706 IA_CSS_LEAVE_ERR_PRIVATE(0); 7707 7708 return 0; 7709 } 7710 7711 static int 7712 create_host_copy_pipeline(struct ia_css_pipe *pipe, 7713 unsigned int max_input_width, 7714 struct ia_css_frame *out_frame) { 7715 struct ia_css_pipeline *me; 7716 int err = 0; 7717 struct ia_css_pipeline_stage_desc stage_desc; 7718 7719 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7720 "create_host_copy_pipeline() enter:\n"); 7721 7722 /* pipeline already created as part of create_host_pipeline_structure */ 7723 me = &pipe->pipeline; 7724 ia_css_pipeline_clean(me); 7725 7726 /* Construct out_frame info */ 7727 out_frame->contiguous = false; 7728 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; 7729 7730 if (copy_on_sp(pipe) && 7731 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) 7732 { 7733 ia_css_frame_info_init( 7734 &out_frame->info, 7735 JPEG_BYTES, 7736 1, 7737 IA_CSS_FRAME_FORMAT_BINARY_8, 7738 0); 7739 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) 7740 { 7741 out_frame->info.raw_bit_depth = 7742 ia_css_pipe_util_pipe_input_format_bpp(pipe); 7743 } 7744 7745 me->num_stages = 1; 7746 me->pipe_id = IA_CSS_PIPE_ID_COPY; 7747 pipe->mode = IA_CSS_PIPE_ID_COPY; 7748 7749 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, 7750 IA_CSS_PIPELINE_RAW_COPY, max_input_width); 7751 err = ia_css_pipeline_create_and_add_stage(me, 7752 &stage_desc, 7753 NULL); 7754 7755 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 7756 7757 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7758 "create_host_copy_pipeline() leave:\n"); 7759 7760 return err; 7761 } 7762 7763 static int 7764 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) { 7765 struct ia_css_pipeline *me = &pipe->pipeline; 7766 int err = 0; 7767 struct ia_css_pipeline_stage_desc stage_desc; 7768 struct ia_css_frame *out_frame = &me->out_frame[0]; 7769 struct ia_css_pipeline_stage *out_stage = NULL; 7770 unsigned int thread_id; 7771 enum sh_css_queue_id queue_id; 7772 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS; 7773 7774 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7775 "create_host_isyscopy_capture_pipeline() enter:\n"); 7776 ia_css_pipeline_clean(me); 7777 7778 /* Construct out_frame info */ 7779 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0); 7780 if (err) 7781 return err; 7782 out_frame->contiguous = false; 7783 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; 7784 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 7785 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id); 7786 out_frame->dynamic_queue_id = queue_id; 7787 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; 7788 7789 me->num_stages = 1; 7790 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE; 7791 pipe->mode = IA_CSS_PIPE_ID_CAPTURE; 7792 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, 7793 IA_CSS_PIPELINE_ISYS_COPY, max_input_width); 7794 err = ia_css_pipeline_create_and_add_stage(me, 7795 &stage_desc, &out_stage); 7796 if (err) 7797 return err; 7798 7799 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous); 7800 7801 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7802 "create_host_isyscopy_capture_pipeline() leave:\n"); 7803 7804 return err; 7805 } 7806 7807 static int 7808 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) { 7809 struct ia_css_pipeline *me; 7810 int err = 0; 7811 enum ia_css_capture_mode mode; 7812 struct ia_css_pipeline_stage *current_stage = NULL; 7813 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL; 7814 struct ia_css_binary *copy_binary, 7815 *primary_binary[MAX_NUM_PRIMARY_STAGES], 7816 *vf_pp_binary, 7817 *pre_isp_binary, 7818 *anr_gdc_binary, 7819 *post_isp_binary, 7820 *yuv_scaler_binary, 7821 *capture_pp_binary, 7822 *capture_ldc_binary; 7823 bool need_pp = false; 7824 bool raw; 7825 7826 struct ia_css_frame *in_frame; 7827 struct ia_css_frame *out_frame; 7828 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 7829 struct ia_css_frame *vf_frame; 7830 struct ia_css_pipeline_stage_desc stage_desc; 7831 bool need_in_frameinfo_memory = false; 7832 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7833 bool sensor = false; 7834 bool buffered_sensor = false; 7835 bool online = false; 7836 bool continuous = false; 7837 #endif 7838 unsigned int i, num_yuv_scaler, num_primary_stage; 7839 bool need_yuv_pp = false; 7840 bool *is_output_stage = NULL; 7841 bool need_ldc = false; 7842 7843 IA_CSS_ENTER_PRIVATE(""); 7844 assert(pipe); 7845 assert(pipe->stream); 7846 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); 7847 7848 me = &pipe->pipeline; 7849 mode = pipe->config.default_capture_config.mode; 7850 raw = (mode == IA_CSS_CAPTURE_MODE_RAW); 7851 ia_css_pipeline_clean(me); 7852 ia_css_pipe_util_create_output_frames(out_frames); 7853 7854 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7855 /* When the input system is 2401, always enable 'in_frameinfo_memory' 7856 * except for the following: 7857 * - Direct Sensor Mode Online Capture 7858 * - Direct Sensor Mode Online Capture 7859 * - Direct Sensor Mode Continuous Capture 7860 * - Buffered Sensor Mode Continuous Capture 7861 */ 7862 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); 7863 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 7864 online = pipe->stream->config.online; 7865 continuous = pipe->stream->config.continuous; 7866 need_in_frameinfo_memory = 7867 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); 7868 #else 7869 /* Construct in_frame info (only in case we have dynamic input */ 7870 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 7871 #endif 7872 if (need_in_frameinfo_memory) 7873 { 7874 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, 7875 IA_CSS_FRAME_FORMAT_RAW); 7876 if (err) { 7877 IA_CSS_LEAVE_ERR_PRIVATE(err); 7878 return err; 7879 } 7880 7881 in_frame = &me->in_frame; 7882 } else 7883 { 7884 in_frame = NULL; 7885 } 7886 7887 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); 7888 if (err) 7889 { 7890 IA_CSS_LEAVE_ERR_PRIVATE(err); 7891 return err; 7892 } 7893 out_frame = &me->out_frame[0]; 7894 7895 /* Construct vf_frame info (only in case we have VF) */ 7896 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) 7897 { 7898 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) { 7899 /* These modes don't support viewfinder output */ 7900 vf_frame = NULL; 7901 } else { 7902 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0); 7903 vf_frame = &me->vf_frame[0]; 7904 } 7905 } else 7906 { 7907 vf_frame = NULL; 7908 } 7909 7910 copy_binary = &pipe->pipe_settings.capture.copy_binary; 7911 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage; 7912 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) 7913 { 7914 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 7915 return -EINVAL; 7916 } 7917 for (i = 0; i < num_primary_stage; i++) 7918 { 7919 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i]; 7920 } 7921 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary; 7922 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary; 7923 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary; 7924 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary; 7925 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary; 7926 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary; 7927 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler; 7928 is_output_stage = pipe->pipe_settings.capture.is_output_stage; 7929 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary; 7930 7931 need_pp = (need_capture_pp(pipe) || pipe->output_stage) && 7932 mode != IA_CSS_CAPTURE_MODE_RAW && 7933 mode != IA_CSS_CAPTURE_MODE_BAYER; 7934 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info); 7935 need_ldc = (capture_ldc_binary && capture_ldc_binary->info); 7936 7937 if (pipe->pipe_settings.capture.copy_binary.info) 7938 { 7939 if (raw) { 7940 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 7941 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 7942 if (!continuous) { 7943 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7944 out_frames, in_frame, NULL); 7945 } else { 7946 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 7947 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7948 out_frames, in_frame, NULL); 7949 } 7950 #else 7951 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7952 out_frames, NULL, NULL); 7953 #endif 7954 } else { 7955 ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame); 7956 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7957 out_frames, NULL, NULL); 7958 } 7959 7960 err = ia_css_pipeline_create_and_add_stage(me, 7961 &stage_desc, 7962 ¤t_stage); 7963 if (err) { 7964 IA_CSS_LEAVE_ERR_PRIVATE(err); 7965 return err; 7966 } 7967 } else if (pipe->stream->config.continuous) 7968 { 7969 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 7970 } 7971 7972 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) 7973 { 7974 struct ia_css_frame *local_in_frame = NULL; 7975 struct ia_css_frame *local_out_frame = NULL; 7976 7977 for (i = 0; i < num_primary_stage; i++) { 7978 if (i == 0) 7979 local_in_frame = in_frame; 7980 else 7981 local_in_frame = NULL; 7982 #ifndef ISP2401 7983 if (!need_pp && (i == num_primary_stage - 1)) 7984 #else 7985 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc) 7986 #endif 7987 local_out_frame = out_frame; 7988 else 7989 local_out_frame = NULL; 7990 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame); 7991 /* 7992 * WARNING: The #if def flag has been added below as a 7993 * temporary solution to solve the problem of enabling the 7994 * view finder in a single binary in a capture flow. The 7995 * vf-pp stage has been removed from Skycam in the solution 7996 * provided. The vf-pp stage should be re-introduced when 7997 * required. This * should not be considered as a clean solution. 7998 * Proper investigation should be done to come up with the clean 7999 * solution. 8000 * */ 8001 ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i], 8002 out_frames, local_in_frame, NULL); 8003 err = ia_css_pipeline_create_and_add_stage(me, 8004 &stage_desc, 8005 ¤t_stage); 8006 if (err) { 8007 IA_CSS_LEAVE_ERR_PRIVATE(err); 8008 return err; 8009 } 8010 } 8011 /* If we use copy iso primary, 8012 the input must be yuv iso raw */ 8013 current_stage->args.copy_vf = 8014 primary_binary[0]->info->sp.pipeline.mode == 8015 IA_CSS_BINARY_MODE_COPY; 8016 current_stage->args.copy_output = current_stage->args.copy_vf; 8017 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED || 8018 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) 8019 { 8020 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 8021 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, 8022 out_frames, in_frame, NULL); 8023 err = ia_css_pipeline_create_and_add_stage(me, 8024 &stage_desc, NULL); 8025 if (err) { 8026 IA_CSS_LEAVE_ERR_PRIVATE(err); 8027 return err; 8028 } 8029 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 8030 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary, 8031 out_frames, NULL, NULL); 8032 err = ia_css_pipeline_create_and_add_stage(me, 8033 &stage_desc, NULL); 8034 if (err) { 8035 IA_CSS_LEAVE_ERR_PRIVATE(err); 8036 return err; 8037 } 8038 8039 if (need_pp) { 8040 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 8041 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary, 8042 out_frames, NULL, NULL); 8043 } else { 8044 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 8045 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary, 8046 out_frames, NULL, NULL); 8047 } 8048 8049 err = ia_css_pipeline_create_and_add_stage(me, 8050 &stage_desc, ¤t_stage); 8051 if (err) { 8052 IA_CSS_LEAVE_ERR_PRIVATE(err); 8053 return err; 8054 } 8055 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) 8056 { 8057 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 8058 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, 8059 out_frames, in_frame, NULL); 8060 err = ia_css_pipeline_create_and_add_stage(me, 8061 &stage_desc, 8062 NULL); 8063 if (err) { 8064 IA_CSS_LEAVE_ERR_PRIVATE(err); 8065 return err; 8066 } 8067 } 8068 8069 #ifndef ISP2401 8070 if (need_pp && current_stage) 8071 { 8072 struct ia_css_frame *local_in_frame = NULL; 8073 8074 local_in_frame = current_stage->args.out_frame[0]; 8075 8076 if (need_ldc) { 8077 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 8078 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, 8079 out_frames, local_in_frame, NULL); 8080 err = ia_css_pipeline_create_and_add_stage(me, 8081 &stage_desc, 8082 ¤t_stage); 8083 local_in_frame = current_stage->args.out_frame[0]; 8084 } 8085 err = add_capture_pp_stage(pipe, me, local_in_frame, 8086 need_yuv_pp ? NULL : out_frame, 8087 #else 8088 /* ldc and capture_pp not supported in same pipeline */ 8089 if (need_ldc && current_stage) 8090 { 8091 in_frame = current_stage->args.out_frame[0]; 8092 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 8093 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, 8094 out_frames, in_frame, NULL); 8095 err = ia_css_pipeline_create_and_add_stage(me, 8096 &stage_desc, 8097 NULL); 8098 } else if (need_pp && current_stage) 8099 { 8100 in_frame = current_stage->args.out_frame[0]; 8101 err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame, 8102 #endif 8103 capture_pp_binary, 8104 ¤t_stage); 8105 if (err) { 8106 IA_CSS_LEAVE_ERR_PRIVATE(err); 8107 return err; 8108 } 8109 } 8110 8111 if (need_yuv_pp && current_stage) 8112 { 8113 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0]; 8114 struct ia_css_frame *tmp_out_frame = NULL; 8115 8116 for (i = 0; i < num_yuv_scaler; i++) { 8117 if (is_output_stage[i] == true) 8118 tmp_out_frame = out_frame; 8119 else 8120 tmp_out_frame = NULL; 8121 8122 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, 8123 NULL, 8124 &yuv_scaler_binary[i], 8125 &yuv_scaler_stage); 8126 if (err) { 8127 IA_CSS_LEAVE_ERR_PRIVATE(err); 8128 return err; 8129 } 8130 /* we use output port 1 as internal output port */ 8131 tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; 8132 } 8133 } 8134 8135 /* 8136 * WARNING: The #if def flag has been added below as a 8137 * temporary solution to solve the problem of enabling the 8138 * view finder in a single binary in a capture flow. The vf-pp 8139 * stage has been removed from Skycam in the solution provided. 8140 * The vf-pp stage should be re-introduced when required. This 8141 * should not be considered as a clean solution. Proper 8142 * investigation should be done to come up with the clean solution. 8143 * */ 8144 if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) 8145 { 8146 in_frame = current_stage->args.out_vf_frame; 8147 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary, 8148 ¤t_stage); 8149 if (err) { 8150 IA_CSS_LEAVE_ERR_PRIVATE(err); 8151 return err; 8152 } 8153 } 8154 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 8155 8156 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8157 "create_host_regular_capture_pipeline() leave:\n"); 8158 8159 return 0; 8160 } 8161 8162 static int 8163 create_host_capture_pipeline(struct ia_css_pipe *pipe) { 8164 int err = 0; 8165 8166 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 8167 8168 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 8169 err = create_host_isyscopy_capture_pipeline(pipe); 8170 else 8171 err = create_host_regular_capture_pipeline(pipe); 8172 if (err) 8173 { 8174 IA_CSS_LEAVE_ERR_PRIVATE(err); 8175 return err; 8176 } 8177 8178 IA_CSS_LEAVE_ERR_PRIVATE(err); 8179 8180 return err; 8181 } 8182 8183 static int capture_start( 8184 struct ia_css_pipe *pipe) { 8185 struct ia_css_pipeline *me; 8186 8187 int err = 0; 8188 enum sh_css_pipe_config_override copy_ovrd; 8189 8190 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 8191 if (!pipe) { 8192 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 8193 return -EINVAL; 8194 } 8195 8196 me = &pipe->pipeline; 8197 8198 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || 8199 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) && 8200 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { 8201 if (copy_on_sp(pipe)) { 8202 err = start_copy_on_sp(pipe, &me->out_frame[0]); 8203 IA_CSS_LEAVE_ERR_PRIVATE(err); 8204 return err; 8205 } 8206 } 8207 8208 #if defined(USE_INPUT_SYSTEM_VERSION_2) 8209 /* old isys: need to send_mipi_frames() in all pipe modes */ 8210 err = send_mipi_frames(pipe); 8211 if (err) { 8212 IA_CSS_LEAVE_ERR_PRIVATE(err); 8213 return err; 8214 } 8215 #elif defined(USE_INPUT_SYSTEM_VERSION_2401) 8216 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) { 8217 err = send_mipi_frames(pipe); 8218 if (err) { 8219 IA_CSS_LEAVE_ERR_PRIVATE(err); 8220 return err; 8221 } 8222 } 8223 8224 #endif 8225 8226 { 8227 unsigned int thread_id; 8228 8229 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 8230 copy_ovrd = 1 << thread_id; 8231 } 8232 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode); 8233 8234 #if !defined(USE_INPUT_SYSTEM_VERSION_2401) 8235 /* 8236 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured, 8237 * which is currently done in start_binary(); but COPY pipe contains no binary, 8238 * and does not call start_binary(); so we need to configure the rx here. 8239 */ 8240 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY && 8241 pipe->stream->reconfigure_css_rx) { 8242 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, 8243 pipe->stream->config.mode); 8244 pipe->stream->reconfigure_css_rx = false; 8245 } 8246 #endif 8247 8248 IA_CSS_LEAVE_ERR_PRIVATE(err); 8249 return err; 8250 } 8251 8252 static int 8253 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, 8254 struct ia_css_frame_info *info, 8255 unsigned int idx) { 8256 assert(pipe); 8257 assert(info); 8258 8259 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8260 "sh_css_pipe_get_output_frame_info() enter:\n"); 8261 8262 *info = pipe->output_info[idx]; 8263 if (copy_on_sp(pipe) && 8264 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) 8265 { 8266 ia_css_frame_info_init( 8267 info, 8268 JPEG_BYTES, 8269 1, 8270 IA_CSS_FRAME_FORMAT_BINARY_8, 8271 0); 8272 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW || 8273 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) 8274 { 8275 info->raw_bit_depth = 8276 ia_css_pipe_util_pipe_input_format_bpp(pipe); 8277 } 8278 8279 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8280 "sh_css_pipe_get_output_frame_info() leave:\n"); 8281 return 0; 8282 } 8283 8284 void 8285 ia_css_stream_send_input_frame(const struct ia_css_stream *stream, 8286 const unsigned short *data, 8287 unsigned int width, 8288 unsigned int height) { 8289 assert(stream); 8290 8291 ia_css_inputfifo_send_input_frame( 8292 data, width, height, 8293 stream->config.channel_id, 8294 stream->config.input_config.format, 8295 stream->config.pixels_per_clock == 2); 8296 } 8297 8298 void 8299 ia_css_stream_start_input_frame(const struct ia_css_stream *stream) { 8300 assert(stream); 8301 8302 ia_css_inputfifo_start_frame( 8303 stream->config.channel_id, 8304 stream->config.input_config.format, 8305 stream->config.pixels_per_clock == 2); 8306 } 8307 8308 void 8309 ia_css_stream_send_input_line(const struct ia_css_stream *stream, 8310 const unsigned short *data, 8311 unsigned int width, 8312 const unsigned short *data2, 8313 unsigned int width2) { 8314 assert(stream); 8315 8316 ia_css_inputfifo_send_line(stream->config.channel_id, 8317 data, width, data2, width2); 8318 } 8319 8320 void 8321 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream, 8322 enum atomisp_input_format format, 8323 const unsigned short *data, 8324 unsigned int width) { 8325 assert(stream); 8326 if (!data || width == 0) 8327 return; 8328 ia_css_inputfifo_send_embedded_line(stream->config.channel_id, 8329 format, data, width); 8330 } 8331 8332 void 8333 ia_css_stream_end_input_frame(const struct ia_css_stream *stream) { 8334 assert(stream); 8335 8336 ia_css_inputfifo_end_frame(stream->config.channel_id); 8337 } 8338 8339 static void 8340 append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) { 8341 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware); 8342 if (!l) { 8343 IA_CSS_ERROR("NULL fw_info"); 8344 IA_CSS_LEAVE_PRIVATE(""); 8345 return; 8346 } 8347 while (*l) 8348 l = &(*l)->next; 8349 *l = firmware; 8350 /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */ 8351 IA_CSS_LEAVE_PRIVATE(""); 8352 } 8353 8354 static void 8355 remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) { 8356 assert(*l); 8357 assert(firmware); 8358 (void)l; 8359 (void)firmware; 8360 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n"); 8361 8362 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n"); 8363 return; /* removing single and multiple firmware is handled in acc_unload_extension() */ 8364 } 8365 8366 static int upload_isp_code(struct ia_css_fw_info *firmware) 8367 { 8368 ia_css_ptr binary; 8369 8370 if (!firmware) { 8371 IA_CSS_ERROR("NULL input parameter"); 8372 return -EINVAL; 8373 } 8374 binary = firmware->info.isp.xmem_addr; 8375 8376 if (!binary) { 8377 unsigned int size = firmware->blob.size; 8378 const unsigned char *blob; 8379 const unsigned char *binary_name; 8380 8381 binary_name = 8382 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME( 8383 firmware)); 8384 blob = binary_name + 8385 strlen((const char *)binary_name) + 8386 1; 8387 binary = sh_css_load_blob(blob, size); 8388 firmware->info.isp.xmem_addr = binary; 8389 } 8390 8391 if (!binary) 8392 return -ENOMEM; 8393 return 0; 8394 } 8395 8396 static int 8397 acc_load_extension(struct ia_css_fw_info *firmware) { 8398 int err; 8399 struct ia_css_fw_info *hd = firmware; 8400 8401 while (hd) 8402 { 8403 err = upload_isp_code(hd); 8404 if (err) 8405 return err; 8406 hd = hd->next; 8407 } 8408 8409 if (!firmware) 8410 return -EINVAL; 8411 firmware->loaded = true; 8412 return 0; 8413 } 8414 8415 static void 8416 acc_unload_extension(struct ia_css_fw_info *firmware) { 8417 struct ia_css_fw_info *hd = firmware; 8418 struct ia_css_fw_info *hdn = NULL; 8419 8420 if (!firmware) /* should not happen */ 8421 return; 8422 /* unload and remove multiple firmwares */ 8423 while (hd) { 8424 hdn = (hd->next) ? &(*hd->next) : NULL; 8425 if (hd->info.isp.xmem_addr) { 8426 hmm_free(hd->info.isp.xmem_addr); 8427 hd->info.isp.xmem_addr = mmgr_NULL; 8428 } 8429 hd->isp_code = NULL; 8430 hd->next = NULL; 8431 hd = hdn; 8432 } 8433 8434 firmware->loaded = false; 8435 } 8436 8437 /* Load firmware for extension */ 8438 static int 8439 ia_css_pipe_load_extension(struct ia_css_pipe *pipe, 8440 struct ia_css_fw_info *firmware) { 8441 int err = 0; 8442 8443 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); 8444 8445 if ((!firmware) || (!pipe)) 8446 { 8447 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 8448 return -EINVAL; 8449 } 8450 8451 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT) 8452 append_firmware(&pipe->output_stage, firmware); 8453 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER) 8454 append_firmware(&pipe->vf_stage, firmware); 8455 err = acc_load_extension(firmware); 8456 8457 IA_CSS_LEAVE_ERR_PRIVATE(err); 8458 return err; 8459 } 8460 8461 /* Unload firmware for extension */ 8462 static void 8463 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe, 8464 struct ia_css_fw_info *firmware) { 8465 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); 8466 8467 if ((!firmware) || (!pipe)) { 8468 IA_CSS_ERROR("NULL input parameters"); 8469 IA_CSS_LEAVE_PRIVATE(""); 8470 return; 8471 } 8472 8473 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT) 8474 remove_firmware(&pipe->output_stage, firmware); 8475 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER) 8476 remove_firmware(&pipe->vf_stage, firmware); 8477 acc_unload_extension(firmware); 8478 8479 IA_CSS_LEAVE_PRIVATE(""); 8480 } 8481 8482 bool 8483 ia_css_pipeline_uses_params(struct ia_css_pipeline *me) { 8484 struct ia_css_pipeline_stage *stage; 8485 8486 assert(me); 8487 8488 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8489 "ia_css_pipeline_uses_params() enter: me=%p\n", me); 8490 8491 for (stage = me->stages; stage; stage = stage->next) 8492 if (stage->binary_info && stage->binary_info->enable.params) { 8493 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8494 "ia_css_pipeline_uses_params() leave: return_bool=true\n"); 8495 return true; 8496 } 8497 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8498 "ia_css_pipeline_uses_params() leave: return_bool=false\n"); 8499 return false; 8500 } 8501 8502 static int 8503 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, 8504 const void *acc_fw) { 8505 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw; 8506 /* In QoS case, load_extension already called, so skipping */ 8507 int err = 0; 8508 8509 if (fw->loaded == false) 8510 err = acc_load_extension(fw); 8511 8512 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8513 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n", 8514 pipeline, acc_fw); 8515 8516 if (!err) 8517 { 8518 struct ia_css_pipeline_stage_desc stage_desc; 8519 8520 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw); 8521 err = ia_css_pipeline_create_and_add_stage(pipeline, 8522 &stage_desc, 8523 NULL); 8524 } 8525 8526 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8527 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n", err); 8528 return err; 8529 } 8530 8531 /* 8532 * @brief Tag a specific frame in continuous capture. 8533 * Refer to "sh_css_internal.h" for details. 8534 */ 8535 int ia_css_stream_capture_frame(struct ia_css_stream *stream, 8536 unsigned int exp_id) { 8537 struct sh_css_tag_descr tag_descr; 8538 u32 encoded_tag_descr; 8539 int err; 8540 8541 assert(stream); 8542 IA_CSS_ENTER("exp_id=%d", exp_id); 8543 8544 /* Only continuous streams have a tagger */ 8545 if (exp_id == 0 || !stream->config.continuous) { 8546 IA_CSS_LEAVE_ERR(-EINVAL); 8547 return -EINVAL; 8548 } 8549 8550 if (!sh_css_sp_is_running()) { 8551 /* SP is not running. The queues are not valid */ 8552 IA_CSS_LEAVE_ERR(-EBUSY); 8553 return -EBUSY; 8554 } 8555 8556 /* Create the tag descriptor from the parameters */ 8557 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr); 8558 /* Encode the tag descriptor into a 32-bit value */ 8559 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); 8560 /* Enqueue the encoded tag to the host2sp queue. 8561 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 8562 * on both host and the SP side. 8563 * It is mainly because it is enough to have only one tag_cmd queue */ 8564 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr); 8565 8566 IA_CSS_LEAVE_ERR(err); 8567 return err; 8568 } 8569 8570 /* 8571 * @brief Configure the continuous capture. 8572 * Refer to "sh_css_internal.h" for details. 8573 */ 8574 int ia_css_stream_capture( 8575 struct ia_css_stream *stream, 8576 int num_captures, 8577 unsigned int skip, 8578 int offset) { 8579 struct sh_css_tag_descr tag_descr; 8580 unsigned int encoded_tag_descr; 8581 int return_err; 8582 8583 if (!stream) 8584 return -EINVAL; 8585 8586 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8587 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n", 8588 num_captures, skip, offset); 8589 8590 /* Check if the tag descriptor is valid */ 8591 if (num_captures < SH_CSS_MINIMUM_TAG_ID) { 8592 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8593 "ia_css_stream_capture() leave: return_err=%d\n", 8594 -EINVAL); 8595 return -EINVAL; 8596 } 8597 8598 /* Create the tag descriptor from the parameters */ 8599 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr); 8600 8601 /* Encode the tag descriptor into a 32-bit value */ 8602 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); 8603 8604 if (!sh_css_sp_is_running()) { 8605 /* SP is not running. The queues are not valid */ 8606 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8607 "ia_css_stream_capture() leaving:queues unavailable\n"); 8608 return -EBUSY; 8609 } 8610 8611 /* Enqueue the encoded tag to the host2sp queue. 8612 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 8613 * on both host and the SP side. 8614 * It is mainly because it is enough to have only one tag_cmd queue */ 8615 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr); 8616 8617 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8618 "ia_css_stream_capture() leave: return_err=%d\n", 8619 return_err); 8620 8621 return return_err; 8622 } 8623 8624 void ia_css_stream_request_flash(struct ia_css_stream *stream) 8625 { 8626 (void)stream; 8627 8628 assert(stream); 8629 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8630 "ia_css_stream_request_flash() enter: void\n"); 8631 8632 #ifndef ISP2401 8633 sh_css_write_host2sp_command(host2sp_cmd_start_flash); 8634 #else 8635 if (sh_css_sp_is_running()) { 8636 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) { 8637 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); 8638 ia_css_debug_dump_sp_sw_debug_info(); 8639 ia_css_debug_dump_debug_info(NULL); 8640 } 8641 } else 8642 IA_CSS_LOG("SP is not running!"); 8643 8644 #endif 8645 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8646 "ia_css_stream_request_flash() leave: return_void\n"); 8647 } 8648 8649 static void 8650 sh_css_init_host_sp_control_vars(void) { 8651 const struct ia_css_fw_info *fw; 8652 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started; 8653 8654 unsigned int HIVE_ADDR_host_sp_queues_initialized; 8655 unsigned int HIVE_ADDR_sp_sleep_mode; 8656 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; 8657 #ifndef ISP2401 8658 unsigned int HIVE_ADDR_sp_stop_copy_preview; 8659 #endif 8660 unsigned int HIVE_ADDR_host_sp_com; 8661 unsigned int o = offsetof(struct host_sp_communication, host2sp_command) 8662 / sizeof(int); 8663 8664 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 8665 unsigned int i; 8666 #endif 8667 8668 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8669 "sh_css_init_host_sp_control_vars() enter: void\n"); 8670 8671 fw = &sh_css_sp_fw; 8672 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started; 8673 8674 HIVE_ADDR_host_sp_queues_initialized = 8675 fw->info.sp.host_sp_queues_initialized; 8676 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode; 8677 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb; 8678 #ifndef ISP2401 8679 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview; 8680 #endif 8681 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; 8682 8683 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */ 8684 8685 (void)HIVE_ADDR_sp_sleep_mode; 8686 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; 8687 #ifndef ISP2401 8688 (void)HIVE_ADDR_sp_stop_copy_preview; 8689 #endif 8690 (void)HIVE_ADDR_host_sp_com; 8691 8692 sp_dmem_store_uint32(SP0_ID, 8693 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started), 8694 (uint32_t)(0)); 8695 8696 sp_dmem_store_uint32(SP0_ID, 8697 (unsigned int)sp_address_of(host_sp_queues_initialized), 8698 (uint32_t)(0)); 8699 sp_dmem_store_uint32(SP0_ID, 8700 (unsigned int)sp_address_of(sp_sleep_mode), 8701 (uint32_t)(0)); 8702 sp_dmem_store_uint32(SP0_ID, 8703 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb), 8704 (uint32_t)(false)); 8705 #ifndef ISP2401 8706 sp_dmem_store_uint32(SP0_ID, 8707 (unsigned int)sp_address_of(sp_stop_copy_preview), 8708 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0)); 8709 #endif 8710 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready); 8711 8712 for (i = 0; i < N_CSI_PORTS; i++) { 8713 sh_css_update_host2sp_num_mipi_frames 8714 (my_css.num_mipi_frames[i]); 8715 } 8716 8717 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8718 "sh_css_init_host_sp_control_vars() leave: return_void\n"); 8719 } 8720 8721 /* 8722 * create the internal structures and fill in the configuration data 8723 */ 8724 8725 static const struct 8726 ia_css_pipe_config ia_css_pipe_default_config = DEFAULT_PIPE_CONFIG; 8727 8728 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config) 8729 { 8730 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n"); 8731 memcpy(pipe_config, &ia_css_pipe_default_config, sizeof(*pipe_config)); 8732 } 8733 8734 void 8735 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config 8736 *extra_config) { 8737 if (!extra_config) { 8738 IA_CSS_ERROR("NULL input parameter"); 8739 return; 8740 } 8741 8742 extra_config->enable_raw_binning = false; 8743 extra_config->enable_yuv_ds = false; 8744 extra_config->enable_high_speed = false; 8745 extra_config->enable_dvs_6axis = false; 8746 extra_config->enable_reduced_pipe = false; 8747 extra_config->disable_vf_pp = false; 8748 extra_config->enable_fractional_ds = false; 8749 } 8750 8751 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config) 8752 { 8753 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n"); 8754 assert(stream_config); 8755 memset(stream_config, 0, sizeof(*stream_config)); 8756 stream_config->online = true; 8757 stream_config->left_padding = -1; 8758 stream_config->pixels_per_clock = 1; 8759 /* temporary default value for backwards compatibility. 8760 * This field used to be hardcoded within CSS but this has now 8761 * been moved to the stream_config struct. */ 8762 stream_config->source.port.rxcount = 0x04040404; 8763 } 8764 8765 static int 8766 ia_css_acc_pipe_create(struct ia_css_pipe *pipe) { 8767 int err = 0; 8768 8769 if (!pipe) 8770 { 8771 IA_CSS_ERROR("NULL input parameter"); 8772 return -EINVAL; 8773 } 8774 8775 /* There is not meaning for num_execs = 0 semantically. Run atleast once. */ 8776 if (pipe->config.acc_num_execs == 0) 8777 pipe->config.acc_num_execs = 1; 8778 8779 if (pipe->config.acc_extension) 8780 { 8781 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension); 8782 } 8783 8784 return err; 8785 } 8786 8787 int 8788 ia_css_pipe_create(const struct ia_css_pipe_config *config, 8789 struct ia_css_pipe **pipe) { 8790 #ifndef ISP2401 8791 if (!config) 8792 #else 8793 int err = 0; 8794 8795 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe); 8796 8797 if (!config) 8798 { 8799 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 8800 #endif 8801 return -EINVAL; 8802 #ifndef ISP2401 8803 if (!pipe) 8804 #else 8805 } 8806 8807 if (!pipe) 8808 { 8809 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 8810 #endif 8811 return -EINVAL; 8812 #ifndef ISP2401 8813 return ia_css_pipe_create_extra(config, NULL, pipe); 8814 #else 8815 } 8816 8817 err = ia_css_pipe_create_extra(config, NULL, pipe); 8818 8819 if (err == 0) 8820 { 8821 IA_CSS_LOG("pipe created successfully = %p", *pipe); 8822 } 8823 8824 IA_CSS_LEAVE_ERR_PRIVATE(err); 8825 8826 return err; 8827 #endif 8828 } 8829 8830 int 8831 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config, 8832 const struct ia_css_pipe_extra_config *extra_config, 8833 struct ia_css_pipe **pipe) { 8834 int err = -EINVAL; 8835 struct ia_css_pipe *internal_pipe = NULL; 8836 unsigned int i; 8837 8838 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe); 8839 8840 /* do not allow to create more than the maximum limit */ 8841 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) 8842 { 8843 IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC); 8844 return -EINVAL; 8845 } 8846 8847 if ((!pipe) || (!config)) 8848 { 8849 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 8850 return -EINVAL; 8851 } 8852 8853 ia_css_debug_dump_pipe_config(config); 8854 ia_css_debug_dump_pipe_extra_config(extra_config); 8855 8856 err = create_pipe(config->mode, &internal_pipe, false); 8857 if (err) 8858 { 8859 IA_CSS_LEAVE_ERR_PRIVATE(err); 8860 return err; 8861 } 8862 8863 /* now we have a pipe structure to fill */ 8864 internal_pipe->config = *config; 8865 if (extra_config) 8866 internal_pipe->extra_config = *extra_config; 8867 else 8868 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config); 8869 8870 if (config->mode == IA_CSS_PIPE_MODE_ACC) 8871 { 8872 /* Temporary hack to migrate acceleration to CSS 2.0. 8873 * In the future the code for all pipe types should be 8874 * unified. */ 8875 *pipe = internal_pipe; 8876 if (!internal_pipe->config.acc_extension && 8877 internal_pipe->config.num_acc_stages == 8878 0) { /* if no acc binary and no standalone stage */ 8879 *pipe = NULL; 8880 IA_CSS_LEAVE_ERR_PRIVATE(0); 8881 return 0; 8882 } 8883 return ia_css_acc_pipe_create(internal_pipe); 8884 } 8885 8886 /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */ 8887 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2) 8888 internal_pipe->dvs_frame_delay = 2; 8889 else 8890 internal_pipe->dvs_frame_delay = 1; 8891 8892 /* we still keep enable_raw_binning for backward compatibility, for any new 8893 fractional bayer downscaling, we should use bayer_ds_out_res. if both are 8894 specified, bayer_ds_out_res will take precedence.if none is specified, we 8895 set bayer_ds_out_res equal to IF output resolution(IF may do cropping on 8896 sensor output) or use default decimation factor 1. */ 8897 if (internal_pipe->extra_config.enable_raw_binning && 8898 internal_pipe->config.bayer_ds_out_res.width) 8899 { 8900 /* fill some code here, if no code is needed, please remove it during integration */ 8901 } 8902 8903 /* YUV downscaling */ 8904 if ((internal_pipe->config.vf_pp_in_res.width || 8905 internal_pipe->config.capt_pp_in_res.width)) 8906 { 8907 enum ia_css_frame_format format; 8908 8909 if (internal_pipe->config.vf_pp_in_res.width) { 8910 format = IA_CSS_FRAME_FORMAT_YUV_LINE; 8911 ia_css_frame_info_init( 8912 &internal_pipe->vf_yuv_ds_input_info, 8913 internal_pipe->config.vf_pp_in_res.width, 8914 internal_pipe->config.vf_pp_in_res.height, 8915 format, 0); 8916 } 8917 if (internal_pipe->config.capt_pp_in_res.width) { 8918 format = IA_CSS_FRAME_FORMAT_YUV420; 8919 ia_css_frame_info_init( 8920 &internal_pipe->out_yuv_ds_input_info, 8921 internal_pipe->config.capt_pp_in_res.width, 8922 internal_pipe->config.capt_pp_in_res.height, 8923 format, 0); 8924 } 8925 } 8926 if (internal_pipe->config.vf_pp_in_res.width && 8927 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 8928 { 8929 ia_css_frame_info_init( 8930 &internal_pipe->vf_yuv_ds_input_info, 8931 internal_pipe->config.vf_pp_in_res.width, 8932 internal_pipe->config.vf_pp_in_res.height, 8933 IA_CSS_FRAME_FORMAT_YUV_LINE, 0); 8934 } 8935 /* handle bayer downscaling output info */ 8936 if (internal_pipe->config.bayer_ds_out_res.width) 8937 { 8938 ia_css_frame_info_init( 8939 &internal_pipe->bds_output_info, 8940 internal_pipe->config.bayer_ds_out_res.width, 8941 internal_pipe->config.bayer_ds_out_res.height, 8942 IA_CSS_FRAME_FORMAT_RAW, 0); 8943 } 8944 8945 /* handle output info, assume always needed */ 8946 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) 8947 { 8948 if (internal_pipe->config.output_info[i].res.width) { 8949 err = sh_css_pipe_configure_output( 8950 internal_pipe, 8951 internal_pipe->config.output_info[i].res.width, 8952 internal_pipe->config.output_info[i].res.height, 8953 internal_pipe->config.output_info[i].padded_width, 8954 internal_pipe->config.output_info[i].format, 8955 i); 8956 if (err) { 8957 IA_CSS_LEAVE_ERR_PRIVATE(err); 8958 kvfree(internal_pipe); 8959 internal_pipe = NULL; 8960 return err; 8961 } 8962 } 8963 8964 /* handle vf output info, when configured */ 8965 internal_pipe->enable_viewfinder[i] = 8966 (internal_pipe->config.vf_output_info[i].res.width != 0); 8967 if (internal_pipe->config.vf_output_info[i].res.width) { 8968 err = sh_css_pipe_configure_viewfinder( 8969 internal_pipe, 8970 internal_pipe->config.vf_output_info[i].res.width, 8971 internal_pipe->config.vf_output_info[i].res.height, 8972 internal_pipe->config.vf_output_info[i].padded_width, 8973 internal_pipe->config.vf_output_info[i].format, 8974 i); 8975 if (err) { 8976 IA_CSS_LEAVE_ERR_PRIVATE(err); 8977 kvfree(internal_pipe); 8978 internal_pipe = NULL; 8979 return err; 8980 } 8981 } 8982 } 8983 if (internal_pipe->config.acc_extension) 8984 { 8985 err = ia_css_pipe_load_extension(internal_pipe, 8986 internal_pipe->config.acc_extension); 8987 if (err) { 8988 IA_CSS_LEAVE_ERR_PRIVATE(err); 8989 kvfree(internal_pipe); 8990 return err; 8991 } 8992 } 8993 /* set all info to zeroes first */ 8994 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info)); 8995 8996 /* all went well, return the pipe */ 8997 *pipe = internal_pipe; 8998 IA_CSS_LEAVE_ERR_PRIVATE(0); 8999 return 0; 9000 } 9001 9002 int 9003 ia_css_pipe_get_info(const struct ia_css_pipe *pipe, 9004 struct ia_css_pipe_info *pipe_info) { 9005 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 9006 "ia_css_pipe_get_info()\n"); 9007 assert(pipe_info); 9008 if (!pipe_info) 9009 { 9010 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 9011 "ia_css_pipe_get_info: pipe_info cannot be NULL\n"); 9012 return -EINVAL; 9013 } 9014 if (!pipe || !pipe->stream) 9015 { 9016 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 9017 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n"); 9018 return -EINVAL; 9019 } 9020 /* we succeeded return the info */ 9021 *pipe_info = pipe->info; 9022 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n"); 9023 return 0; 9024 } 9025 9026 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info) 9027 { 9028 unsigned int i; 9029 9030 if (pipe_info) { 9031 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) { 9032 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable) 9033 return true; 9034 } 9035 } 9036 9037 return false; 9038 } 9039 9040 int 9041 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe, 9042 int pin_index, 9043 enum ia_css_frame_format new_format) { 9044 int err = 0; 9045 9046 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format); 9047 9048 if (!pipe) 9049 { 9050 IA_CSS_ERROR("pipe is not set"); 9051 err = -EINVAL; 9052 IA_CSS_LEAVE_ERR_PRIVATE(err); 9053 return err; 9054 } 9055 if (0 != pin_index && 1 != pin_index) 9056 { 9057 IA_CSS_ERROR("pin index is not valid"); 9058 err = -EINVAL; 9059 IA_CSS_LEAVE_ERR_PRIVATE(err); 9060 return err; 9061 } 9062 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) 9063 { 9064 IA_CSS_ERROR("new format is not valid"); 9065 err = -EINVAL; 9066 IA_CSS_LEAVE_ERR_PRIVATE(err); 9067 return err; 9068 } else 9069 { 9070 err = ia_css_pipe_check_format(pipe, new_format); 9071 if (!err) { 9072 if (pin_index == 0) { 9073 pipe->output_info[0].format = new_format; 9074 } else { 9075 pipe->vf_output_info[0].format = new_format; 9076 } 9077 } 9078 } 9079 IA_CSS_LEAVE_ERR_PRIVATE(err); 9080 return err; 9081 } 9082 9083 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9084 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */ 9085 static int 9086 ia_css_stream_configure_rx(struct ia_css_stream *stream) { 9087 struct ia_css_input_port *config; 9088 9089 assert(stream); 9090 9091 config = &stream->config.source.port; 9092 /* AM: this code is not reliable, especially for 2400 */ 9093 if (config->num_lanes == 1) 9094 stream->csi_rx_config.mode = MONO_1L_1L_0L; 9095 else if (config->num_lanes == 2) 9096 stream->csi_rx_config.mode = MONO_2L_1L_0L; 9097 else if (config->num_lanes == 3) 9098 stream->csi_rx_config.mode = MONO_3L_1L_0L; 9099 else if (config->num_lanes == 4) 9100 stream->csi_rx_config.mode = MONO_4L_1L_0L; 9101 else if (config->num_lanes != 0) 9102 return -EINVAL; 9103 9104 if (config->port > MIPI_PORT2_ID) 9105 return -EINVAL; 9106 stream->csi_rx_config.port = 9107 ia_css_isys_port_to_mipi_port(config->port); 9108 stream->csi_rx_config.timeout = config->timeout; 9109 stream->csi_rx_config.initcount = 0; 9110 stream->csi_rx_config.synccount = 0x28282828; 9111 stream->csi_rx_config.rxcount = config->rxcount; 9112 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE) 9113 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE; 9114 else 9115 { 9116 /* not implemented yet, requires extension of the rx_cfg_t 9117 * struct */ 9118 return -EINVAL; 9119 } 9120 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2); 9121 stream->reconfigure_css_rx = true; 9122 return 0; 9123 } 9124 #endif 9125 9126 static struct ia_css_pipe * 9127 find_pipe(struct ia_css_pipe *pipes[], 9128 unsigned int num_pipes, 9129 enum ia_css_pipe_mode mode, 9130 bool copy_pipe) { 9131 unsigned int i; 9132 9133 assert(pipes); 9134 for (i = 0; i < num_pipes; i++) { 9135 assert(pipes[i]); 9136 if (pipes[i]->config.mode != mode) 9137 continue; 9138 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY) 9139 continue; 9140 return pipes[i]; 9141 } 9142 return NULL; 9143 } 9144 9145 static int 9146 ia_css_acc_stream_create(struct ia_css_stream *stream) { 9147 int i; 9148 int err = 0; 9149 9150 assert(stream); 9151 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 9152 9153 if (!stream) 9154 { 9155 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 9156 return -EINVAL; 9157 } 9158 9159 for (i = 0; i < stream->num_pipes; i++) 9160 { 9161 struct ia_css_pipe *pipe = stream->pipes[i]; 9162 9163 assert(pipe); 9164 if (!pipe) { 9165 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 9166 return -EINVAL; 9167 } 9168 9169 pipe->stream = stream; 9170 } 9171 9172 /* Map SP threads before doing anything. */ 9173 err = map_sp_threads(stream, true); 9174 if (err) 9175 { 9176 IA_CSS_LEAVE_ERR_PRIVATE(err); 9177 return err; 9178 } 9179 9180 for (i = 0; i < stream->num_pipes; i++) 9181 { 9182 struct ia_css_pipe *pipe = stream->pipes[i]; 9183 9184 assert(pipe); 9185 ia_css_pipe_map_queue(pipe, true); 9186 } 9187 9188 err = create_host_pipeline_structure(stream); 9189 if (err) 9190 { 9191 IA_CSS_LEAVE_ERR_PRIVATE(err); 9192 return err; 9193 } 9194 9195 stream->started = false; 9196 9197 IA_CSS_LEAVE_ERR_PRIVATE(0); 9198 9199 return 0; 9200 } 9201 9202 static int 9203 metadata_info_init(const struct ia_css_metadata_config *mdc, 9204 struct ia_css_metadata_info *md) { 9205 /* Either both width and height should be set or neither */ 9206 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0)) 9207 return -EINVAL; 9208 9209 md->resolution = mdc->resolution; 9210 /* We round up the stride to a multiple of the width 9211 * of the port going to DDR, this is a HW requirements (DMA). */ 9212 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES); 9213 md->size = mdc->resolution.height * md->stride; 9214 return 0; 9215 } 9216 9217 /* ISP2401 */ 9218 static int check_pipe_resolutions(const struct ia_css_pipe *pipe) 9219 { 9220 int err = 0; 9221 9222 IA_CSS_ENTER_PRIVATE(""); 9223 9224 if (!pipe || !pipe->stream) { 9225 IA_CSS_ERROR("null arguments"); 9226 err = -EINVAL; 9227 goto EXIT; 9228 } 9229 9230 if (ia_css_util_check_res(pipe->config.input_effective_res.width, 9231 pipe->config.input_effective_res.height) != 0) { 9232 IA_CSS_ERROR("effective resolution not supported"); 9233 err = -EINVAL; 9234 goto EXIT; 9235 } 9236 if (!ia_css_util_resolution_is_zero( 9237 pipe->stream->config.input_config.input_res)) { 9238 if (!ia_css_util_res_leq(pipe->config.input_effective_res, 9239 pipe->stream->config.input_config.input_res)) { 9240 IA_CSS_ERROR("effective resolution is larger than input resolution"); 9241 err = -EINVAL; 9242 goto EXIT; 9243 } 9244 } 9245 if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) { 9246 IA_CSS_ERROR("output resolution must be even"); 9247 err = -EINVAL; 9248 goto EXIT; 9249 } 9250 if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) { 9251 IA_CSS_ERROR("VF resolution must be even"); 9252 err = -EINVAL; 9253 goto EXIT; 9254 } 9255 EXIT: 9256 IA_CSS_LEAVE_ERR_PRIVATE(err); 9257 return err; 9258 } 9259 9260 int 9261 ia_css_stream_create(const struct ia_css_stream_config *stream_config, 9262 int num_pipes, 9263 struct ia_css_pipe *pipes[], 9264 struct ia_css_stream **stream) { 9265 struct ia_css_pipe *curr_pipe; 9266 struct ia_css_stream *curr_stream = NULL; 9267 bool spcopyonly; 9268 bool sensor_binning_changed; 9269 int i, j; 9270 int err = -EINVAL; 9271 struct ia_css_metadata_info md_info; 9272 struct ia_css_resolution effective_res; 9273 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9274 bool aspect_ratio_crop_enabled = false; 9275 #endif 9276 9277 IA_CSS_ENTER("num_pipes=%d", num_pipes); 9278 ia_css_debug_dump_stream_config(stream_config, num_pipes); 9279 9280 /* some checks */ 9281 if (num_pipes == 0 || 9282 !stream || 9283 !pipes) 9284 { 9285 err = -EINVAL; 9286 IA_CSS_LEAVE_ERR(err); 9287 return err; 9288 } 9289 9290 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9291 /* We don't support metadata for JPEG stream, since they both use str2mem */ 9292 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && 9293 stream_config->metadata_config.resolution.height > 0) 9294 { 9295 err = -EINVAL; 9296 IA_CSS_LEAVE_ERR(err); 9297 return err; 9298 } 9299 #endif 9300 9301 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9302 if (stream_config->online && stream_config->pack_raw_pixels) 9303 { 9304 IA_CSS_LOG("online and pack raw is invalid on input system 2401"); 9305 err = -EINVAL; 9306 IA_CSS_LEAVE_ERR(err); 9307 return err; 9308 } 9309 #endif 9310 9311 ia_css_debug_pipe_graph_dump_stream_config(stream_config); 9312 9313 /* check if mipi size specified */ 9314 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 9315 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9316 if (!stream_config->online) 9317 #endif 9318 { 9319 unsigned int port = (unsigned int)stream_config->source.port.port; 9320 9321 if (port >= N_MIPI_PORT_ID) { 9322 err = -EINVAL; 9323 IA_CSS_LEAVE_ERR(err); 9324 return err; 9325 } 9326 9327 if (my_css.size_mem_words != 0) { 9328 my_css.mipi_frame_size[port] = my_css.size_mem_words; 9329 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) { 9330 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words; 9331 } else { 9332 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 9333 "ia_css_stream_create() exit: error, need to set mipi frame size.\n"); 9334 assert(stream_config->mipi_buffer_config.size_mem_words != 0); 9335 err = -EINVAL; 9336 IA_CSS_LEAVE_ERR(err); 9337 return err; 9338 } 9339 9340 if (my_css.size_mem_words != 0) { 9341 my_css.num_mipi_frames[port] = 9342 2; /* Temp change: Default for backwards compatibility. */ 9343 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) { 9344 my_css.num_mipi_frames[port] = 9345 stream_config->mipi_buffer_config.nof_mipi_buffers; 9346 } else { 9347 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 9348 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n"); 9349 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0); 9350 err = -EINVAL; 9351 IA_CSS_LEAVE_ERR(err); 9352 return err; 9353 } 9354 } 9355 9356 /* Currently we only supported metadata up to a certain size. */ 9357 err = metadata_info_init(&stream_config->metadata_config, &md_info); 9358 if (err) 9359 { 9360 IA_CSS_LEAVE_ERR(err); 9361 return err; 9362 } 9363 9364 /* allocate the stream instance */ 9365 curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL); 9366 if (!curr_stream) 9367 { 9368 err = -ENOMEM; 9369 IA_CSS_LEAVE_ERR(err); 9370 return err; 9371 } 9372 /* default all to 0 */ 9373 curr_stream->info.metadata_info = md_info; 9374 9375 /* allocate pipes */ 9376 curr_stream->num_pipes = num_pipes; 9377 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL); 9378 if (!curr_stream->pipes) 9379 { 9380 curr_stream->num_pipes = 0; 9381 kfree(curr_stream); 9382 curr_stream = NULL; 9383 err = -ENOMEM; 9384 IA_CSS_LEAVE_ERR(err); 9385 return err; 9386 } 9387 /* store pipes */ 9388 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY); 9389 for (i = 0; i < num_pipes; i++) 9390 curr_stream->pipes[i] = pipes[i]; 9391 curr_stream->last_pipe = curr_stream->pipes[0]; 9392 /* take over stream config */ 9393 curr_stream->config = *stream_config; 9394 9395 #if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE) 9396 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR && 9397 stream_config->online) 9398 curr_stream->config.online = false; 9399 #endif 9400 9401 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9402 if (curr_stream->config.online) 9403 { 9404 curr_stream->config.source.port.num_lanes = 9405 stream_config->source.port.num_lanes; 9406 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; 9407 } 9408 #endif 9409 /* in case driver doesn't configure init number of raw buffers, configure it here */ 9410 if (curr_stream->config.target_num_cont_raw_buf == 0) 9411 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES; 9412 if (curr_stream->config.init_num_cont_raw_buf == 0) 9413 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf; 9414 9415 /* Enable locking & unlocking of buffers in RAW buffer pool */ 9416 if (curr_stream->config.ia_css_enable_raw_buffer_locking) 9417 sh_css_sp_configure_enable_raw_pool_locking( 9418 curr_stream->config.lock_all); 9419 9420 /* copy mode specific stuff */ 9421 switch (curr_stream->config.mode) 9422 { 9423 case IA_CSS_INPUT_MODE_SENSOR: 9424 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: 9425 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9426 ia_css_stream_configure_rx(curr_stream); 9427 #endif 9428 break; 9429 case IA_CSS_INPUT_MODE_TPG: 9430 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9431 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d", 9432 curr_stream->config.source.tpg.x_mask, 9433 curr_stream->config.source.tpg.y_mask, 9434 curr_stream->config.source.tpg.x_delta, 9435 curr_stream->config.source.tpg.y_delta, 9436 curr_stream->config.source.tpg.xy_mask); 9437 9438 sh_css_sp_configure_tpg( 9439 curr_stream->config.source.tpg.x_mask, 9440 curr_stream->config.source.tpg.y_mask, 9441 curr_stream->config.source.tpg.x_delta, 9442 curr_stream->config.source.tpg.y_delta, 9443 curr_stream->config.source.tpg.xy_mask); 9444 #endif 9445 break; 9446 case IA_CSS_INPUT_MODE_PRBS: 9447 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9448 IA_CSS_LOG("mode prbs"); 9449 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed); 9450 #endif 9451 break; 9452 case IA_CSS_INPUT_MODE_MEMORY: 9453 IA_CSS_LOG("mode memory"); 9454 curr_stream->reconfigure_css_rx = false; 9455 break; 9456 default: 9457 IA_CSS_LOG("mode sensor/default"); 9458 } 9459 9460 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9461 err = aspect_ratio_crop_init(curr_stream, 9462 pipes, 9463 &aspect_ratio_crop_enabled); 9464 if (err) 9465 { 9466 IA_CSS_LEAVE_ERR(err); 9467 goto ERR; 9468 } 9469 #endif 9470 for (i = 0; i < num_pipes; i++) 9471 { 9472 struct ia_css_resolution effective_res; 9473 9474 curr_pipe = pipes[i]; 9475 /* set current stream */ 9476 curr_pipe->stream = curr_stream; 9477 /* take over effective info */ 9478 9479 effective_res = curr_pipe->config.input_effective_res; 9480 if (effective_res.height == 0 || effective_res.width == 0) { 9481 effective_res = curr_pipe->stream->config.input_config.effective_res; 9482 9483 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 9484 /* The aspect ratio cropping is currently only 9485 * supported on the new input system. */ 9486 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) { 9487 struct ia_css_resolution crop_res; 9488 9489 err = aspect_ratio_crop(curr_pipe, &crop_res); 9490 if (!err) { 9491 effective_res = crop_res; 9492 } else { 9493 /* in case of error fallback to default 9494 * effective resolution from driver. */ 9495 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err); 9496 } 9497 } 9498 #endif 9499 curr_pipe->config.input_effective_res = effective_res; 9500 } 9501 IA_CSS_LOG("effective_res=%dx%d", 9502 effective_res.width, 9503 effective_res.height); 9504 } 9505 9506 if (IS_ISP2401) { 9507 for (i = 0; i < num_pipes; i++) { 9508 if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC && 9509 pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) { 9510 err = check_pipe_resolutions(pipes[i]); 9511 if (err) { 9512 goto ERR; 9513 } 9514 } 9515 } 9516 } 9517 9518 err = ia_css_stream_isp_parameters_init(curr_stream); 9519 if (err) 9520 goto ERR; 9521 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs); 9522 9523 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) 9524 { 9525 *stream = curr_stream; 9526 err = ia_css_acc_stream_create(curr_stream); 9527 goto ERR; 9528 } 9529 /* sensor binning */ 9530 if (!spcopyonly) 9531 { 9532 sensor_binning_changed = 9533 sh_css_params_set_binning_factor(curr_stream, 9534 curr_stream->config.sensor_binning_factor); 9535 } else 9536 { 9537 sensor_binning_changed = false; 9538 } 9539 9540 IA_CSS_LOG("sensor_binning=%d, changed=%d", 9541 curr_stream->config.sensor_binning_factor, sensor_binning_changed); 9542 /* loop over pipes */ 9543 IA_CSS_LOG("num_pipes=%d", num_pipes); 9544 curr_stream->cont_capt = false; 9545 /* Temporary hack: we give the preview pipe a reference to the capture 9546 * pipe in continuous capture mode. */ 9547 if (curr_stream->config.continuous) 9548 { 9549 /* Search for the preview pipe and create the copy pipe */ 9550 struct ia_css_pipe *preview_pipe; 9551 struct ia_css_pipe *video_pipe; 9552 struct ia_css_pipe *acc_pipe; 9553 struct ia_css_pipe *capture_pipe = NULL; 9554 struct ia_css_pipe *copy_pipe = NULL; 9555 9556 if (num_pipes >= 2) { 9557 curr_stream->cont_capt = true; 9558 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder; 9559 9560 if (!IS_ISP2401) 9561 curr_stream->stop_copy_preview = my_css.stop_copy_preview; 9562 } 9563 9564 /* Create copy pipe here, since it may not be exposed to the driver */ 9565 preview_pipe = find_pipe(pipes, num_pipes, 9566 IA_CSS_PIPE_MODE_PREVIEW, false); 9567 video_pipe = find_pipe(pipes, num_pipes, 9568 IA_CSS_PIPE_MODE_VIDEO, false); 9569 acc_pipe = find_pipe(pipes, num_pipes, 9570 IA_CSS_PIPE_MODE_ACC, false); 9571 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true) 9572 curr_stream->cont_capt = 9573 false; /* preview + QoS case will not need cont_capt switch */ 9574 if (curr_stream->cont_capt == true) { 9575 capture_pipe = find_pipe(pipes, num_pipes, 9576 IA_CSS_PIPE_MODE_CAPTURE, false); 9577 if (!capture_pipe) { 9578 err = -EINVAL; 9579 goto ERR; 9580 } 9581 } 9582 /* We do not support preview and video pipe at the same time */ 9583 if (preview_pipe && video_pipe) { 9584 err = -EINVAL; 9585 goto ERR; 9586 } 9587 9588 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) { 9589 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); 9590 if (err) 9591 goto ERR; 9592 ia_css_pipe_config_defaults(©_pipe->config); 9593 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe; 9594 copy_pipe->stream = curr_stream; 9595 } 9596 if (preview_pipe && (curr_stream->cont_capt == true)) { 9597 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe; 9598 } 9599 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) { 9600 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); 9601 if (err) 9602 goto ERR; 9603 ia_css_pipe_config_defaults(©_pipe->config); 9604 video_pipe->pipe_settings.video.copy_pipe = copy_pipe; 9605 copy_pipe->stream = curr_stream; 9606 } 9607 if (video_pipe && (curr_stream->cont_capt == true)) { 9608 video_pipe->pipe_settings.video.capture_pipe = capture_pipe; 9609 } 9610 if (preview_pipe && acc_pipe) { 9611 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe; 9612 } 9613 } 9614 for (i = 0; i < num_pipes; i++) 9615 { 9616 curr_pipe = pipes[i]; 9617 /* set current stream */ 9618 curr_pipe->stream = curr_stream; 9619 9620 if (!IS_ISP2401) { 9621 /* take over effective info */ 9622 9623 effective_res = curr_pipe->config.input_effective_res; 9624 err = ia_css_util_check_res( 9625 effective_res.width, 9626 effective_res.height); 9627 if (err) 9628 goto ERR; 9629 } 9630 /* sensor binning per pipe */ 9631 if (sensor_binning_changed) 9632 sh_css_pipe_free_shading_table(curr_pipe); 9633 } 9634 9635 /* now pipes have been configured, info should be available */ 9636 for (i = 0; i < num_pipes; i++) 9637 { 9638 struct ia_css_pipe_info *pipe_info = NULL; 9639 9640 curr_pipe = pipes[i]; 9641 9642 err = sh_css_pipe_load_binaries(curr_pipe); 9643 if (err) 9644 goto ERR; 9645 9646 /* handle each pipe */ 9647 pipe_info = &curr_pipe->info; 9648 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { 9649 err = sh_css_pipe_get_output_frame_info(curr_pipe, 9650 &pipe_info->output_info[j], j); 9651 if (err) 9652 goto ERR; 9653 } 9654 9655 if (IS_ISP2401) 9656 pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res; 9657 9658 if (!spcopyonly) { 9659 if (!IS_ISP2401) 9660 err = sh_css_pipe_get_shading_info(curr_pipe, 9661 &pipe_info->shading_info, NULL); 9662 else 9663 err = sh_css_pipe_get_shading_info(curr_pipe, 9664 &pipe_info->shading_info, &curr_pipe->config); 9665 9666 if (err) 9667 goto ERR; 9668 err = sh_css_pipe_get_grid_info(curr_pipe, 9669 &pipe_info->grid_info); 9670 if (err) 9671 goto ERR; 9672 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { 9673 sh_css_pipe_get_viewfinder_frame_info(curr_pipe, 9674 &pipe_info->vf_output_info[j], j); 9675 if (err) 9676 goto ERR; 9677 } 9678 } 9679 9680 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe; 9681 } 9682 9683 curr_stream->started = false; 9684 9685 /* Map SP threads before doing anything. */ 9686 err = map_sp_threads(curr_stream, true); 9687 if (err) 9688 { 9689 IA_CSS_LOG("map_sp_threads: return_err=%d", err); 9690 goto ERR; 9691 } 9692 9693 for (i = 0; i < num_pipes; i++) 9694 { 9695 curr_pipe = pipes[i]; 9696 ia_css_pipe_map_queue(curr_pipe, true); 9697 } 9698 9699 /* Create host side pipeline objects without stages */ 9700 err = create_host_pipeline_structure(curr_stream); 9701 if (err) 9702 { 9703 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err); 9704 goto ERR; 9705 } 9706 9707 /* assign curr_stream */ 9708 *stream = curr_stream; 9709 9710 ERR: 9711 if (!err) { 9712 /* working mode: enter into the seed list */ 9713 if (my_css_save.mode == sh_css_mode_working) { 9714 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { 9715 if (!my_css_save.stream_seeds[i].stream) { 9716 IA_CSS_LOG("entered stream into loc=%d", i); 9717 my_css_save.stream_seeds[i].orig_stream = stream; 9718 my_css_save.stream_seeds[i].stream = curr_stream; 9719 my_css_save.stream_seeds[i].num_pipes = num_pipes; 9720 my_css_save.stream_seeds[i].stream_config = *stream_config; 9721 for (j = 0; j < num_pipes; j++) { 9722 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config; 9723 my_css_save.stream_seeds[i].pipes[j] = pipes[j]; 9724 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j]; 9725 } 9726 break; 9727 } 9728 } 9729 } else { 9730 ia_css_stream_destroy(curr_stream); 9731 } 9732 } else { 9733 ia_css_stream_destroy(curr_stream); 9734 } 9735 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode); 9736 return err; 9737 } 9738 9739 int 9740 ia_css_stream_destroy(struct ia_css_stream *stream) { 9741 int i; 9742 int err = 0; 9743 9744 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 9745 if (!stream) 9746 { 9747 err = -EINVAL; 9748 IA_CSS_LEAVE_ERR_PRIVATE(err); 9749 return err; 9750 } 9751 9752 ia_css_stream_isp_parameters_uninit(stream); 9753 9754 if ((stream->last_pipe) && 9755 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) 9756 { 9757 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 9758 bool free_mpi; 9759 9760 for (i = 0; i < stream->num_pipes; i++) { 9761 struct ia_css_pipe *entry = stream->pipes[i]; 9762 unsigned int sp_thread_id; 9763 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal; 9764 9765 assert(entry); 9766 if (entry) { 9767 /* get the SP thread id */ 9768 if (ia_css_pipeline_get_sp_thread_id( 9769 ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true) 9770 return -EINVAL; 9771 /* get the target input terminal */ 9772 sp_pipeline_input_terminal = 9773 &sh_css_sp_group.pipe_io[sp_thread_id].input; 9774 9775 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) { 9776 ia_css_isys_stream_h isys_stream = 9777 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]; 9778 if (stream->config.isys_config[i].valid && isys_stream->valid) 9779 ia_css_isys_stream_destroy(isys_stream); 9780 } 9781 } 9782 } 9783 free_mpi = stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; 9784 if (IS_ISP2401) { 9785 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_TPG; 9786 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_PRBS; 9787 } 9788 9789 if (free_mpi) { 9790 for (i = 0; i < stream->num_pipes; i++) { 9791 struct ia_css_pipe *entry = stream->pipes[i]; 9792 /* free any mipi frames that are remaining: 9793 * some test stream create-destroy cycles do not generate output frames 9794 * and the mipi buffer is not freed in the deque function 9795 */ 9796 if (entry) 9797 free_mipi_frames(entry); 9798 } 9799 } 9800 stream_unregister_with_csi_rx(stream); 9801 #endif 9802 9803 for (i = 0; i < stream->num_pipes; i++) { 9804 struct ia_css_pipe *curr_pipe = stream->pipes[i]; 9805 9806 assert(curr_pipe); 9807 ia_css_pipe_map_queue(curr_pipe, false); 9808 } 9809 9810 err = map_sp_threads(stream, false); 9811 if (err) { 9812 IA_CSS_LEAVE_ERR_PRIVATE(err); 9813 return err; 9814 } 9815 } 9816 9817 /* remove references from pipes to stream */ 9818 for (i = 0; i < stream->num_pipes; i++) 9819 { 9820 struct ia_css_pipe *entry = stream->pipes[i]; 9821 9822 assert(entry); 9823 if (entry) { 9824 /* clear reference to stream */ 9825 entry->stream = NULL; 9826 /* check internal copy pipe */ 9827 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW && 9828 entry->pipe_settings.preview.copy_pipe) { 9829 IA_CSS_LOG("clearing stream on internal preview copy pipe"); 9830 entry->pipe_settings.preview.copy_pipe->stream = NULL; 9831 } 9832 if (entry->mode == IA_CSS_PIPE_ID_VIDEO && 9833 entry->pipe_settings.video.copy_pipe) { 9834 IA_CSS_LOG("clearing stream on internal video copy pipe"); 9835 entry->pipe_settings.video.copy_pipe->stream = NULL; 9836 } 9837 err = sh_css_pipe_unload_binaries(entry); 9838 } 9839 } 9840 /* free associated memory of stream struct */ 9841 kfree(stream->pipes); 9842 stream->pipes = NULL; 9843 stream->num_pipes = 0; 9844 9845 /* working mode: take out of the seed list */ 9846 if (my_css_save.mode == sh_css_mode_working) { 9847 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { 9848 if (my_css_save.stream_seeds[i].stream == stream) 9849 { 9850 IA_CSS_LOG("took out stream %d", i); 9851 my_css_save.stream_seeds[i].stream = NULL; 9852 break; 9853 } 9854 } 9855 } 9856 9857 kfree(stream); 9858 IA_CSS_LEAVE_ERR(err); 9859 9860 return err; 9861 } 9862 9863 int 9864 ia_css_stream_get_info(const struct ia_css_stream *stream, 9865 struct ia_css_stream_info *stream_info) { 9866 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n"); 9867 assert(stream); 9868 assert(stream_info); 9869 9870 *stream_info = stream->info; 9871 return 0; 9872 } 9873 9874 /* 9875 * Rebuild a stream, including allocating structs, setting configuration and 9876 * building the required pipes. 9877 * The data is taken from the css_save struct updated upon stream creation. 9878 * The stream handle is used to identify the correct entry in the css_save struct 9879 */ 9880 int 9881 ia_css_stream_load(struct ia_css_stream *stream) { 9882 if (!IS_ISP2401) { 9883 int i; 9884 int err; 9885 9886 assert(stream); 9887 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n"); 9888 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) 9889 { 9890 if (my_css_save.stream_seeds[i].stream == stream) { 9891 int j; 9892 9893 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) { 9894 if ((err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j], 9895 &my_css_save.stream_seeds[i].pipes[j])) != 0) { 9896 if (j) { 9897 int k; 9898 9899 for (k = 0; k < j; k++) 9900 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]); 9901 } 9902 return err; 9903 } 9904 } 9905 err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config, 9906 my_css_save.stream_seeds[i].num_pipes, 9907 my_css_save.stream_seeds[i].pipes, 9908 &my_css_save.stream_seeds[i].stream); 9909 if (err) { 9910 ia_css_stream_destroy(stream); 9911 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) 9912 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]); 9913 return err; 9914 } 9915 break; 9916 } 9917 } 9918 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n"); 9919 return 0; 9920 } else { 9921 /* TODO remove function - DEPRECATED */ 9922 (void)stream; 9923 return -ENOTSUPP; 9924 } 9925 } 9926 9927 int 9928 ia_css_stream_start(struct ia_css_stream *stream) { 9929 int err = 0; 9930 9931 IA_CSS_ENTER("stream = %p", stream); 9932 if ((!stream) || (!stream->last_pipe)) 9933 { 9934 IA_CSS_LEAVE_ERR(-EINVAL); 9935 return -EINVAL; 9936 } 9937 IA_CSS_LOG("starting %d", stream->last_pipe->mode); 9938 9939 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf); 9940 9941 /* Create host side pipeline. */ 9942 err = create_host_pipeline(stream); 9943 if (err) 9944 { 9945 IA_CSS_LEAVE_ERR(err); 9946 return err; 9947 } 9948 9949 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 9950 if ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) || 9951 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)) 9952 stream_register_with_csi_rx(stream); 9953 #endif 9954 9955 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9956 /* Initialize mipi size checks */ 9957 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 9958 { 9959 unsigned int idx; 9960 unsigned int port = (unsigned int)(stream->config.source.port.port); 9961 9962 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) { 9963 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 9964 sh_css_get_mipi_sizes_for_check(port, idx); 9965 } 9966 } 9967 #endif 9968 9969 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) 9970 { 9971 err = sh_css_config_input_network(stream); 9972 if (err) 9973 return err; 9974 } 9975 9976 err = sh_css_pipe_start(stream); 9977 IA_CSS_LEAVE_ERR(err); 9978 return err; 9979 } 9980 9981 int 9982 ia_css_stream_stop(struct ia_css_stream *stream) { 9983 int err = 0; 9984 9985 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n"); 9986 assert(stream); 9987 assert(stream->last_pipe); 9988 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n", 9989 stream->last_pipe->mode); 9990 9991 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9992 /* De-initialize mipi size checks */ 9993 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 9994 { 9995 unsigned int idx; 9996 unsigned int port = (unsigned int)(stream->config.source.port.port); 9997 9998 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) { 9999 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0; 10000 } 10001 } 10002 #endif 10003 10004 if (!IS_ISP2401) { 10005 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline); 10006 } else { 10007 err = sh_css_pipes_stop(stream); 10008 } 10009 10010 if (err) 10011 return err; 10012 10013 /* Ideally, unmapping should happen after pipeline_stop, but current 10014 * semantics do not allow that. */ 10015 /* err = map_sp_threads(stream, false); */ 10016 10017 return err; 10018 } 10019 10020 bool 10021 ia_css_stream_has_stopped(struct ia_css_stream *stream) { 10022 bool stopped; 10023 10024 assert(stream); 10025 10026 if (!IS_ISP2401) { 10027 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline); 10028 } else { 10029 stopped = sh_css_pipes_have_stopped(stream); 10030 } 10031 10032 return stopped; 10033 } 10034 10035 /* ISP2400 */ 10036 /* 10037 * Destroy the stream and all the pipes related to it. 10038 * The stream handle is used to identify the correct entry in the css_save struct 10039 */ 10040 int 10041 ia_css_stream_unload(struct ia_css_stream *stream) { 10042 int i; 10043 10044 assert(stream); 10045 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n"); 10046 /* some checks */ 10047 assert(stream); 10048 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) 10049 if (my_css_save.stream_seeds[i].stream == stream) 10050 { 10051 int j; 10052 10053 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 10054 "ia_css_stream_unload(): unloading %d (%p)\n", i, 10055 my_css_save.stream_seeds[i].stream); 10056 ia_css_stream_destroy(stream); 10057 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) 10058 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]); 10059 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 10060 "ia_css_stream_unload(): after unloading %d (%p)\n", i, 10061 my_css_save.stream_seeds[i].stream); 10062 break; 10063 } 10064 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n"); 10065 return 0; 10066 } 10067 10068 int 10069 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, 10070 enum ia_css_pipe_id *pipe_id) { 10071 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n"); 10072 if (pipe) 10073 *pipe_id = pipe->mode; 10074 else 10075 *pipe_id = IA_CSS_PIPE_ID_COPY; 10076 10077 return 0; 10078 } 10079 10080 enum atomisp_input_format 10081 ia_css_stream_get_format(const struct ia_css_stream *stream) { 10082 return stream->config.input_config.format; 10083 } 10084 10085 bool 10086 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) { 10087 return (stream->config.pixels_per_clock == 2); 10088 } 10089 10090 struct ia_css_binary * 10091 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream 10092 *stream) { 10093 struct ia_css_pipe *pipe; 10094 10095 assert(stream); 10096 10097 pipe = stream->pipes[0]; 10098 10099 if (stream->num_pipes == 2) { 10100 assert(stream->pipes[1]); 10101 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO || 10102 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 10103 pipe = stream->pipes[1]; 10104 } 10105 10106 return ia_css_pipe_get_shading_correction_binary(pipe); 10107 } 10108 10109 struct ia_css_binary * 10110 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) { 10111 int i; 10112 struct ia_css_pipe *video_pipe = NULL; 10113 10114 /* First we find the video pipe */ 10115 for (i = 0; i < stream->num_pipes; i++) { 10116 struct ia_css_pipe *pipe = stream->pipes[i]; 10117 10118 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) { 10119 video_pipe = pipe; 10120 break; 10121 } 10122 } 10123 if (video_pipe) 10124 return &video_pipe->pipe_settings.video.video_binary; 10125 return NULL; 10126 } 10127 10128 struct ia_css_binary * 10129 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) { 10130 struct ia_css_pipe *pipe; 10131 struct ia_css_binary *s3a_binary = NULL; 10132 10133 assert(stream); 10134 10135 pipe = stream->pipes[0]; 10136 10137 if (stream->num_pipes == 2) { 10138 assert(stream->pipes[1]); 10139 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO || 10140 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 10141 pipe = stream->pipes[1]; 10142 } 10143 10144 s3a_binary = ia_css_pipe_get_s3a_binary(pipe); 10145 10146 return s3a_binary; 10147 } 10148 10149 int 10150 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, 10151 unsigned int output_padded_width) { 10152 struct ia_css_pipe *pipe; 10153 10154 assert(stream); 10155 10156 pipe = stream->last_pipe; 10157 10158 assert(pipe); 10159 10160 /* set the config also just in case (redundant info? why do we save config in pipe?) */ 10161 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width; 10162 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width; 10163 10164 return 0; 10165 } 10166 10167 static struct ia_css_binary * 10168 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) { 10169 struct ia_css_binary *binary = NULL; 10170 10171 assert(pipe); 10172 10173 switch (pipe->config.mode) { 10174 case IA_CSS_PIPE_MODE_PREVIEW: 10175 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary; 10176 break; 10177 case IA_CSS_PIPE_MODE_VIDEO: 10178 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 10179 break; 10180 case IA_CSS_PIPE_MODE_CAPTURE: 10181 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 10182 unsigned int i; 10183 10184 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 10185 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) { 10186 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i]; 10187 break; 10188 } 10189 } 10190 } else if (pipe->config.default_capture_config.mode == 10191 IA_CSS_CAPTURE_MODE_BAYER) 10192 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 10193 else if (pipe->config.default_capture_config.mode == 10194 IA_CSS_CAPTURE_MODE_ADVANCED || 10195 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { 10196 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) 10197 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 10198 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2) 10199 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary; 10200 } 10201 break; 10202 default: 10203 break; 10204 } 10205 10206 if (binary && binary->info->sp.enable.sc) 10207 return binary; 10208 10209 return NULL; 10210 } 10211 10212 static struct ia_css_binary * 10213 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) { 10214 struct ia_css_binary *binary = NULL; 10215 10216 assert(pipe); 10217 10218 switch (pipe->config.mode) { 10219 case IA_CSS_PIPE_MODE_PREVIEW: 10220 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary; 10221 break; 10222 case IA_CSS_PIPE_MODE_VIDEO: 10223 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 10224 break; 10225 case IA_CSS_PIPE_MODE_CAPTURE: 10226 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 10227 unsigned int i; 10228 10229 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 10230 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) { 10231 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i]; 10232 break; 10233 } 10234 } 10235 } else if (pipe->config.default_capture_config.mode == 10236 IA_CSS_CAPTURE_MODE_BAYER) 10237 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 10238 else if (pipe->config.default_capture_config.mode == 10239 IA_CSS_CAPTURE_MODE_ADVANCED || 10240 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { 10241 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) 10242 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 10243 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2) 10244 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary; 10245 else 10246 assert(0); 10247 } 10248 break; 10249 default: 10250 break; 10251 } 10252 10253 if (binary && !binary->info->sp.enable.s3a) 10254 binary = NULL; 10255 10256 return binary; 10257 } 10258 10259 static struct ia_css_binary * 10260 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) { 10261 struct ia_css_binary *binary = NULL; 10262 10263 assert(pipe); 10264 10265 switch (pipe->config.mode) { 10266 case IA_CSS_PIPE_MODE_VIDEO: 10267 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 10268 break; 10269 default: 10270 break; 10271 } 10272 10273 if (binary && !binary->info->sp.enable.dis) 10274 binary = NULL; 10275 10276 return binary; 10277 } 10278 10279 struct ia_css_pipeline * 10280 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) { 10281 assert(pipe); 10282 10283 return (struct ia_css_pipeline *)&pipe->pipeline; 10284 } 10285 10286 unsigned int 10287 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) { 10288 assert(pipe); 10289 10290 /* KW was not sure this function was not returning a value 10291 that was out of range; so added an assert, and, for the 10292 case when asserts are not enabled, clip to the largest 10293 value; pipe_num is unsigned so the value cannot be too small 10294 */ 10295 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX); 10296 10297 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX) 10298 return (IA_CSS_PIPELINE_NUM_MAX - 1); 10299 10300 return pipe->pipe_num; 10301 } 10302 10303 unsigned int 10304 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) { 10305 assert(pipe); 10306 10307 return (unsigned int)pipe->config.isp_pipe_version; 10308 } 10309 10310 #define SP_START_TIMEOUT_US 30000000 10311 10312 int 10313 ia_css_start_sp(void) { 10314 unsigned long timeout; 10315 int err = 0; 10316 10317 IA_CSS_ENTER(""); 10318 sh_css_sp_start_isp(); 10319 10320 /* waiting for the SP is completely started */ 10321 timeout = SP_START_TIMEOUT_US; 10322 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) 10323 { 10324 timeout--; 10325 udelay(1); 10326 } 10327 if (timeout == 0) 10328 { 10329 IA_CSS_ERROR("timeout during SP initialization"); 10330 return -EINVAL; 10331 } 10332 10333 /* Workaround, in order to run two streams in parallel. See TASK 4271*/ 10334 /* TODO: Fix this. */ 10335 10336 sh_css_init_host_sp_control_vars(); 10337 10338 /* buffers should be initialized only when sp is started */ 10339 /* AM: At the moment it will be done only when there is no stream active. */ 10340 10341 sh_css_setup_queues(); 10342 ia_css_bufq_dump_queue_info(); 10343 10344 IA_CSS_LEAVE_ERR(err); 10345 return err; 10346 } 10347 10348 /* 10349 * Time to wait SP for termincate. Only condition when this can happen 10350 * is a fatal hw failure, but we must be able to detect this and emit 10351 * a proper error trace. 10352 */ 10353 #define SP_SHUTDOWN_TIMEOUT_US 200000 10354 10355 int 10356 ia_css_stop_sp(void) { 10357 unsigned long timeout; 10358 int err = 0; 10359 10360 IA_CSS_ENTER("void"); 10361 10362 if (!sh_css_sp_is_running()) 10363 { 10364 err = -EINVAL; 10365 IA_CSS_LEAVE("SP already stopped : return_err=%d", err); 10366 10367 /* Return an error - stop SP should not have been called by driver */ 10368 return err; 10369 } 10370 10371 /* For now, stop whole SP */ 10372 if (!IS_ISP2401) { 10373 sh_css_write_host2sp_command(host2sp_cmd_terminate); 10374 } else { 10375 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) 10376 { 10377 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); 10378 ia_css_debug_dump_sp_sw_debug_info(); 10379 ia_css_debug_dump_debug_info(NULL); 10380 } 10381 } 10382 10383 sh_css_sp_set_sp_running(false); 10384 10385 timeout = SP_SHUTDOWN_TIMEOUT_US; 10386 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) 10387 { 10388 timeout--; 10389 udelay(1); 10390 } 10391 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED)) 10392 IA_CSS_WARNING("SP has not terminated (SW)"); 10393 10394 if (timeout == 0) 10395 { 10396 IA_CSS_WARNING("SP is not idle"); 10397 ia_css_debug_dump_sp_sw_debug_info(); 10398 } 10399 timeout = SP_SHUTDOWN_TIMEOUT_US; 10400 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) 10401 { 10402 timeout--; 10403 udelay(1); 10404 } 10405 if (timeout == 0) 10406 { 10407 IA_CSS_WARNING("ISP is not idle"); 10408 ia_css_debug_dump_sp_sw_debug_info(); 10409 } 10410 10411 sh_css_hmm_buffer_record_uninit(); 10412 10413 /* clear pending param sets from refcount */ 10414 sh_css_param_clear_param_sets(); 10415 10416 IA_CSS_LEAVE_ERR(err); 10417 return err; 10418 } 10419 10420 int 10421 ia_css_update_continuous_frames(struct ia_css_stream *stream) { 10422 struct ia_css_pipe *pipe; 10423 unsigned int i; 10424 10425 ia_css_debug_dtrace( 10426 IA_CSS_DEBUG_TRACE, 10427 "sh_css_update_continuous_frames() enter:\n"); 10428 10429 if (!stream) 10430 { 10431 ia_css_debug_dtrace( 10432 IA_CSS_DEBUG_TRACE, 10433 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n"); 10434 return -EINVAL; 10435 } 10436 10437 pipe = stream->continuous_pipe; 10438 10439 for (i = stream->config.init_num_cont_raw_buf; 10440 i < stream->config.target_num_cont_raw_buf; i++) 10441 { 10442 sh_css_update_host2sp_offline_frame(i, 10443 pipe->continuous_frames[i], pipe->cont_md_buffers[i]); 10444 } 10445 sh_css_update_host2sp_cont_num_raw_frames 10446 (stream->config.target_num_cont_raw_buf, true); 10447 ia_css_debug_dtrace( 10448 IA_CSS_DEBUG_TRACE, 10449 "sh_css_update_continuous_frames() leave: return_void\n"); 10450 10451 return 0; 10452 } 10453 10454 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) 10455 { 10456 unsigned int thread_id; 10457 enum ia_css_pipe_id pipe_id; 10458 unsigned int pipe_num; 10459 bool need_input_queue; 10460 10461 IA_CSS_ENTER(""); 10462 assert(pipe); 10463 10464 pipe_id = pipe->mode; 10465 pipe_num = pipe->pipe_num; 10466 10467 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 10468 10469 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 10470 need_input_queue = true; 10471 #else 10472 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 10473 #endif 10474 10475 /* map required buffer queues to resources */ 10476 /* TODO: to be improved */ 10477 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) { 10478 if (need_input_queue) 10479 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10480 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10481 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10482 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 10483 #if defined SH_CSS_ENABLE_METADATA 10484 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10485 #endif 10486 if (pipe->pipe_settings.preview.preview_binary.info && 10487 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a) 10488 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 10489 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) { 10490 unsigned int i; 10491 10492 if (need_input_queue) 10493 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10494 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10495 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); 10496 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10497 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 10498 #if defined SH_CSS_ENABLE_METADATA 10499 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10500 #endif 10501 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 10502 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 10503 if (pipe->pipe_settings.capture.primary_binary[i].info && 10504 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) { 10505 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 10506 break; 10507 } 10508 } 10509 } else if (pipe->config.default_capture_config.mode == 10510 IA_CSS_CAPTURE_MODE_ADVANCED || 10511 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT || 10512 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) { 10513 if (pipe->pipe_settings.capture.pre_isp_binary.info && 10514 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a) 10515 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 10516 } 10517 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) { 10518 if (need_input_queue) 10519 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10520 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10521 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) 10522 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); 10523 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10524 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 10525 #if defined SH_CSS_ENABLE_METADATA 10526 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10527 #endif 10528 if (pipe->pipe_settings.video.video_binary.info && 10529 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a) 10530 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 10531 if (pipe->pipe_settings.video.video_binary.info && 10532 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis 10533 )) 10534 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map); 10535 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) { 10536 if (need_input_queue) 10537 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10538 if (!pipe->stream->config.continuous) 10539 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10540 #if defined SH_CSS_ENABLE_METADATA 10541 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10542 #endif 10543 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) { 10544 if (need_input_queue) 10545 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10546 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10547 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10548 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 10549 #if defined SH_CSS_ENABLE_METADATA 10550 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10551 #endif 10552 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) { 10553 unsigned int idx; 10554 10555 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) { 10556 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map); 10557 if (pipe->enable_viewfinder[idx]) 10558 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map); 10559 } 10560 if (need_input_queue) 10561 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10562 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10563 #if defined SH_CSS_ENABLE_METADATA 10564 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10565 #endif 10566 } 10567 IA_CSS_LEAVE(""); 10568 } 10569 10570 #if CONFIG_ON_FRAME_ENQUEUE() 10571 static int set_config_on_frame_enqueue(struct ia_css_frame_info 10572 *info, struct frame_data_wrapper *frame) { 10573 frame->config_on_frame_enqueue.padded_width = 0; 10574 10575 /* currently we support configuration on frame enqueue only on YUV formats */ 10576 /* on other formats the padded_width is zeroed for no configuration override */ 10577 switch (info->format) { 10578 case IA_CSS_FRAME_FORMAT_YUV420: 10579 case IA_CSS_FRAME_FORMAT_NV12: 10580 if (info->padded_width > info->res.width) { 10581 frame->config_on_frame_enqueue.padded_width = info->padded_width; 10582 } else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) { 10583 return -EINVAL; 10584 } 10585 /* nothing to do if width == padded width or padded width is zeroed (the same) */ 10586 break; 10587 default: 10588 break; 10589 } 10590 10591 return 0; 10592 } 10593 #endif 10594 10595 int 10596 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) { 10597 int ret; 10598 10599 IA_CSS_ENTER(""); 10600 10601 /* Only continuous streams have a tagger to which we can send the 10602 * unlock message. */ 10603 if (!stream || !stream->config.continuous) 10604 { 10605 IA_CSS_ERROR("invalid stream pointer"); 10606 return -EINVAL; 10607 } 10608 10609 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID || 10610 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) 10611 { 10612 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id); 10613 return -EINVAL; 10614 } 10615 10616 /* Send the event. Since we verified that the exp_id is valid, 10617 * we can safely assign it to an 8-bit argument here. */ 10618 ret = ia_css_bufq_enqueue_psys_event( 10619 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0); 10620 10621 IA_CSS_LEAVE_ERR(ret); 10622 return ret; 10623 } 10624 10625 /* @brief Set the state (Enable or Disable) of the Extension stage in the 10626 * given pipe. 10627 */ 10628 int 10629 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, 10630 bool enable) { 10631 unsigned int thread_id; 10632 struct ia_css_pipeline_stage *stage; 10633 int err = 0; 10634 10635 IA_CSS_ENTER(""); 10636 10637 /* Parameter Check */ 10638 if (!pipe || !pipe->stream) 10639 { 10640 IA_CSS_ERROR("Invalid Pipe."); 10641 err = -EINVAL; 10642 } else if (!(pipe->config.acc_extension)) 10643 { 10644 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)"); 10645 err = -EINVAL; 10646 } else if (!sh_css_sp_is_running()) 10647 { 10648 IA_CSS_ERROR("Leaving: queue unavailable."); 10649 err = -EBUSY; 10650 } else 10651 { 10652 /* Query the threadid and stage_num for the Extension firmware*/ 10653 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 10654 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); 10655 if (!err) { 10656 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/ 10657 err = ia_css_bufq_enqueue_psys_event( 10658 (uint8_t)IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE, 10659 (uint8_t)thread_id, 10660 (uint8_t)stage->stage_num, 10661 enable ? 1 : 0); 10662 if (!err) { 10663 if (enable) 10664 SH_CSS_QOS_STAGE_ENABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num); 10665 else 10666 SH_CSS_QOS_STAGE_DISABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num); 10667 } 10668 } 10669 } 10670 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable); 10671 return err; 10672 } 10673 10674 /* @brief Get the state (Enable or Disable) of the Extension stage in the 10675 * given pipe. 10676 */ 10677 int 10678 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, 10679 bool *enable) { 10680 struct ia_css_pipeline_stage *stage; 10681 unsigned int thread_id; 10682 int err = 0; 10683 10684 IA_CSS_ENTER(""); 10685 10686 /* Parameter Check */ 10687 if (!pipe || !pipe->stream) 10688 { 10689 IA_CSS_ERROR("Invalid Pipe."); 10690 err = -EINVAL; 10691 } else if (!(pipe->config.acc_extension)) 10692 { 10693 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); 10694 err = -EINVAL; 10695 } else if (!sh_css_sp_is_running()) 10696 { 10697 IA_CSS_ERROR("Leaving: queue unavailable."); 10698 err = -EBUSY; 10699 } else 10700 { 10701 /* Query the threadid and stage_num corresponding to the Extension firmware*/ 10702 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 10703 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); 10704 10705 if (!err) { 10706 /* Get the Extension State */ 10707 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id], 10708 stage->stage_num)) ? true : false; 10709 } 10710 } 10711 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable); 10712 return err; 10713 } 10714 10715 /* ISP2401 */ 10716 int 10717 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, 10718 u32 fw_handle, 10719 struct ia_css_isp_param_css_segments *css_seg, 10720 struct ia_css_isp_param_isp_segments *isp_seg) { 10721 unsigned int HIVE_ADDR_sp_group; 10722 static struct sh_css_sp_group sp_group; 10723 static struct sh_css_sp_stage sp_stage; 10724 static struct sh_css_isp_stage isp_stage; 10725 const struct ia_css_fw_info *fw; 10726 unsigned int thread_id; 10727 struct ia_css_pipeline_stage *stage; 10728 int err = 0; 10729 int stage_num = 0; 10730 enum ia_css_isp_memories mem; 10731 bool enabled; 10732 10733 IA_CSS_ENTER(""); 10734 10735 fw = &sh_css_sp_fw; 10736 10737 /* Parameter Check */ 10738 if (!pipe || !pipe->stream) 10739 { 10740 IA_CSS_ERROR("Invalid Pipe."); 10741 err = -EINVAL; 10742 } else if (!(pipe->config.acc_extension)) 10743 { 10744 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); 10745 err = -EINVAL; 10746 } else if (!sh_css_sp_is_running()) 10747 { 10748 IA_CSS_ERROR("Leaving: queue unavailable."); 10749 err = -EBUSY; 10750 } else 10751 { 10752 /* Query the thread_id and stage_num corresponding to the Extension firmware */ 10753 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 10754 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); 10755 if (!err) { 10756 /* Get the Extension State */ 10757 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id], 10758 stage->stage_num)) ? true : false; 10759 /* Update mapped arg only when extension stage is not enabled */ 10760 if (enabled) { 10761 IA_CSS_ERROR("Leaving: cannot update when stage is enabled."); 10762 err = -EBUSY; 10763 } else { 10764 stage_num = stage->stage_num; 10765 10766 HIVE_ADDR_sp_group = fw->info.sp.group; 10767 sp_dmem_load(SP0_ID, 10768 (unsigned int)sp_address_of(sp_group), 10769 &sp_group, sizeof(struct sh_css_sp_group)); 10770 hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num], 10771 &sp_stage, sizeof(struct sh_css_sp_stage)); 10772 10773 hmm_load(sp_stage.isp_stage_addr, 10774 &isp_stage, sizeof(struct sh_css_isp_stage)); 10775 10776 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) { 10777 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address = 10778 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address; 10779 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size = 10780 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size; 10781 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address 10782 = 10783 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address; 10784 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size 10785 = 10786 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size; 10787 } 10788 10789 hmm_store(sp_stage.isp_stage_addr, 10790 &isp_stage, sizeof(struct sh_css_isp_stage)); 10791 } 10792 } 10793 } 10794 IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle); 10795 return err; 10796 } 10797 10798 #ifdef USE_INPUT_SYSTEM_VERSION_2401 10799 static int 10800 aspect_ratio_crop_init(struct ia_css_stream *curr_stream, 10801 struct ia_css_pipe *pipes[], 10802 bool *do_crop_status) { 10803 int err = 0; 10804 int i; 10805 struct ia_css_pipe *curr_pipe; 10806 u32 pipe_mask = 0; 10807 10808 if ((!curr_stream) || 10809 (curr_stream->num_pipes == 0) || 10810 (!pipes) || 10811 (!do_crop_status)) 10812 { 10813 err = -EINVAL; 10814 IA_CSS_LEAVE_ERR(err); 10815 return err; 10816 } 10817 10818 for (i = 0; i < curr_stream->num_pipes; i++) 10819 { 10820 curr_pipe = pipes[i]; 10821 pipe_mask |= (1 << curr_pipe->config.mode); 10822 } 10823 10824 *do_crop_status = 10825 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) || 10826 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) && 10827 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) && 10828 curr_stream->config.continuous); 10829 return 0; 10830 } 10831 10832 static bool 10833 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) { 10834 bool status = false; 10835 10836 if ((curr_pipe) && enabled) { 10837 if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) || 10838 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) || 10839 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE)) 10840 status = true; 10841 } 10842 10843 return status; 10844 } 10845 10846 static int 10847 aspect_ratio_crop(struct ia_css_pipe *curr_pipe, 10848 struct ia_css_resolution *effective_res) { 10849 int err = 0; 10850 struct ia_css_resolution crop_res; 10851 struct ia_css_resolution *in_res = NULL; 10852 struct ia_css_resolution *out_res = NULL; 10853 bool use_bds_output_info = false; 10854 bool use_vf_pp_in_res = false; 10855 bool use_capt_pp_in_res = false; 10856 10857 if ((!curr_pipe) || 10858 (!effective_res)) 10859 { 10860 err = -EINVAL; 10861 IA_CSS_LEAVE_ERR(err); 10862 return err; 10863 } 10864 10865 if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) && 10866 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) && 10867 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) 10868 { 10869 err = -EINVAL; 10870 IA_CSS_LEAVE_ERR(err); 10871 return err; 10872 } 10873 10874 use_bds_output_info = 10875 ((curr_pipe->bds_output_info.res.width != 0) && 10876 (curr_pipe->bds_output_info.res.height != 0)); 10877 10878 use_vf_pp_in_res = 10879 ((curr_pipe->config.vf_pp_in_res.width != 0) && 10880 (curr_pipe->config.vf_pp_in_res.height != 0)); 10881 10882 use_capt_pp_in_res = 10883 ((curr_pipe->config.capt_pp_in_res.width != 0) && 10884 (curr_pipe->config.capt_pp_in_res.height != 0)); 10885 10886 in_res = &curr_pipe->stream->config.input_config.effective_res; 10887 out_res = &curr_pipe->output_info[0].res; 10888 10889 switch (curr_pipe->config.mode) 10890 { 10891 case IA_CSS_PIPE_MODE_PREVIEW: 10892 if (use_bds_output_info) 10893 out_res = &curr_pipe->bds_output_info.res; 10894 else if (use_vf_pp_in_res) 10895 out_res = &curr_pipe->config.vf_pp_in_res; 10896 break; 10897 case IA_CSS_PIPE_MODE_VIDEO: 10898 if (use_bds_output_info) 10899 out_res = &curr_pipe->bds_output_info.res; 10900 break; 10901 case IA_CSS_PIPE_MODE_CAPTURE: 10902 if (use_capt_pp_in_res) 10903 out_res = &curr_pipe->config.capt_pp_in_res; 10904 break; 10905 case IA_CSS_PIPE_MODE_ACC: 10906 case IA_CSS_PIPE_MODE_COPY: 10907 case IA_CSS_PIPE_MODE_YUVPP: 10908 default: 10909 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n", 10910 curr_pipe->config.mode); 10911 assert(0); 10912 break; 10913 } 10914 10915 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res); 10916 if (!err) 10917 { 10918 *effective_res = crop_res; 10919 } else 10920 { 10921 /* in case of error fallback to default 10922 * effective resolution from driver. */ 10923 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err); 10924 } 10925 return err; 10926 } 10927 #endif 10928 10929 static void 10930 sh_css_hmm_buffer_record_init(void) { 10931 int i; 10932 10933 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) 10934 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]); 10935 } 10936 10937 static void 10938 sh_css_hmm_buffer_record_uninit(void) { 10939 int i; 10940 struct sh_css_hmm_buffer_record *buffer_record = NULL; 10941 10942 buffer_record = &hmm_buffer_record[0]; 10943 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 10944 if (buffer_record->in_use) { 10945 if (buffer_record->h_vbuf) 10946 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf); 10947 sh_css_hmm_buffer_record_reset(buffer_record); 10948 } 10949 buffer_record++; 10950 } 10951 } 10952 10953 static void 10954 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) { 10955 assert(buffer_record); 10956 buffer_record->in_use = false; 10957 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID; 10958 buffer_record->h_vbuf = NULL; 10959 buffer_record->kernel_ptr = 0; 10960 } 10961 10962 static struct sh_css_hmm_buffer_record 10963 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf, 10964 enum ia_css_buffer_type type, 10965 hrt_address kernel_ptr) { 10966 int i; 10967 struct sh_css_hmm_buffer_record *buffer_record = NULL; 10968 struct sh_css_hmm_buffer_record *out_buffer_record = NULL; 10969 10970 assert(h_vbuf); 10971 assert((type > IA_CSS_BUFFER_TYPE_INVALID) && 10972 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE)); 10973 assert(kernel_ptr != 0); 10974 10975 buffer_record = &hmm_buffer_record[0]; 10976 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 10977 if (!buffer_record->in_use) { 10978 buffer_record->in_use = true; 10979 buffer_record->type = type; 10980 buffer_record->h_vbuf = h_vbuf; 10981 buffer_record->kernel_ptr = kernel_ptr; 10982 out_buffer_record = buffer_record; 10983 break; 10984 } 10985 buffer_record++; 10986 } 10987 10988 return out_buffer_record; 10989 } 10990 10991 static struct sh_css_hmm_buffer_record 10992 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr, 10993 enum ia_css_buffer_type type) { 10994 int i; 10995 struct sh_css_hmm_buffer_record *buffer_record = NULL; 10996 bool found_record = false; 10997 10998 buffer_record = &hmm_buffer_record[0]; 10999 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 11000 if ((buffer_record->in_use) && 11001 (buffer_record->type == type) && 11002 (buffer_record->h_vbuf) && 11003 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) { 11004 found_record = true; 11005 break; 11006 } 11007 buffer_record++; 11008 } 11009 11010 if (found_record) 11011 return buffer_record; 11012 else 11013 return NULL; 11014 } 11015