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