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 enum ia_css_err 186 allocate_delay_frames(struct ia_css_pipe *pipe); 187 188 static enum ia_css_err 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 * - IA_CSS_SUCCESS, 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 enum ia_css_err 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 enum ia_css_err 229 ia_css_pipe_check_format(struct ia_css_pipe *pipe, 230 enum ia_css_frame_format format); 231 232 /* ISP 2401 */ 233 static enum ia_css_err 234 check_pipe_resolutions(const struct ia_css_pipe *pipe); 235 236 static enum ia_css_err 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 enum ia_css_err 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 enum ia_css_err 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 enum ia_css_err 274 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe); 275 276 static 277 enum ia_css_err 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 enum ia_css_err 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 enum ia_css_err 288 capture_start(struct ia_css_pipe *pipe); 289 290 static enum ia_css_err 291 video_start(struct ia_css_pipe *pipe); 292 293 static enum ia_css_err 294 preview_start(struct ia_css_pipe *pipe); 295 296 static enum ia_css_err 297 yuvpp_start(struct ia_css_pipe *pipe); 298 299 static bool copy_on_sp(struct ia_css_pipe *pipe); 300 301 static enum ia_css_err 302 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, 303 struct ia_css_frame *vf_frame, unsigned int idx); 304 305 static enum ia_css_err 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 enum ia_css_err 310 init_out_frameinfo_defaults(struct ia_css_pipe *pipe, 311 struct ia_css_frame *out_frame, unsigned int idx); 312 313 static enum ia_css_err 314 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, 315 const void *acc_fw); 316 317 static enum ia_css_err 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 enum ia_css_err 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 enum ia_css_err 332 create_host_pipeline_structure(struct ia_css_stream *stream); 333 334 static enum ia_css_err 335 create_host_pipeline(struct ia_css_stream *stream); 336 337 static enum ia_css_err 338 create_host_preview_pipeline(struct ia_css_pipe *pipe); 339 340 static enum ia_css_err 341 create_host_video_pipeline(struct ia_css_pipe *pipe); 342 343 static enum ia_css_err 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 enum ia_css_err 349 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe); 350 351 static enum ia_css_err 352 create_host_capture_pipeline(struct ia_css_pipe *pipe); 353 354 static enum ia_css_err 355 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe); 356 357 static enum ia_css_err 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 enum ia_css_err 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 enum ia_css_err 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 enum ia_css_err 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 enum ia_css_err 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 IA_CSS_ERR_INVALID_ARGUMENTS; 519 return IA_CSS_SUCCESS; 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 IA_CSS_SUCCESS; 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 enum ia_css_err 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 enum ia_css_err 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 IA_CSS_ERR_INTERNAL_ERROR; 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 IA_CSS_ERR_INTERNAL_ERROR; 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 IA_CSS_ERR_INTERNAL_ERROR; 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 IA_CSS_ERR_INTERNAL_ERROR; 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 IA_CSS_ERR_INTERNAL_ERROR; 1165 } 1166 } 1167 1168 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 1169 "sh_css_config_input_network() leave:\n"); 1170 1171 return IA_CSS_SUCCESS; 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 enum ia_css_err stream_csi_rx_helper( 1230 struct ia_css_stream *stream, 1231 enum ia_css_err (*func)(enum mipi_port_id, uint32_t)) 1232 { 1233 enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR; 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 == IA_CSS_SUCCESS) && 1263 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)); 1264 1265 exit: 1266 return retval; 1267 } 1268 1269 static inline enum ia_css_err 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 enum ia_css_err 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 enum ia_css_err 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 IA_CSS_ERR_INVALID_ARGUMENTS; 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 IA_CSS_ERR_INTERNAL_ERROR; 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 IA_CSS_SUCCESS; 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 enum ia_css_err 1629 ia_css_load_firmware(struct device *dev, const struct ia_css_env *env, 1630 const struct ia_css_fw *fw) { 1631 enum ia_css_err err; 1632 1633 if (!env) 1634 return IA_CSS_ERR_INVALID_ARGUMENTS; 1635 if (!fw) 1636 return IA_CSS_ERR_INVALID_ARGUMENTS; 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 == IA_CSS_SUCCESS) 1650 { 1651 err = ia_css_binary_init_infos(); 1652 if (err == IA_CSS_SUCCESS) 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 enum ia_css_err 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 enum ia_css_err 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 IA_CSS_ERR_INVALID_ARGUMENTS; 1709 if (!env) 1710 return IA_CSS_ERR_INVALID_ARGUMENTS; 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 1776 { 1777 IA_CSS_LEAVE_ERR(err); 1778 return err; 1779 } 1780 err = sh_css_params_init(); 1781 if (err != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) { 1791 IA_CSS_LEAVE_ERR(err); 1792 return err; 1793 } 1794 err = ia_css_binary_init_infos(); 1795 if (err != IA_CSS_SUCCESS) { 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 IA_CSS_ERR_INTERNAL_ERROR; 1806 1807 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg); 1808 if (err != IA_CSS_SUCCESS) 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(IA_CSS_ERR_SYSTEM_NOT_IDLE); 1826 return IA_CSS_ERR_SYSTEM_NOT_IDLE; 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 = IA_CSS_ERR_INVALID_ARGUMENTS; 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 enum ia_css_err 1858 ia_css_enable_isys_event_queue(bool enable) { 1859 if (sh_css_sp_is_running()) 1860 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 1861 sh_css_sp_enable_isys_event_queue(enable); 1862 return IA_CSS_SUCCESS; 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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(IA_CSS_ERR_INVALID_ARGUMENTS); 1902 return IA_CSS_ERR_INVALID_ARGUMENTS; 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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(IA_CSS_ERR_INVALID_ARGUMENTS); 1975 return IA_CSS_ERR_INVALID_ARGUMENTS; 1976 } 1977 1978 main_pipe = stream->last_pipe; 1979 assert(main_pipe); 1980 if (!main_pipe) 1981 { 1982 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 1983 return IA_CSS_ERR_INVALID_ARGUMENTS; 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 = IA_CSS_ERR_INVALID_ARGUMENTS; 2026 } 2027 2028 if ((err == IA_CSS_SUCCESS) && 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 == IA_CSS_SUCCESS) && 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 == IA_CSS_SUCCESS) && 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 && IA_CSS_SUCCESS == 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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(IA_CSS_ERR_INVALID_ARGUMENTS); 2083 return IA_CSS_ERR_INVALID_ARGUMENTS; 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 2169 goto ERR; 2170 2171 break; 2172 default: 2173 err = IA_CSS_ERR_INVALID_ARGUMENTS; 2174 } 2175 if (err != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 2183 goto ERR; 2184 } 2185 2186 if (capture_pipe) 2187 { 2188 err = create_host_capture_pipeline(capture_pipe); 2189 if (err != IA_CSS_SUCCESS) 2190 goto ERR; 2191 } 2192 2193 if (acc_pipe) 2194 { 2195 err = create_host_acc_pipeline(acc_pipe); 2196 if (err != IA_CSS_SUCCESS) 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 && IA_CSS_SUCCESS == 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 = IA_CSS_ERR_INVALID_ARGUMENTS; 2224 } 2225 if (err != IA_CSS_SUCCESS) 2226 goto ERR; 2227 } 2228 } 2229 2230 ERR: 2231 IA_CSS_LEAVE_ERR_PRIVATE(err); 2232 return err; 2233 } 2234 2235 static enum ia_css_err 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 IA_CSS_ERR_INVALID_ARGUMENTS; 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 IA_CSS_ERR_INVALID_ARGUMENTS; 2279 } 2280 2281 return IA_CSS_SUCCESS; 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 enum ia_css_err 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 IA_CSS_ERR_INVALID_ARGUMENTS; 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 IA_CSS_ERR_RESOURCE_EXHAUSTED; 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 IA_CSS_SUCCESS; 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 enum ia_css_err 2343 create_pipe(enum ia_css_pipe_mode mode, 2344 struct ia_css_pipe **pipe, 2345 bool copy_pipe) { 2346 enum ia_css_err err = IA_CSS_SUCCESS; 2347 struct ia_css_pipe *me; 2348 2349 if (!pipe) 2350 { 2351 IA_CSS_ERROR("NULL pipe parameter"); 2352 return IA_CSS_ERR_INVALID_ARGUMENTS; 2353 } 2354 2355 me = kmalloc(sizeof(*me), GFP_KERNEL); 2356 if (!me) 2357 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 2358 2359 err = init_pipe_defaults(mode, me, copy_pipe); 2360 if (err != IA_CSS_SUCCESS) 2361 { 2362 kfree(me); 2363 return err; 2364 } 2365 2366 err = pipe_generate_pipe_num(me, &me->pipe_num); 2367 if (err != IA_CSS_SUCCESS) 2368 { 2369 kfree(me); 2370 return err; 2371 } 2372 2373 *pipe = me; 2374 return IA_CSS_SUCCESS; 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 enum ia_css_err 2414 ia_css_pipe_destroy(struct ia_css_pipe *pipe) { 2415 enum ia_css_err err = IA_CSS_SUCCESS; 2416 2417 IA_CSS_ENTER("pipe = %p", pipe); 2418 2419 if (!pipe) 2420 { 2421 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 2422 return IA_CSS_ERR_INVALID_ARGUMENTS; 2423 } 2424 2425 if (pipe->stream) 2426 { 2427 IA_CSS_LOG("ia_css_stream_destroy not called!"); 2428 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 2429 return IA_CSS_ERR_INVALID_ARGUMENTS; 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 enum ia_css_err 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 IA_CSS_ERR_INTERNAL_ERROR; 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 IA_CSS_SUCCESS; 2619 } 2620 2621 enum ia_css_err 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 IA_CSS_SUCCESS; 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(IA_CSS_ERR_INVALID_ARGUMENTS); 2662 return IA_CSS_ERR_INVALID_ARGUMENTS; 2663 } 2664 2665 cnd_virq_enable_channel(irq, enable); 2666 2667 IA_CSS_LEAVE_ERR(IA_CSS_SUCCESS); 2668 return IA_CSS_SUCCESS; 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 enum ia_css_err 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 enum ia_css_err 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 != IA_CSS_SUCCESS) 2721 return err; 2722 copy_binary->left_padding = left_padding; 2723 return IA_CSS_SUCCESS; 2724 } 2725 2726 static enum ia_css_err 2727 alloc_continuous_frames( 2728 struct ia_css_pipe *pipe, bool init_time) { 2729 enum ia_css_err err = IA_CSS_SUCCESS; 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(IA_CSS_ERR_INVALID_ARGUMENTS); 2742 return IA_CSS_ERR_INVALID_ARGUMENTS; 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(IA_CSS_ERR_INTERNAL_ERROR); 2770 return IA_CSS_ERR_INTERNAL_ERROR; 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(IA_CSS_ERR_INTERNAL_ERROR); 2810 return IA_CSS_ERR_INTERNAL_ERROR; 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 != IA_CSS_SUCCESS) { 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(IA_CSS_SUCCESS); 2845 return IA_CSS_SUCCESS; 2846 } 2847 2848 enum ia_css_err 2849 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) { 2850 if (!stream) 2851 return IA_CSS_ERR_INVALID_ARGUMENTS; 2852 return alloc_continuous_frames(stream->continuous_pipe, false); 2853 } 2854 2855 static enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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 IA_CSS_SUCCESS; 2886 2887 err = ia_css_util_check_input(&pipe->stream->config, false, false); 2888 if (err != IA_CSS_SUCCESS) 2889 return err; 2890 err = ia_css_frame_check_info(pipe_out_info); 2891 if (err != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 2936 return err; 2937 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary); 2938 if (err != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 2980 return err; 2981 err = ia_css_binary_find(&preview_descr, 2982 &mycs->preview_binary); 2983 if (err != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 IA_CSS_SUCCESS; 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 enum ia_css_err 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(IA_CSS_ERR_INVALID_ARGUMENTS); 3050 return IA_CSS_ERR_INVALID_ARGUMENTS; 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(IA_CSS_SUCCESS); 3057 return IA_CSS_SUCCESS; 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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 != IA_CSS_SUCCESS) 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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 IA_CSS_ERR_INVALID_ARGUMENTS; 3145 if (!in_frame) 3146 return IA_CSS_ERR_INVALID_ARGUMENTS; 3147 if (!vf_pp_binary) 3148 return IA_CSS_ERR_INVALID_ARGUMENTS; 3149 if (!vf_pp_stage) 3150 return IA_CSS_ERR_INVALID_ARGUMENTS; 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 != IA_CSS_SUCCESS) 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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 != IA_CSS_SUCCESS) 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 enum ia_css_err 3322 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, 3323 struct ia_css_frame *vf_frame, unsigned int idx) { 3324 enum ia_css_err err = IA_CSS_SUCCESS; 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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 enum ia_css_err 3528 init_out_frameinfo_defaults(struct ia_css_pipe *pipe, 3529 struct ia_css_frame *out_frame, unsigned int idx) { 3530 enum ia_css_err err = IA_CSS_SUCCESS; 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 enum ia_css_err 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 enum ia_css_err err = IA_CSS_SUCCESS; 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(IA_CSS_ERR_INVALID_ARGUMENTS); 3576 return IA_CSS_ERR_INVALID_ARGUMENTS; 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 != IA_CSS_SUCCESS) 3605 goto ERR; 3606 } 3607 3608 out_frame->data = 0; 3609 err = init_out_frameinfo_defaults(pipe, out_frame, 0); 3610 if (err != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 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 != IA_CSS_SUCCESS) 3687 goto ERR; 3688 } 3689 if (video_stage) { 3690 int frm; 3691 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) { 3692 video_stage->args.tnr_frames[frm] = 3693 pipe->pipe_settings.video.tnr_frames[frm]; 3694 } 3695 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) { 3696 video_stage->args.delay_frames[frm] = 3697 pipe->pipe_settings.video.delay_frames[frm]; 3698 } 3699 } 3700 3701 /* Append Extension on Video out, if enabled */ 3702 if (!need_vf_pp && video_stage && pipe->config.acc_extension && 3703 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) { 3704 struct ia_css_frame *out = NULL; 3705 struct ia_css_frame *in = NULL; 3706 3707 if ((pipe->config.acc_extension->info.isp.sp.enable.output) && 3708 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) && 3709 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) { 3710 /* In/Out Frame mapping to support output frame extension.*/ 3711 out = video_stage->args.out_frame[0]; 3712 err = ia_css_frame_allocate_from_info(&in, &pipe->output_info[0]); 3713 if (err != IA_CSS_SUCCESS) 3714 goto ERR; 3715 video_stage->args.out_frame[0] = in; 3716 } 3717 3718 err = add_firmwares(me, video_binary, pipe->output_stage, 3719 last_output_firmware(pipe->output_stage), 3720 IA_CSS_BINARY_MODE_VIDEO, 3721 in, out, NULL, &video_stage, NULL); 3722 if (err != IA_CSS_SUCCESS) 3723 goto ERR; 3724 } 3725 3726 if (need_yuv_pp && video_stage) { 3727 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0]; 3728 struct ia_css_frame *tmp_out_frame = NULL; 3729 3730 for (i = 0; i < num_yuv_scaler; i++) { 3731 if (is_output_stage[i] == true) { 3732 tmp_out_frame = out_frame; 3733 } else { 3734 tmp_out_frame = NULL; 3735 } 3736 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, 3737 NULL, 3738 &yuv_scaler_binary[i], 3739 &yuv_scaler_stage); 3740 3741 if (err != IA_CSS_SUCCESS) { 3742 IA_CSS_LEAVE_ERR_PRIVATE(err); 3743 return err; 3744 } 3745 /* we use output port 1 as internal output port */ 3746 if (yuv_scaler_stage) 3747 tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; 3748 } 3749 } 3750 3751 pipe->pipeline.acquire_isp_each_stage = false; 3752 ia_css_pipeline_finalize_stages(&pipe->pipeline, 3753 pipe->stream->config.continuous); 3754 3755 ERR: 3756 IA_CSS_LEAVE_ERR_PRIVATE(err); 3757 return err; 3758 } 3759 3760 static enum ia_css_err 3761 create_host_acc_pipeline(struct ia_css_pipe *pipe) { 3762 enum ia_css_err err = IA_CSS_SUCCESS; 3763 const struct ia_css_fw_info *fw; 3764 unsigned int i; 3765 3766 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 3767 if ((!pipe) || (!pipe->stream)) 3768 { 3769 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 3770 return IA_CSS_ERR_INVALID_ARGUMENTS; 3771 } 3772 3773 pipe->pipeline.num_execs = pipe->config.acc_num_execs; 3774 /* Reset pipe_qos_config to default disable all QOS extension stages */ 3775 if (pipe->config.acc_extension) 3776 pipe->pipeline.pipe_qos_config = 0; 3777 3778 fw = pipe->vf_stage; 3779 for (i = 0; fw; fw = fw->next) 3780 { 3781 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw); 3782 if (err != IA_CSS_SUCCESS) 3783 goto ERR; 3784 } 3785 3786 for (i = 0; i < pipe->config.num_acc_stages; i++) 3787 { 3788 struct ia_css_fw_info *fw = pipe->config.acc_stages[i]; 3789 3790 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw); 3791 if (err != IA_CSS_SUCCESS) 3792 goto ERR; 3793 } 3794 3795 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 3796 3797 ERR: 3798 IA_CSS_LEAVE_ERR_PRIVATE(err); 3799 return err; 3800 } 3801 3802 /* Create stages for preview */ 3803 static enum ia_css_err 3804 create_host_preview_pipeline(struct ia_css_pipe *pipe) { 3805 struct ia_css_pipeline_stage *copy_stage = NULL; 3806 struct ia_css_pipeline_stage *preview_stage = NULL; 3807 struct ia_css_pipeline_stage *vf_pp_stage = NULL; 3808 struct ia_css_pipeline_stage_desc stage_desc; 3809 struct ia_css_pipeline *me = NULL; 3810 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL; 3811 struct ia_css_frame *in_frame = NULL; 3812 enum ia_css_err err = IA_CSS_SUCCESS; 3813 struct ia_css_frame *out_frame; 3814 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 3815 bool need_in_frameinfo_memory = false; 3816 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3817 bool sensor = false; 3818 bool buffered_sensor = false; 3819 bool online = false; 3820 bool continuous = false; 3821 #endif 3822 3823 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 3824 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) 3825 { 3826 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 3827 return IA_CSS_ERR_INVALID_ARGUMENTS; 3828 } 3829 3830 ia_css_pipe_util_create_output_frames(out_frames); 3831 /* pipeline already created as part of create_host_pipeline_structure */ 3832 me = &pipe->pipeline; 3833 ia_css_pipeline_clean(me); 3834 3835 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3836 /* When the input system is 2401, always enable 'in_frameinfo_memory' 3837 * except for the following: 3838 * - Direct Sensor Mode Online Preview 3839 * - Buffered Sensor Mode Online Preview 3840 * - Direct Sensor Mode Continuous Preview 3841 * - Buffered Sensor Mode Continuous Preview 3842 */ 3843 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); 3844 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 3845 online = pipe->stream->config.online; 3846 continuous = pipe->stream->config.continuous; 3847 need_in_frameinfo_memory = 3848 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); 3849 #else 3850 /* Construct in_frame info (only in case we have dynamic input */ 3851 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 3852 #endif 3853 if (need_in_frameinfo_memory) 3854 { 3855 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, 3856 IA_CSS_FRAME_FORMAT_RAW); 3857 if (err != IA_CSS_SUCCESS) 3858 goto ERR; 3859 3860 in_frame = &me->in_frame; 3861 } else 3862 { 3863 in_frame = NULL; 3864 } 3865 3866 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); 3867 if (err != IA_CSS_SUCCESS) 3868 goto ERR; 3869 out_frame = &me->out_frame[0]; 3870 3871 copy_binary = &pipe->pipe_settings.preview.copy_binary; 3872 preview_binary = &pipe->pipe_settings.preview.preview_binary; 3873 if (pipe->pipe_settings.preview.vf_pp_binary.info) 3874 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary; 3875 3876 if (pipe->pipe_settings.preview.copy_binary.info) 3877 { 3878 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 3879 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 3880 out_frames, NULL, NULL); 3881 err = ia_css_pipeline_create_and_add_stage(me, 3882 &stage_desc, 3883 ©_stage); 3884 if (err != IA_CSS_SUCCESS) 3885 goto ERR; 3886 in_frame = me->stages->args.out_frame[0]; 3887 #ifndef ISP2401 3888 } else 3889 { 3890 #else 3891 } else if (pipe->stream->config.continuous) 3892 { 3893 #endif 3894 #ifdef USE_INPUT_SYSTEM_VERSION_2401 3895 /* When continuous is enabled, configure in_frame with the 3896 * last pipe, which is the copy pipe. 3897 */ 3898 if (continuous || !online) { 3899 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 3900 } 3901 #else 3902 in_frame = pipe->continuous_frames[0]; 3903 #endif 3904 } 3905 3906 if (vf_pp_binary) 3907 { 3908 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 3909 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, 3910 out_frames, in_frame, NULL); 3911 } else 3912 { 3913 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 3914 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, 3915 out_frames, in_frame, NULL); 3916 } 3917 err = ia_css_pipeline_create_and_add_stage(me, 3918 &stage_desc, 3919 &preview_stage); 3920 if (err != IA_CSS_SUCCESS) 3921 goto ERR; 3922 /* If we use copy iso preview, the input must be yuv iso raw */ 3923 preview_stage->args.copy_vf = 3924 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY; 3925 preview_stage->args.copy_output = !preview_stage->args.copy_vf; 3926 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) 3927 { 3928 /* in case of copy, use the vf frame as output frame */ 3929 preview_stage->args.out_vf_frame = 3930 preview_stage->args.out_frame[0]; 3931 } 3932 if (vf_pp_binary) 3933 { 3934 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY) 3935 in_frame = preview_stage->args.out_vf_frame; 3936 else 3937 in_frame = preview_stage->args.out_frame[0]; 3938 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary, 3939 &vf_pp_stage); 3940 if (err != IA_CSS_SUCCESS) 3941 goto ERR; 3942 } 3943 3944 pipe->pipeline.acquire_isp_each_stage = false; 3945 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 3946 3947 ERR: 3948 IA_CSS_LEAVE_ERR_PRIVATE(err); 3949 return err; 3950 } 3951 3952 static void send_raw_frames(struct ia_css_pipe *pipe) 3953 { 3954 if (pipe->stream->config.continuous) { 3955 unsigned int i; 3956 3957 sh_css_update_host2sp_cont_num_raw_frames 3958 (pipe->stream->config.init_num_cont_raw_buf, true); 3959 sh_css_update_host2sp_cont_num_raw_frames 3960 (pipe->stream->config.target_num_cont_raw_buf, false); 3961 3962 /* Hand-over all the SP-internal buffers */ 3963 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) { 3964 sh_css_update_host2sp_offline_frame(i, 3965 pipe->continuous_frames[i], pipe->cont_md_buffers[i]); 3966 } 3967 } 3968 3969 return; 3970 } 3971 3972 static enum ia_css_err 3973 preview_start(struct ia_css_pipe *pipe) { 3974 struct ia_css_pipeline *me; 3975 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL; 3976 enum ia_css_err err = IA_CSS_SUCCESS; 3977 struct ia_css_pipe *copy_pipe, *capture_pipe; 3978 struct ia_css_pipe *acc_pipe; 3979 enum sh_css_pipe_config_override copy_ovrd; 3980 enum ia_css_input_mode preview_pipe_input_mode; 3981 const struct ia_css_coordinate *coord = NULL; 3982 const struct ia_css_isp_parameters *params = NULL; 3983 3984 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 3985 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) 3986 { 3987 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 3988 return IA_CSS_ERR_INVALID_ARGUMENTS; 3989 } 3990 3991 me = &pipe->pipeline; 3992 3993 preview_pipe_input_mode = pipe->stream->config.mode; 3994 3995 copy_pipe = pipe->pipe_settings.preview.copy_pipe; 3996 capture_pipe = pipe->pipe_settings.preview.capture_pipe; 3997 acc_pipe = pipe->pipe_settings.preview.acc_pipe; 3998 3999 copy_binary = &pipe->pipe_settings.preview.copy_binary; 4000 preview_binary = &pipe->pipe_settings.preview.preview_binary; 4001 if (pipe->pipe_settings.preview.vf_pp_binary.info) 4002 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary; 4003 4004 sh_css_metrics_start_frame(); 4005 4006 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 4007 /* multi stream video needs mipi buffers */ 4008 err = send_mipi_frames(pipe); 4009 if (err != IA_CSS_SUCCESS) { 4010 IA_CSS_LEAVE_ERR_PRIVATE(err); 4011 return err; 4012 } 4013 #endif 4014 send_raw_frames(pipe); 4015 4016 { 4017 unsigned int thread_id; 4018 4019 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 4020 copy_ovrd = 1 << thread_id; 4021 4022 if (pipe->stream->cont_capt) 4023 { 4024 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), 4025 &thread_id); 4026 copy_ovrd |= 1 << thread_id; 4027 } 4028 } 4029 4030 if (atomisp_hw_is_isp2401) { 4031 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl; 4032 params = pipe->stream->isp_params_configs; 4033 } 4034 4035 /* Construct and load the copy pipe */ 4036 if (pipe->stream->config.continuous) 4037 { 4038 sh_css_sp_init_pipeline(©_pipe->pipeline, 4039 IA_CSS_PIPE_ID_COPY, 4040 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe), 4041 false, 4042 pipe->stream->config.pixels_per_clock == 2, false, 4043 false, pipe->required_bds_factor, 4044 copy_ovrd, 4045 pipe->stream->config.mode, 4046 &pipe->stream->config.metadata_config, 4047 &pipe->stream->info.metadata_info, 4048 #if !defined(HAS_NO_INPUT_SYSTEM) 4049 pipe->stream->config.source.port.port, 4050 #endif 4051 coord, 4052 params); 4053 4054 /* make the preview pipe start with mem mode input, copy handles 4055 the actual mode */ 4056 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; 4057 } 4058 4059 /* Construct and load the capture pipe */ 4060 if (pipe->stream->cont_capt) 4061 { 4062 sh_css_sp_init_pipeline(&capture_pipe->pipeline, 4063 IA_CSS_PIPE_ID_CAPTURE, 4064 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe), 4065 capture_pipe->config.default_capture_config.enable_xnr != 0, 4066 capture_pipe->stream->config.pixels_per_clock == 2, 4067 true, /* continuous */ 4068 false, /* offline */ 4069 capture_pipe->required_bds_factor, 4070 0, 4071 IA_CSS_INPUT_MODE_MEMORY, 4072 &pipe->stream->config.metadata_config, 4073 &pipe->stream->info.metadata_info, 4074 #if !defined(HAS_NO_INPUT_SYSTEM) 4075 (enum mipi_port_id)0, 4076 #endif 4077 coord, 4078 params); 4079 } 4080 4081 if (acc_pipe) 4082 { 4083 sh_css_sp_init_pipeline(&acc_pipe->pipeline, 4084 IA_CSS_PIPE_ID_ACC, 4085 (uint8_t)ia_css_pipe_get_pipe_num(acc_pipe), 4086 false, 4087 pipe->stream->config.pixels_per_clock == 2, 4088 false, /* continuous */ 4089 false, /* offline */ 4090 pipe->required_bds_factor, 4091 0, 4092 IA_CSS_INPUT_MODE_MEMORY, 4093 NULL, 4094 NULL, 4095 #if !defined(HAS_NO_INPUT_SYSTEM) 4096 (enum mipi_port_id)0, 4097 #endif 4098 coord, 4099 params); 4100 } 4101 4102 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode); 4103 4104 IA_CSS_LEAVE_ERR_PRIVATE(err); 4105 return err; 4106 } 4107 4108 enum ia_css_err 4109 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, 4110 const struct ia_css_buffer *buffer) { 4111 enum ia_css_err return_err = IA_CSS_SUCCESS; 4112 unsigned int thread_id; 4113 enum sh_css_queue_id queue_id; 4114 struct ia_css_pipeline *pipeline; 4115 struct ia_css_pipeline_stage *stage; 4116 struct ia_css_rmgr_vbuf_handle p_vbuf; 4117 struct ia_css_rmgr_vbuf_handle *h_vbuf; 4118 struct sh_css_hmm_buffer ddr_buffer; 4119 enum ia_css_buffer_type buf_type; 4120 enum ia_css_pipe_id pipe_id; 4121 bool ret_err; 4122 4123 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer); 4124 4125 if ((!pipe) || (!buffer)) 4126 { 4127 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4128 return IA_CSS_ERR_INVALID_ARGUMENTS; 4129 } 4130 4131 buf_type = buffer->type; 4132 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME 4133 is removed */ 4134 #if 0 4135 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 4136 { 4137 bool found_pipe = false; 4138 4139 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 4140 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) && 4141 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) { 4142 buf_type += i; 4143 found_pipe = true; 4144 break; 4145 } 4146 } 4147 if (!found_pipe) 4148 return IA_CSS_ERR_INVALID_ARGUMENTS; 4149 } 4150 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) 4151 { 4152 bool found_pipe = false; 4153 4154 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 4155 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) && 4156 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) { 4157 buf_type += i; 4158 found_pipe = true; 4159 break; 4160 } 4161 } 4162 if (!found_pipe) 4163 return IA_CSS_ERR_INVALID_ARGUMENTS; 4164 } 4165 #endif 4166 pipe_id = pipe->mode; 4167 4168 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type); 4169 4170 assert(pipe_id < IA_CSS_PIPE_ID_NUM); 4171 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE); 4172 if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) || 4173 (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) || 4174 (pipe_id >= IA_CSS_PIPE_ID_NUM)) 4175 { 4176 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); 4177 return IA_CSS_ERR_INTERNAL_ERROR; 4178 } 4179 4180 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 4181 if (!ret_err) 4182 { 4183 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4184 return IA_CSS_ERR_INVALID_ARGUMENTS; 4185 } 4186 4187 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id); 4188 if (!ret_err) 4189 { 4190 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4191 return IA_CSS_ERR_INVALID_ARGUMENTS; 4192 } 4193 4194 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) 4195 { 4196 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4197 return IA_CSS_ERR_INVALID_ARGUMENTS; 4198 } 4199 4200 if (!sh_css_sp_is_running()) 4201 { 4202 IA_CSS_LOG("SP is not running!"); 4203 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); 4204 /* SP is not running. The queues are not valid */ 4205 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 4206 } 4207 4208 pipeline = &pipe->pipeline; 4209 4210 assert(pipeline || 4211 pipe_id == IA_CSS_PIPE_ID_COPY || 4212 pipe_id == IA_CSS_PIPE_ID_ACC); 4213 4214 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr)); 4215 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL); 4216 ddr_buffer.cookie_ptr = buffer->driver_cookie; 4217 ddr_buffer.timing_data = buffer->timing_data; 4218 4219 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) 4220 { 4221 if (!buffer->data.stats_3a) { 4222 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4223 return IA_CSS_ERR_INVALID_ARGUMENTS; 4224 } 4225 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a); 4226 ddr_buffer.payload.s3a = *buffer->data.stats_3a; 4227 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) 4228 { 4229 if (!buffer->data.stats_dvs) { 4230 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4231 return IA_CSS_ERR_INVALID_ARGUMENTS; 4232 } 4233 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs); 4234 ddr_buffer.payload.dis = *buffer->data.stats_dvs; 4235 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) 4236 { 4237 if (!buffer->data.metadata) { 4238 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4239 return IA_CSS_ERR_INVALID_ARGUMENTS; 4240 } 4241 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata); 4242 ddr_buffer.payload.metadata = *buffer->data.metadata; 4243 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME) 4244 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 4245 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) 4246 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME) 4247 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)) 4248 { 4249 if (!buffer->data.frame) { 4250 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4251 return IA_CSS_ERR_INVALID_ARGUMENTS; 4252 } 4253 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame); 4254 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data; 4255 ddr_buffer.payload.frame.flashed = 0; 4256 4257 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 4258 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n", 4259 buf_type, buffer->data.frame->data); 4260 4261 #if CONFIG_ON_FRAME_ENQUEUE() 4262 return_err = set_config_on_frame_enqueue( 4263 &buffer->data.frame->info, 4264 &ddr_buffer.payload.frame); 4265 if (return_err != IA_CSS_SUCCESS) { 4266 IA_CSS_LEAVE_ERR(return_err); 4267 return return_err; 4268 } 4269 #endif 4270 } 4271 4272 /* start of test for using rmgr for acq/rel memory */ 4273 p_vbuf.vptr = 0; 4274 p_vbuf.count = 0; 4275 p_vbuf.size = sizeof(struct sh_css_hmm_buffer); 4276 h_vbuf = &p_vbuf; 4277 /* TODO: change next to correct pool for optimization */ 4278 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf); 4279 4280 assert(h_vbuf); 4281 assert(h_vbuf->vptr != 0x0); 4282 4283 if ((!h_vbuf) || (h_vbuf->vptr == 0x0)) 4284 { 4285 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); 4286 return IA_CSS_ERR_INTERNAL_ERROR; 4287 } 4288 4289 hmm_store(h_vbuf->vptr, 4290 (void *)(&ddr_buffer), 4291 sizeof(struct sh_css_hmm_buffer)); 4292 if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) 4293 || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) 4294 || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) 4295 { 4296 if (!pipeline) { 4297 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf); 4298 IA_CSS_LOG("pipeline is empty!"); 4299 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); 4300 return IA_CSS_ERR_INTERNAL_ERROR; 4301 } 4302 4303 for (stage = pipeline->stages; stage; stage = stage->next) { 4304 /* The SP will read the params 4305 after it got empty 3a and dis */ 4306 if (STATS_ENABLED(stage)) { 4307 /* there is a stage that needs it */ 4308 return_err = ia_css_bufq_enqueue_buffer(thread_id, 4309 queue_id, 4310 (uint32_t)h_vbuf->vptr); 4311 } 4312 } 4313 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME) 4314 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 4315 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) 4316 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME) 4317 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME) 4318 || (buf_type == IA_CSS_BUFFER_TYPE_METADATA)) 4319 { 4320 return_err = ia_css_bufq_enqueue_buffer(thread_id, 4321 queue_id, 4322 (uint32_t)h_vbuf->vptr); 4323 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) 4324 if ((return_err == IA_CSS_SUCCESS) && 4325 (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)) { 4326 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d", 4327 ddr_buffer.payload.frame.frame_data, 4328 queue_id, thread_id); 4329 } 4330 #endif 4331 } 4332 4333 if (return_err == IA_CSS_SUCCESS) 4334 { 4335 if (sh_css_hmm_buffer_record_acquire( 4336 h_vbuf, buf_type, 4337 HOST_ADDRESS(ddr_buffer.kernel_ptr))) { 4338 IA_CSS_LOG("send vbuf=%p", h_vbuf); 4339 } else { 4340 return_err = IA_CSS_ERR_INTERNAL_ERROR; 4341 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n"); 4342 } 4343 } 4344 4345 /* 4346 * Tell the SP which queues are not empty, 4347 * by sending the software event. 4348 */ 4349 if (return_err == IA_CSS_SUCCESS) 4350 { 4351 if (!sh_css_sp_is_running()) { 4352 /* SP is not running. The queues are not valid */ 4353 IA_CSS_LOG("SP is not running!"); 4354 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); 4355 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 4356 } 4357 return_err = ia_css_bufq_enqueue_psys_event( 4358 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED, 4359 (uint8_t)thread_id, 4360 queue_id, 4361 0); 4362 } else 4363 { 4364 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf); 4365 IA_CSS_ERROR("buffer not enqueued"); 4366 } 4367 4368 IA_CSS_LEAVE("return value = %d", return_err); 4369 4370 return return_err; 4371 } 4372 4373 /* 4374 * TODO: Free up the hmm memory space. 4375 */ 4376 enum ia_css_err 4377 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, 4378 struct ia_css_buffer *buffer) { 4379 enum ia_css_err return_err; 4380 enum sh_css_queue_id queue_id; 4381 ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0; 4382 struct sh_css_hmm_buffer ddr_buffer; 4383 enum ia_css_buffer_type buf_type; 4384 enum ia_css_pipe_id pipe_id; 4385 unsigned int thread_id; 4386 hrt_address kernel_ptr = 0; 4387 bool ret_err; 4388 4389 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer); 4390 4391 if ((!pipe) || (!buffer)) 4392 { 4393 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4394 return IA_CSS_ERR_INVALID_ARGUMENTS; 4395 } 4396 4397 pipe_id = pipe->mode; 4398 4399 buf_type = buffer->type; 4400 4401 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type); 4402 4403 ddr_buffer.kernel_ptr = 0; 4404 4405 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 4406 if (!ret_err) 4407 { 4408 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4409 return IA_CSS_ERR_INVALID_ARGUMENTS; 4410 } 4411 4412 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id); 4413 if (!ret_err) 4414 { 4415 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4416 return IA_CSS_ERR_INVALID_ARGUMENTS; 4417 } 4418 4419 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) 4420 { 4421 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4422 return IA_CSS_ERR_INVALID_ARGUMENTS; 4423 } 4424 4425 if (!sh_css_sp_is_running()) 4426 { 4427 IA_CSS_LOG("SP is not running!"); 4428 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); 4429 /* SP is not running. The queues are not valid */ 4430 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 4431 } 4432 4433 return_err = ia_css_bufq_dequeue_buffer(queue_id, 4434 (uint32_t *)&ddr_buffer_addr); 4435 4436 if (return_err == IA_CSS_SUCCESS) 4437 { 4438 struct ia_css_frame *frame; 4439 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL; 4440 4441 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr); 4442 4443 /* Validate the ddr_buffer_addr and buf_type */ 4444 hmm_buffer_record = sh_css_hmm_buffer_record_validate( 4445 ddr_buffer_addr, buf_type); 4446 if (hmm_buffer_record) { 4447 /* valid hmm_buffer_record found. Save the kernel_ptr 4448 * for validation after performing hmm_load. The 4449 * vbuf handle and buffer_record can be released. 4450 */ 4451 kernel_ptr = hmm_buffer_record->kernel_ptr; 4452 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf); 4453 sh_css_hmm_buffer_record_reset(hmm_buffer_record); 4454 } else { 4455 IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)", 4456 ddr_buffer_addr, buf_type); 4457 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); 4458 return IA_CSS_ERR_INTERNAL_ERROR; 4459 } 4460 4461 hmm_load(ddr_buffer_addr, 4462 &ddr_buffer, 4463 sizeof(struct sh_css_hmm_buffer)); 4464 4465 /* if the kernel_ptr is 0 or an invalid, return an error. 4466 * do not access the buffer via the kernal_ptr. 4467 */ 4468 if ((ddr_buffer.kernel_ptr == 0) || 4469 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) { 4470 IA_CSS_ERROR("kernel_ptr invalid"); 4471 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr); 4472 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr)); 4473 IA_CSS_ERROR("buf_type: %d\n", buf_type); 4474 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); 4475 return IA_CSS_ERR_INTERNAL_ERROR; 4476 } 4477 4478 if (ddr_buffer.kernel_ptr != 0) { 4479 /* buffer->exp_id : all instances to be removed later once the driver change 4480 * is completed. See patch #5758 for reference */ 4481 buffer->exp_id = 0; 4482 buffer->driver_cookie = ddr_buffer.cookie_ptr; 4483 buffer->timing_data = ddr_buffer.timing_data; 4484 4485 if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) || 4486 (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) { 4487 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick; 4488 } 4489 4490 switch (buf_type) { 4491 case IA_CSS_BUFFER_TYPE_INPUT_FRAME: 4492 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: 4493 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: 4494 if ((pipe) && (pipe->stop_requested == true)) { 4495 #if defined(USE_INPUT_SYSTEM_VERSION_2) 4496 /* free mipi frames only for old input system 4497 * for 2401 it is done in ia_css_stream_destroy call 4498 */ 4499 return_err = free_mipi_frames(pipe); 4500 if (return_err != IA_CSS_SUCCESS) { 4501 IA_CSS_LOG("free_mipi_frames() failed"); 4502 IA_CSS_LEAVE_ERR(return_err); 4503 return return_err; 4504 } 4505 #endif 4506 pipe->stop_requested = false; 4507 } 4508 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME: 4509 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME: 4510 frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr); 4511 buffer->data.frame = frame; 4512 buffer->exp_id = ddr_buffer.payload.frame.exp_id; 4513 frame->exp_id = ddr_buffer.payload.frame.exp_id; 4514 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id; 4515 if (ddr_buffer.payload.frame.flashed == 1) 4516 frame->flash_state = 4517 IA_CSS_FRAME_FLASH_STATE_PARTIAL; 4518 if (ddr_buffer.payload.frame.flashed == 2) 4519 frame->flash_state = 4520 IA_CSS_FRAME_FLASH_STATE_FULL; 4521 frame->valid = pipe->num_invalid_frames == 0; 4522 if (!frame->valid) 4523 pipe->num_invalid_frames--; 4524 4525 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) { 4526 #ifdef USE_INPUT_SYSTEM_VERSION_2401 4527 frame->planes.binary.size = frame->data_bytes; 4528 #else 4529 frame->planes.binary.size = 4530 sh_css_sp_get_binary_copy_size(); 4531 #endif 4532 } 4533 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) 4534 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { 4535 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d", 4536 frame->data, frame->isp_config_id, thread_id); 4537 } 4538 #endif 4539 4540 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 4541 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n", 4542 buf_type, buffer->data.frame->data); 4543 4544 break; 4545 case IA_CSS_BUFFER_TYPE_3A_STATISTICS: 4546 buffer->data.stats_3a = 4547 (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr); 4548 buffer->exp_id = ddr_buffer.payload.s3a.exp_id; 4549 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id; 4550 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id; 4551 break; 4552 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS: 4553 buffer->data.stats_dvs = 4554 (struct ia_css_isp_dvs_statistics *) 4555 HOST_ADDRESS(ddr_buffer.kernel_ptr); 4556 buffer->exp_id = ddr_buffer.payload.dis.exp_id; 4557 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id; 4558 break; 4559 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS: 4560 break; 4561 case IA_CSS_BUFFER_TYPE_METADATA: 4562 buffer->data.metadata = 4563 (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr); 4564 buffer->exp_id = ddr_buffer.payload.metadata.exp_id; 4565 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id; 4566 break; 4567 default: 4568 return_err = IA_CSS_ERR_INTERNAL_ERROR; 4569 break; 4570 } 4571 } 4572 } 4573 4574 /* 4575 * Tell the SP which queues are not full, 4576 * by sending the software event. 4577 */ 4578 if (return_err == IA_CSS_SUCCESS) 4579 { 4580 if (!sh_css_sp_is_running()) { 4581 IA_CSS_LOG("SP is not running!"); 4582 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); 4583 /* SP is not running. The queues are not valid */ 4584 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 4585 } 4586 ia_css_bufq_enqueue_psys_event( 4587 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED, 4588 0, 4589 queue_id, 4590 0); 4591 } 4592 IA_CSS_LEAVE("buffer=%p", buffer); 4593 4594 return return_err; 4595 } 4596 4597 /* 4598 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h 4599 * TODO: modify and move it if possible. 4600 * 4601 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC: 4602 * 1) "enum ia_css_event_type" (ia_css_event_public.h) 4603 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h) 4604 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c) 4605 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c) 4606 */ 4607 static enum ia_css_event_type convert_event_sp_to_host_domain[] = { 4608 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */ 4609 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */ 4610 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */ 4611 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */ 4612 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */ 4613 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */ 4614 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */ 4615 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */ 4616 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */ 4617 IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */ 4618 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */ 4619 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */ 4620 IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */ 4621 IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */ 4622 IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */ 4623 IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */ 4624 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */ 4625 }; 4626 4627 enum ia_css_err 4628 ia_css_dequeue_event(struct ia_css_event *event) { 4629 return ia_css_dequeue_psys_event(event); 4630 } 4631 4632 enum ia_css_err 4633 ia_css_dequeue_psys_event(struct ia_css_event *event) { 4634 enum ia_css_pipe_id pipe_id = 0; 4635 u8 payload[4] = {0, 0, 0, 0}; 4636 enum ia_css_err ret_err; 4637 4638 /*TODO: 4639 * a) use generic decoding function , same as the one used by sp. 4640 * b) group decode and dequeue into eventQueue module 4641 * 4642 * We skip the IA_CSS_ENTER logging call 4643 * to avoid flooding the logs when the host application 4644 * uses polling. */ 4645 if (!event) 4646 return IA_CSS_ERR_INVALID_ARGUMENTS; 4647 4648 if (!sh_css_sp_is_running()) 4649 { 4650 /* SP is not running. The queues are not valid */ 4651 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 4652 } 4653 4654 /* dequeue the event (if any) from the psys event queue */ 4655 ret_err = ia_css_bufq_dequeue_psys_event(payload); 4656 if (ret_err != IA_CSS_SUCCESS) 4657 return ret_err; 4658 4659 IA_CSS_LOG("event dequeued from psys event queue"); 4660 4661 /* Tell the SP that we dequeued an event from the event queue. */ 4662 ia_css_bufq_enqueue_psys_event( 4663 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0); 4664 4665 /* Events are decoded into 4 bytes of payload, the first byte 4666 * contains the sp event type. This is converted to a host enum. 4667 * TODO: can this enum conversion be eliminated */ 4668 event->type = convert_event_sp_to_host_domain[payload[0]]; 4669 /* Some sane default values since not all events use all fields. */ 4670 event->pipe = NULL; 4671 event->port = MIPI_PORT0_ID; 4672 event->exp_id = 0; 4673 event->fw_warning = IA_CSS_FW_WARNING_NONE; 4674 event->fw_handle = 0; 4675 event->timer_data = 0; 4676 event->timer_code = 0; 4677 event->timer_subcode = 0; 4678 4679 if (event->type == IA_CSS_EVENT_TYPE_TIMER) 4680 { 4681 /* timer event ??? get the 2nd event and decode the data into the event struct */ 4682 u32 tmp_data; 4683 /* 1st event: LSB 16-bit timer data and code */ 4684 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8)); 4685 event->timer_code = payload[2]; 4686 payload[0] = payload[1] = payload[2] = payload[3] = 0; 4687 ret_err = ia_css_bufq_dequeue_psys_event(payload); 4688 if (ret_err != IA_CSS_SUCCESS) { 4689 /* no 2nd event ??? an error */ 4690 /* Putting IA_CSS_ERROR is resulting in failures in 4691 * Merrifield smoke testing */ 4692 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n"); 4693 return ret_err; 4694 } 4695 ia_css_bufq_enqueue_psys_event( 4696 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0); 4697 event->type = convert_event_sp_to_host_domain[payload[0]]; 4698 /* It's a timer */ 4699 if (event->type == IA_CSS_EVENT_TYPE_TIMER) { 4700 /* 2nd event data: MSB 16-bit timer and subcode */ 4701 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8)); 4702 event->timer_data |= (tmp_data << 16); 4703 event->timer_subcode = payload[2]; 4704 } 4705 /* It's a non timer event. So clear first half of the timer event data. 4706 * If the second part of the TIMER event is not received, we discard 4707 * the first half of the timer data and process the non timer event without 4708 * affecting the flow. So the non timer event falls through 4709 * the code. */ 4710 else { 4711 event->timer_data = 0; 4712 event->timer_code = 0; 4713 event->timer_subcode = 0; 4714 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded"); 4715 } 4716 } 4717 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) 4718 { 4719 event->port = (enum mipi_port_id)payload[1]; 4720 event->exp_id = payload[3]; 4721 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) 4722 { 4723 event->fw_warning = (enum ia_css_fw_warning)payload[1]; 4724 /* exp_id is only available in these warning types */ 4725 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED || 4726 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED) 4727 event->exp_id = payload[3]; 4728 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) 4729 { 4730 event->fw_assert_module_id = payload[1]; /* module */ 4731 event->fw_assert_line_no = (payload[2] << 8) + payload[3]; 4732 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */ 4733 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) 4734 { 4735 /* pipe related events. 4736 * payload[1] contains the pipe_num, 4737 * payload[2] contains the pipe_id. These are different. */ 4738 event->pipe = find_pipe_by_num(payload[1]); 4739 pipe_id = (enum ia_css_pipe_id)payload[2]; 4740 /* Check to see if pipe still exists */ 4741 if (!event->pipe) 4742 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 4743 4744 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) { 4745 /* find the capture pipe that goes with this */ 4746 int i, n; 4747 4748 n = event->pipe->stream->num_pipes; 4749 for (i = 0; i < n; i++) { 4750 struct ia_css_pipe *p = 4751 event->pipe->stream->pipes[i]; 4752 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { 4753 event->pipe = p; 4754 break; 4755 } 4756 } 4757 event->exp_id = payload[3]; 4758 } 4759 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) { 4760 /* payload[3] contains the acc fw handle. */ 4761 u32 stage_num = (uint32_t)payload[3]; 4762 4763 ret_err = ia_css_pipeline_get_fw_from_stage( 4764 &event->pipe->pipeline, 4765 stage_num, 4766 &event->fw_handle); 4767 if (ret_err != IA_CSS_SUCCESS) { 4768 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u", 4769 stage_num); 4770 return ret_err; 4771 } 4772 } 4773 } 4774 4775 if (event->pipe) 4776 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id); 4777 else 4778 IA_CSS_LEAVE("event_id=%d", event->type); 4779 4780 return IA_CSS_SUCCESS; 4781 } 4782 4783 enum ia_css_err 4784 ia_css_dequeue_isys_event(struct ia_css_event *event) { 4785 u8 payload[4] = {0, 0, 0, 0}; 4786 enum ia_css_err err = IA_CSS_SUCCESS; 4787 4788 /* We skip the IA_CSS_ENTER logging call 4789 * to avoid flooding the logs when the host application 4790 * uses polling. */ 4791 if (!event) 4792 return IA_CSS_ERR_INVALID_ARGUMENTS; 4793 4794 if (!sh_css_sp_is_running()) 4795 { 4796 /* SP is not running. The queues are not valid */ 4797 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 4798 } 4799 4800 err = ia_css_bufq_dequeue_isys_event(payload); 4801 if (err != IA_CSS_SUCCESS) 4802 return err; 4803 4804 IA_CSS_LOG("event dequeued from isys event queue"); 4805 4806 /* Update SP state to indicate that element was dequeued. */ 4807 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED); 4808 4809 /* Fill return struct with appropriate info */ 4810 event->type = IA_CSS_EVENT_TYPE_PORT_EOF; 4811 /* EOF events are associated with a CSI port, not with a pipe */ 4812 event->pipe = NULL; 4813 event->port = payload[1]; 4814 event->exp_id = payload[3]; 4815 4816 IA_CSS_LEAVE_ERR(err); 4817 return err; 4818 } 4819 4820 static void 4821 acc_start(struct ia_css_pipe *pipe) 4822 { 4823 assert(pipe); 4824 assert(pipe->stream); 4825 4826 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD, 4827 pipe->stream->config.mode); 4828 } 4829 4830 static enum ia_css_err 4831 sh_css_pipe_start(struct ia_css_stream *stream) { 4832 enum ia_css_err err = IA_CSS_SUCCESS; 4833 4834 struct ia_css_pipe *pipe; 4835 enum ia_css_pipe_id pipe_id; 4836 unsigned int thread_id; 4837 4838 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 4839 4840 if (!stream) 4841 { 4842 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4843 return IA_CSS_ERR_INVALID_ARGUMENTS; 4844 } 4845 pipe = stream->last_pipe; 4846 if (!pipe) 4847 { 4848 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 4849 return IA_CSS_ERR_INVALID_ARGUMENTS; 4850 } 4851 4852 pipe_id = pipe->mode; 4853 4854 if (stream->started == true) 4855 { 4856 IA_CSS_WARNING("Cannot start stream that is already started"); 4857 IA_CSS_LEAVE_ERR(err); 4858 return err; 4859 } 4860 4861 pipe->stop_requested = false; 4862 4863 switch (pipe_id) 4864 { 4865 case IA_CSS_PIPE_ID_PREVIEW: 4866 err = preview_start(pipe); 4867 break; 4868 case IA_CSS_PIPE_ID_VIDEO: 4869 err = video_start(pipe); 4870 break; 4871 case IA_CSS_PIPE_ID_CAPTURE: 4872 err = capture_start(pipe); 4873 break; 4874 case IA_CSS_PIPE_ID_YUVPP: 4875 err = yuvpp_start(pipe); 4876 break; 4877 case IA_CSS_PIPE_ID_ACC: 4878 acc_start(pipe); 4879 break; 4880 default: 4881 err = IA_CSS_ERR_INVALID_ARGUMENTS; 4882 } 4883 /* DH regular multi pipe - not continuous mode: start the next pipes too */ 4884 if (!stream->config.continuous) 4885 { 4886 int i; 4887 4888 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err ; i++) { 4889 switch (stream->pipes[i]->mode) { 4890 case IA_CSS_PIPE_ID_PREVIEW: 4891 stream->pipes[i]->stop_requested = false; 4892 err = preview_start(stream->pipes[i]); 4893 break; 4894 case IA_CSS_PIPE_ID_VIDEO: 4895 stream->pipes[i]->stop_requested = false; 4896 err = video_start(stream->pipes[i]); 4897 break; 4898 case IA_CSS_PIPE_ID_CAPTURE: 4899 stream->pipes[i]->stop_requested = false; 4900 err = capture_start(stream->pipes[i]); 4901 break; 4902 case IA_CSS_PIPE_ID_YUVPP: 4903 stream->pipes[i]->stop_requested = false; 4904 err = yuvpp_start(stream->pipes[i]); 4905 break; 4906 case IA_CSS_PIPE_ID_ACC: 4907 stream->pipes[i]->stop_requested = false; 4908 acc_start(stream->pipes[i]); 4909 break; 4910 default: 4911 err = IA_CSS_ERR_INVALID_ARGUMENTS; 4912 } 4913 } 4914 } 4915 if (err != IA_CSS_SUCCESS) 4916 { 4917 IA_CSS_LEAVE_ERR_PRIVATE(err); 4918 return err; 4919 } 4920 4921 /* Force ISP parameter calculation after a mode change 4922 * Acceleration API examples pass NULL for stream but they 4923 * don't use ISP parameters anyway. So this should be okay. 4924 * The SP binary (jpeg) copy does not use any parameters. 4925 */ 4926 if (!copy_on_sp(pipe)) 4927 { 4928 sh_css_invalidate_params(stream); 4929 err = sh_css_param_update_isp_params(pipe, 4930 stream->isp_params_configs, true, NULL); 4931 if (err != IA_CSS_SUCCESS) { 4932 IA_CSS_LEAVE_ERR_PRIVATE(err); 4933 return err; 4934 } 4935 } 4936 4937 ia_css_debug_pipe_graph_dump_epilogue(); 4938 4939 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 4940 4941 if (!sh_css_sp_is_running()) 4942 { 4943 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); 4944 /* SP is not running. The queues are not valid */ 4945 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 4946 } 4947 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM, 4948 (uint8_t)thread_id, 0, 0); 4949 4950 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */ 4951 if (!stream->config.continuous) 4952 { 4953 int i; 4954 4955 for (i = 1; i < stream->num_pipes; i++) { 4956 ia_css_pipeline_get_sp_thread_id( 4957 ia_css_pipe_get_pipe_num(stream->pipes[i]), 4958 &thread_id); 4959 ia_css_bufq_enqueue_psys_event( 4960 IA_CSS_PSYS_SW_EVENT_START_STREAM, 4961 (uint8_t)thread_id, 0, 0); 4962 } 4963 } 4964 4965 /* in case of continuous capture mode, we also start capture thread and copy thread*/ 4966 if (pipe->stream->config.continuous) 4967 { 4968 struct ia_css_pipe *copy_pipe = NULL; 4969 4970 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 4971 copy_pipe = pipe->pipe_settings.preview.copy_pipe; 4972 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) 4973 copy_pipe = pipe->pipe_settings.video.copy_pipe; 4974 4975 if (!copy_pipe) { 4976 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); 4977 return IA_CSS_ERR_INTERNAL_ERROR; 4978 } 4979 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe), 4980 &thread_id); 4981 /* by the time we reach here q is initialized and handle is available.*/ 4982 ia_css_bufq_enqueue_psys_event( 4983 IA_CSS_PSYS_SW_EVENT_START_STREAM, 4984 (uint8_t)thread_id, 0, 0); 4985 } 4986 if (pipe->stream->cont_capt) 4987 { 4988 struct ia_css_pipe *capture_pipe = NULL; 4989 4990 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 4991 capture_pipe = pipe->pipe_settings.preview.capture_pipe; 4992 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) 4993 capture_pipe = pipe->pipe_settings.video.capture_pipe; 4994 4995 if (!capture_pipe) { 4996 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); 4997 return IA_CSS_ERR_INTERNAL_ERROR; 4998 } 4999 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), 5000 &thread_id); 5001 /* by the time we reach here q is initialized and handle is available.*/ 5002 ia_css_bufq_enqueue_psys_event( 5003 IA_CSS_PSYS_SW_EVENT_START_STREAM, 5004 (uint8_t)thread_id, 0, 0); 5005 } 5006 5007 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */ 5008 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 5009 { 5010 struct ia_css_pipe *acc_pipe = NULL; 5011 5012 acc_pipe = pipe->pipe_settings.preview.acc_pipe; 5013 5014 if (acc_pipe) { 5015 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe), 5016 &thread_id); 5017 /* by the time we reach here q is initialized and handle is available.*/ 5018 ia_css_bufq_enqueue_psys_event( 5019 IA_CSS_PSYS_SW_EVENT_START_STREAM, 5020 (uint8_t)thread_id, 0, 0); 5021 } 5022 } 5023 5024 stream->started = true; 5025 5026 IA_CSS_LEAVE_ERR_PRIVATE(err); 5027 return err; 5028 } 5029 5030 /* ISP2400 */ 5031 void 5032 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview) 5033 { 5034 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5035 "sh_css_enable_cont_capt() enter: enable=%d\n", enable); 5036 //my_css.cont_capt = enable; 5037 my_css.stop_copy_preview = stop_copy_preview; 5038 } 5039 5040 bool 5041 sh_css_continuous_is_enabled(uint8_t pipe_num) 5042 { 5043 struct ia_css_pipe *pipe; 5044 bool continuous; 5045 5046 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5047 "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num); 5048 5049 pipe = find_pipe_by_num(pipe_num); 5050 continuous = pipe && pipe->stream->config.continuous; 5051 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5052 "sh_css_continuous_is_enabled() leave: enable=%d\n", 5053 continuous); 5054 return continuous; 5055 } 5056 5057 /* ISP2400 */ 5058 enum ia_css_err 5059 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, 5060 int *buffer_depth) { 5061 if (!buffer_depth) 5062 return IA_CSS_ERR_INVALID_ARGUMENTS; 5063 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n"); 5064 (void)stream; 5065 *buffer_depth = NUM_CONTINUOUS_FRAMES; 5066 return IA_CSS_SUCCESS; 5067 } 5068 5069 enum ia_css_err 5070 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) { 5071 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth); 5072 (void)stream; 5073 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1) 5074 return IA_CSS_ERR_INVALID_ARGUMENTS; 5075 /* ok, value allowed */ 5076 stream->config.target_num_cont_raw_buf = buffer_depth; 5077 /* TODO: check what to regarding initialization */ 5078 return IA_CSS_SUCCESS; 5079 } 5080 5081 /* ISP2401 */ 5082 enum ia_css_err 5083 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, 5084 int *buffer_depth) { 5085 if (!buffer_depth) 5086 return IA_CSS_ERR_INVALID_ARGUMENTS; 5087 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n"); 5088 (void)stream; 5089 *buffer_depth = stream->config.target_num_cont_raw_buf; 5090 return IA_CSS_SUCCESS; 5091 } 5092 5093 /* 5094 * @brief Stop all "ia_css_pipe" instances in the target 5095 * "ia_css_stream" instance. 5096 * 5097 * Refer to "Local prototypes" for more info. 5098 */ 5099 /* ISP2401 */ 5100 static enum ia_css_err 5101 sh_css_pipes_stop(struct ia_css_stream *stream) 5102 { 5103 enum ia_css_err err = IA_CSS_SUCCESS; 5104 struct ia_css_pipe *main_pipe; 5105 enum ia_css_pipe_id main_pipe_id; 5106 int i; 5107 5108 assert(stream); 5109 if (!stream) 5110 { 5111 IA_CSS_LOG("stream does NOT exist!"); 5112 err = IA_CSS_ERR_INTERNAL_ERROR; 5113 goto ERR; 5114 } 5115 5116 main_pipe = stream->last_pipe; 5117 assert(main_pipe); 5118 if (!main_pipe) 5119 { 5120 IA_CSS_LOG("main_pipe does NOT exist!"); 5121 err = IA_CSS_ERR_INTERNAL_ERROR; 5122 goto ERR; 5123 } 5124 5125 main_pipe_id = main_pipe->mode; 5126 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id); 5127 5128 /* 5129 * Stop all "ia_css_pipe" instances in this target 5130 * "ia_css_stream" instance. 5131 */ 5132 for (i = 0; i < stream->num_pipes; i++) 5133 { 5134 /* send the "stop" request to the "ia_css_pipe" instance */ 5135 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", 5136 stream->pipes[i]->pipeline.pipe_id); 5137 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline); 5138 5139 /* 5140 * Exit this loop if "ia_css_pipeline_request_stop()" 5141 * returns the error code. 5142 * 5143 * The error code would be generated in the following 5144 * two cases: 5145 * (1) The Scalar Processor has already been stopped. 5146 * (2) The "Host->SP" event queue is full. 5147 * 5148 * As the convention of using CSS API 2.0/2.1, such CSS 5149 * error code would be propogated from the CSS-internal 5150 * API returned value to the CSS API returned value. Then 5151 * the CSS driver should capture these error code and 5152 * handle it in the driver exception handling mechanism. 5153 */ 5154 if (err != IA_CSS_SUCCESS) { 5155 goto ERR; 5156 } 5157 } 5158 5159 /* 5160 * In the CSS firmware use scenario "Continuous Preview" 5161 * as well as "Continuous Video", the "ia_css_pipe" instance 5162 * "Copy Pipe" is activated. This "Copy Pipe" is private to 5163 * the CSS firmware so that it is not listed in the target 5164 * "ia_css_stream" instance. 5165 * 5166 * We need to stop this "Copy Pipe", as well. 5167 */ 5168 if (main_pipe->stream->config.continuous) 5169 { 5170 struct ia_css_pipe *copy_pipe = NULL; 5171 5172 /* get the reference to "Copy Pipe" */ 5173 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW) 5174 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 5175 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO) 5176 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 5177 5178 /* return the error code if "Copy Pipe" does NOT exist */ 5179 assert(copy_pipe); 5180 if (!copy_pipe) { 5181 IA_CSS_LOG("Copy Pipe does NOT exist!"); 5182 err = IA_CSS_ERR_INTERNAL_ERROR; 5183 goto ERR; 5184 } 5185 5186 /* send the "stop" request to "Copy Pipe" */ 5187 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", 5188 copy_pipe->pipeline.pipe_id); 5189 err = ia_css_pipeline_request_stop(©_pipe->pipeline); 5190 } 5191 5192 ERR: 5193 IA_CSS_LEAVE_ERR_PRIVATE(err); 5194 return err; 5195 } 5196 5197 /* 5198 * @brief Check if all "ia_css_pipe" instances in the target 5199 * "ia_css_stream" instance have stopped. 5200 * 5201 * Refer to "Local prototypes" for more info. 5202 */ 5203 /* ISP2401 */ 5204 static bool 5205 sh_css_pipes_have_stopped(struct ia_css_stream *stream) 5206 { 5207 bool rval = true; 5208 5209 struct ia_css_pipe *main_pipe; 5210 enum ia_css_pipe_id main_pipe_id; 5211 5212 int i; 5213 5214 assert(stream); 5215 if (!stream) { 5216 IA_CSS_LOG("stream does NOT exist!"); 5217 rval = false; 5218 goto RET; 5219 } 5220 5221 main_pipe = stream->last_pipe; 5222 assert(main_pipe); 5223 5224 if (!main_pipe) { 5225 IA_CSS_LOG("main_pipe does NOT exist!"); 5226 rval = false; 5227 goto RET; 5228 } 5229 5230 main_pipe_id = main_pipe->mode; 5231 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id); 5232 5233 /* 5234 * Check if every "ia_css_pipe" instance in this target 5235 * "ia_css_stream" instance has stopped. 5236 */ 5237 for (i = 0; i < stream->num_pipes; i++) { 5238 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline); 5239 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d", 5240 stream->pipes[i]->pipeline.pipe_id, 5241 rval); 5242 } 5243 5244 /* 5245 * In the CSS firmware use scenario "Continuous Preview" 5246 * as well as "Continuous Video", the "ia_css_pipe" instance 5247 * "Copy Pipe" is activated. This "Copy Pipe" is private to 5248 * the CSS firmware so that it is not listed in the target 5249 * "ia_css_stream" instance. 5250 * 5251 * We need to check if this "Copy Pipe" has stopped, as well. 5252 */ 5253 if (main_pipe->stream->config.continuous) { 5254 struct ia_css_pipe *copy_pipe = NULL; 5255 5256 /* get the reference to "Copy Pipe" */ 5257 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW) 5258 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 5259 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO) 5260 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 5261 5262 /* return if "Copy Pipe" does NOT exist */ 5263 assert(copy_pipe); 5264 if (!copy_pipe) { 5265 IA_CSS_LOG("Copy Pipe does NOT exist!"); 5266 5267 rval = false; 5268 goto RET; 5269 } 5270 5271 /* check if "Copy Pipe" has stopped or not */ 5272 rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline); 5273 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d", 5274 copy_pipe->pipeline.pipe_id, 5275 rval); 5276 } 5277 5278 RET: 5279 IA_CSS_LEAVE_PRIVATE("rval=%d", rval); 5280 return rval; 5281 } 5282 5283 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) 5284 unsigned int 5285 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx) 5286 { 5287 OP___assert(port < N_CSI_PORTS); 5288 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT); 5289 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5290 "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n", 5291 port, idx, my_css.mipi_sizes_for_check[port][idx]); 5292 return my_css.mipi_sizes_for_check[port][idx]; 5293 } 5294 #endif 5295 5296 static enum ia_css_err sh_css_pipe_configure_output( 5297 struct ia_css_pipe *pipe, 5298 unsigned int width, 5299 unsigned int height, 5300 unsigned int padded_width, 5301 enum ia_css_frame_format format, 5302 unsigned int idx) 5303 { 5304 enum ia_css_err err = IA_CSS_SUCCESS; 5305 5306 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, padded width = %d, format = %d, idx = %d", 5307 pipe, width, height, padded_width, format, idx); 5308 if (!pipe) { 5309 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 5310 return IA_CSS_ERR_INVALID_ARGUMENTS; 5311 } 5312 5313 err = ia_css_util_check_res(width, height); 5314 if (err != IA_CSS_SUCCESS) { 5315 IA_CSS_LEAVE_ERR_PRIVATE(err); 5316 return err; 5317 } 5318 if (pipe->output_info[idx].res.width != width || 5319 pipe->output_info[idx].res.height != height || 5320 pipe->output_info[idx].format != format) { 5321 ia_css_frame_info_init( 5322 &pipe->output_info[idx], 5323 width, 5324 height, 5325 format, 5326 padded_width); 5327 } 5328 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 5329 return IA_CSS_SUCCESS; 5330 } 5331 5332 static enum ia_css_err 5333 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe, 5334 struct ia_css_shading_info *shading_info, 5335 struct ia_css_pipe_config *pipe_config) 5336 { 5337 enum ia_css_err err = IA_CSS_SUCCESS; 5338 struct ia_css_binary *binary = NULL; 5339 5340 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5341 "sh_css_pipe_get_shading_info() enter:\n"); 5342 5343 binary = ia_css_pipe_get_shading_correction_binary(pipe); 5344 5345 if (binary) 5346 { 5347 err = ia_css_binary_get_shading_info(binary, 5348 IA_CSS_SHADING_CORRECTION_TYPE_1, 5349 pipe->required_bds_factor, 5350 (const struct ia_css_stream_config *)&pipe->stream->config, 5351 shading_info, pipe_config); 5352 5353 /* Other function calls can be added here when other shading correction types will be added 5354 * in the future. 5355 */ 5356 } else 5357 { 5358 /* When the pipe does not have a binary which has the shading 5359 * correction, this function does not need to fill the shading 5360 * information. It is not a error case, and then 5361 * this function should return IA_CSS_SUCCESS. 5362 */ 5363 memset(shading_info, 0, sizeof(*shading_info)); 5364 } 5365 return err; 5366 } 5367 5368 static enum ia_css_err 5369 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe, 5370 struct ia_css_grid_info *info) { 5371 enum ia_css_err err = IA_CSS_SUCCESS; 5372 struct ia_css_binary *binary = NULL; 5373 5374 assert(pipe); 5375 assert(info); 5376 5377 IA_CSS_ENTER_PRIVATE(""); 5378 5379 binary = ia_css_pipe_get_s3a_binary(pipe); 5380 5381 if (binary) 5382 { 5383 err = ia_css_binary_3a_grid_info(binary, info, pipe); 5384 if (err != IA_CSS_SUCCESS) 5385 goto ERR; 5386 } else 5387 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid)); 5388 5389 binary = ia_css_pipe_get_sdis_binary(pipe); 5390 5391 if (binary) 5392 { 5393 ia_css_binary_dvs_grid_info(binary, info, pipe); 5394 ia_css_binary_dvs_stat_grid_info(binary, info, pipe); 5395 } else 5396 { 5397 memset(&info->dvs_grid.dvs_grid_info, 0, 5398 sizeof(info->dvs_grid.dvs_grid_info)); 5399 memset(&info->dvs_grid.dvs_stat_grid_info, 0, 5400 sizeof(info->dvs_grid.dvs_stat_grid_info)); 5401 } 5402 5403 if (binary) 5404 { 5405 /* copy pipe does not have ISP binary*/ 5406 info->isp_in_width = binary->internal_frame_info.res.width; 5407 info->isp_in_height = binary->internal_frame_info.res.height; 5408 } 5409 5410 #if defined(HAS_VAMEM_VERSION_2) 5411 info->vamem_type = IA_CSS_VAMEM_TYPE_2; 5412 #elif defined(HAS_VAMEM_VERSION_1) 5413 info->vamem_type = IA_CSS_VAMEM_TYPE_1; 5414 #else 5415 #error "Unknown VAMEM version" 5416 #endif 5417 5418 ERR : 5419 IA_CSS_LEAVE_ERR_PRIVATE(err); 5420 return err; 5421 } 5422 5423 /* ISP2401 */ 5424 /* 5425 * @brief Check if a format is supported by the pipe. 5426 * 5427 */ 5428 static enum ia_css_err 5429 ia_css_pipe_check_format(struct ia_css_pipe *pipe, 5430 enum ia_css_frame_format format) { 5431 const enum ia_css_frame_format *supported_formats; 5432 int number_of_formats; 5433 int found = 0; 5434 int i; 5435 5436 IA_CSS_ENTER_PRIVATE(""); 5437 5438 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) 5439 { 5440 IA_CSS_ERROR("Pipe or binary info is not set"); 5441 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 5442 return IA_CSS_ERR_INVALID_ARGUMENTS; 5443 } 5444 5445 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats; 5446 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format); 5447 5448 for (i = 0; i < number_of_formats && !found; i++) 5449 { 5450 if (supported_formats[i] == format) { 5451 found = 1; 5452 break; 5453 } 5454 } 5455 if (!found) 5456 { 5457 IA_CSS_ERROR("Requested format is not supported by binary"); 5458 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 5459 return IA_CSS_ERR_INVALID_ARGUMENTS; 5460 } else 5461 { 5462 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 5463 return IA_CSS_SUCCESS; 5464 } 5465 } 5466 5467 static enum ia_css_err load_video_binaries(struct ia_css_pipe *pipe) 5468 { 5469 struct ia_css_frame_info video_in_info, tnr_info, 5470 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info; 5471 bool online; 5472 enum ia_css_err err = IA_CSS_SUCCESS; 5473 bool continuous = pipe->stream->config.continuous; 5474 unsigned int i; 5475 unsigned int num_output_pins; 5476 struct ia_css_frame_info video_bin_out_info; 5477 bool need_scaler = false; 5478 bool vf_res_different_than_output = false; 5479 bool need_vf_pp = false; 5480 int vf_ds_log2; 5481 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video; 5482 5483 IA_CSS_ENTER_PRIVATE(""); 5484 assert(pipe); 5485 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO); 5486 /* we only test the video_binary because offline video doesn't need a 5487 * vf_pp binary and online does not (always use) the copy_binary. 5488 * All are always reset at the same time anyway. 5489 */ 5490 if (mycs->video_binary.info) 5491 return IA_CSS_SUCCESS; 5492 5493 online = pipe->stream->config.online; 5494 pipe_out_info = &pipe->output_info[0]; 5495 pipe_vf_out_info = &pipe->vf_output_info[0]; 5496 5497 assert(pipe_out_info); 5498 5499 /* 5500 * There is no explicit input format requirement for raw or yuv 5501 * What matters is that there is a binary that supports the stream format. 5502 * This is checked in the binary_find(), so no need to check it here 5503 */ 5504 err = ia_css_util_check_input(&pipe->stream->config, false, false); 5505 if (err != IA_CSS_SUCCESS) 5506 return err; 5507 /* cannot have online video and input_mode memory */ 5508 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY) 5509 return IA_CSS_ERR_INVALID_ARGUMENTS; 5510 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 5511 err = ia_css_util_check_vf_out_info(pipe_out_info, 5512 pipe_vf_out_info); 5513 if (err != IA_CSS_SUCCESS) 5514 return err; 5515 } else { 5516 err = ia_css_frame_check_info(pipe_out_info); 5517 if (err != IA_CSS_SUCCESS) 5518 return err; 5519 } 5520 5521 if (pipe->out_yuv_ds_input_info.res.width) 5522 video_bin_out_info = pipe->out_yuv_ds_input_info; 5523 else 5524 video_bin_out_info = *pipe_out_info; 5525 5526 /* Video */ 5527 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 5528 video_vf_info = pipe_vf_out_info; 5529 vf_res_different_than_output = (video_vf_info->res.width != 5530 video_bin_out_info.res.width) || 5531 (video_vf_info->res.height != video_bin_out_info.res.height); 5532 } else { 5533 video_vf_info = NULL; 5534 } 5535 5536 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res); 5537 5538 /* we build up the pipeline starting at the end */ 5539 /* YUV post-processing if needed */ 5540 if (need_scaler) { 5541 struct ia_css_cas_binary_descr cas_scaler_descr = { }; 5542 5543 /* NV12 is the common format that is supported by both */ 5544 /* yuv_scaler and the video_xx_isp2_min binaries. */ 5545 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12; 5546 5547 err = ia_css_pipe_create_cas_scaler_desc_single_output( 5548 &video_bin_out_info, 5549 pipe_out_info, 5550 NULL, 5551 &cas_scaler_descr); 5552 if (err != IA_CSS_SUCCESS) 5553 return err; 5554 mycs->num_yuv_scaler = cas_scaler_descr.num_stage; 5555 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * 5556 sizeof(struct ia_css_binary), GFP_KERNEL); 5557 if (!mycs->yuv_scaler_binary) { 5558 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 5559 return err; 5560 } 5561 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage 5562 * sizeof(bool), GFP_KERNEL); 5563 if (!mycs->is_output_stage) { 5564 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 5565 return err; 5566 } 5567 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 5568 struct ia_css_binary_descr yuv_scaler_descr; 5569 5570 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 5571 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 5572 &yuv_scaler_descr, &cas_scaler_descr.in_info[i], 5573 &cas_scaler_descr.out_info[i], 5574 &cas_scaler_descr.internal_out_info[i], 5575 &cas_scaler_descr.vf_info[i]); 5576 err = ia_css_binary_find(&yuv_scaler_descr, 5577 &mycs->yuv_scaler_binary[i]); 5578 if (err != IA_CSS_SUCCESS) { 5579 kfree(mycs->is_output_stage); 5580 mycs->is_output_stage = NULL; 5581 return err; 5582 } 5583 } 5584 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 5585 } 5586 5587 { 5588 struct ia_css_binary_descr video_descr; 5589 enum ia_css_frame_format vf_info_format; 5590 5591 err = ia_css_pipe_get_video_binarydesc(pipe, 5592 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info, 5593 video_vf_info, 5594 pipe->stream->config.left_padding); 5595 if (err != IA_CSS_SUCCESS) 5596 return err; 5597 5598 /* In the case where video_vf_info is not NULL, this allows 5599 * us to find a potential video library with desired vf format. 5600 * If success, no vf_pp binary is needed. 5601 * If failed, we will look up video binary with YUV_LINE vf format 5602 */ 5603 err = ia_css_binary_find(&video_descr, 5604 &mycs->video_binary); 5605 5606 if (err != IA_CSS_SUCCESS) { 5607 if (video_vf_info) { 5608 /* This will do another video binary lookup later for YUV_LINE format*/ 5609 need_vf_pp = true; 5610 } else 5611 return err; 5612 } else if (video_vf_info) { 5613 /* The first video binary lookup is successful, but we may 5614 * still need vf_pp binary based on additiona check */ 5615 num_output_pins = mycs->video_binary.info->num_output_pins; 5616 vf_ds_log2 = mycs->video_binary.vf_downscale_log2; 5617 5618 /* If the binary has dual output pins, we need vf_pp if the resolution 5619 * is different. */ 5620 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output); 5621 5622 /* If the binary has single output pin, we need vf_pp if additional 5623 * scaling is needed for vf */ 5624 need_vf_pp |= ((num_output_pins == 1) && 5625 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) || 5626 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height))); 5627 } 5628 5629 if (need_vf_pp) { 5630 /* save the current vf_info format for restoration later */ 5631 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5632 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n"); 5633 5634 vf_info_format = video_vf_info->format; 5635 5636 if (!pipe->config.enable_vfpp_bci) 5637 ia_css_frame_info_set_format(video_vf_info, 5638 IA_CSS_FRAME_FORMAT_YUV_LINE); 5639 5640 ia_css_binary_destroy_isp_parameters(&mycs->video_binary); 5641 5642 err = ia_css_binary_find(&video_descr, 5643 &mycs->video_binary); 5644 5645 /* restore original vf_info format */ 5646 ia_css_frame_info_set_format(video_vf_info, 5647 vf_info_format); 5648 if (err != IA_CSS_SUCCESS) 5649 return err; 5650 } 5651 } 5652 5653 /* If a video binary does not use a ref_frame, we set the frame delay 5654 * to 0. This is the case for the 1-stage low-power video binary. */ 5655 if (!mycs->video_binary.info->sp.enable.ref_frame) 5656 pipe->dvs_frame_delay = 0; 5657 5658 /* The delay latency determines the number of invalid frames after 5659 * a stream is started. */ 5660 pipe->num_invalid_frames = pipe->dvs_frame_delay; 5661 pipe->info.num_invalid_frames = pipe->num_invalid_frames; 5662 5663 /* Viewfinder frames also decrement num_invalid_frames. If the pipe 5664 * outputs a viewfinder output, then we need double the number of 5665 * invalid frames */ 5666 if (video_vf_info) 5667 pipe->num_invalid_frames *= 2; 5668 5669 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 5670 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n", 5671 pipe->num_invalid_frames, pipe->dvs_frame_delay); 5672 5673 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */ 5674 #if !defined(USE_INPUT_SYSTEM_VERSION_2401) 5675 /* Copy */ 5676 if (!online && !continuous) { 5677 /* TODO: what exactly needs doing, prepend the copy binary to 5678 * video base this only on !online? 5679 */ 5680 err = load_copy_binary(pipe, 5681 &mycs->copy_binary, 5682 &mycs->video_binary); 5683 if (err != IA_CSS_SUCCESS) 5684 return err; 5685 } 5686 #else 5687 (void)continuous; 5688 #endif 5689 5690 #if !defined(HAS_OUTPUT_SYSTEM) 5691 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) { 5692 struct ia_css_binary_descr vf_pp_descr; 5693 5694 if (mycs->video_binary.vf_frame_info.format 5695 == IA_CSS_FRAME_FORMAT_YUV_LINE) { 5696 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr, 5697 &mycs->video_binary.vf_frame_info, 5698 pipe_vf_out_info); 5699 } else { 5700 /* output from main binary is not yuv line. currently this is 5701 * possible only when bci is enabled on vfpp output */ 5702 assert(pipe->config.enable_vfpp_bci == true); 5703 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr, 5704 &mycs->video_binary.vf_frame_info, 5705 pipe_vf_out_info, NULL, NULL); 5706 } 5707 5708 err = ia_css_binary_find(&vf_pp_descr, 5709 &mycs->vf_pp_binary); 5710 if (err != IA_CSS_SUCCESS) 5711 return err; 5712 } 5713 #endif 5714 5715 err = allocate_delay_frames(pipe); 5716 5717 if (err != IA_CSS_SUCCESS) 5718 return err; 5719 5720 if (mycs->video_binary.info->sp.enable.block_output) { 5721 unsigned int tnr_width; 5722 unsigned int tnr_height; 5723 5724 tnr_info = mycs->video_binary.out_frame_info[0]; 5725 5726 if (atomisp_hw_is_isp2401) { 5727 /* Select resolution for TNR. If 5728 * output_system_in_resolution(GDC_out_resolution) is 5729 * being used, then select that as it will also be in resolution for 5730 * TNR. At present, it only make sense for Skycam */ 5731 if (pipe->config.output_system_in_res.width && 5732 pipe->config.output_system_in_res.height) { 5733 tnr_width = pipe->config.output_system_in_res.width; 5734 tnr_height = pipe->config.output_system_in_res.height; 5735 } else { 5736 tnr_width = tnr_info.res.width; 5737 tnr_height = tnr_info.res.height; 5738 } 5739 5740 /* Make tnr reference buffers output block width(in pix) align */ 5741 tnr_info.res.width = CEIL_MUL(tnr_width, 5742 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY)); 5743 tnr_info.padded_width = tnr_info.res.width; 5744 } else { 5745 tnr_height = tnr_info.res.height; 5746 } 5747 5748 /* Make tnr reference buffers output block height align */ 5749 tnr_info.res.height = CEIL_MUL(tnr_height, 5750 mycs->video_binary.info->sp.block.output_block_height); 5751 } else { 5752 tnr_info = mycs->video_binary.internal_frame_info; 5753 } 5754 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE; 5755 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH; 5756 5757 for (i = 0; i < NUM_TNR_FRAMES; i++) { 5758 if (mycs->tnr_frames[i]) { 5759 ia_css_frame_free(mycs->tnr_frames[i]); 5760 mycs->tnr_frames[i] = NULL; 5761 } 5762 err = ia_css_frame_allocate_from_info( 5763 &mycs->tnr_frames[i], 5764 &tnr_info); 5765 if (err != IA_CSS_SUCCESS) 5766 return err; 5767 } 5768 IA_CSS_LEAVE_PRIVATE(""); 5769 return IA_CSS_SUCCESS; 5770 } 5771 5772 static enum ia_css_err 5773 unload_video_binaries(struct ia_css_pipe *pipe) { 5774 unsigned int i; 5775 5776 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 5777 5778 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) 5779 { 5780 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 5781 return IA_CSS_ERR_INVALID_ARGUMENTS; 5782 } 5783 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary); 5784 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary); 5785 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary); 5786 5787 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++) 5788 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]); 5789 5790 kfree(pipe->pipe_settings.video.is_output_stage); 5791 pipe->pipe_settings.video.is_output_stage = NULL; 5792 kfree(pipe->pipe_settings.video.yuv_scaler_binary); 5793 pipe->pipe_settings.video.yuv_scaler_binary = NULL; 5794 5795 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 5796 return IA_CSS_SUCCESS; 5797 } 5798 5799 static enum ia_css_err video_start(struct ia_css_pipe *pipe) 5800 { 5801 struct ia_css_binary *copy_binary; 5802 enum ia_css_err err = IA_CSS_SUCCESS; 5803 struct ia_css_pipe *copy_pipe, *capture_pipe; 5804 enum sh_css_pipe_config_override copy_ovrd; 5805 enum ia_css_input_mode video_pipe_input_mode; 5806 5807 const struct ia_css_coordinate *coord = NULL; 5808 const struct ia_css_isp_parameters *params = NULL; 5809 5810 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 5811 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { 5812 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 5813 return IA_CSS_ERR_INVALID_ARGUMENTS; 5814 } 5815 5816 video_pipe_input_mode = pipe->stream->config.mode; 5817 5818 copy_pipe = pipe->pipe_settings.video.copy_pipe; 5819 capture_pipe = pipe->pipe_settings.video.capture_pipe; 5820 5821 copy_binary = &pipe->pipe_settings.video.copy_binary; 5822 5823 sh_css_metrics_start_frame(); 5824 5825 /* multi stream video needs mipi buffers */ 5826 5827 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 5828 err = send_mipi_frames(pipe); 5829 if (err != IA_CSS_SUCCESS) 5830 return err; 5831 #endif 5832 5833 send_raw_frames(pipe); 5834 { 5835 unsigned int thread_id; 5836 5837 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 5838 copy_ovrd = 1 << thread_id; 5839 5840 if (pipe->stream->cont_capt) { 5841 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), 5842 &thread_id); 5843 copy_ovrd |= 1 << thread_id; 5844 } 5845 } 5846 5847 if (atomisp_hw_is_isp2401) { 5848 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl; 5849 params = pipe->stream->isp_params_configs; 5850 } 5851 5852 /* Construct and load the copy pipe */ 5853 if (pipe->stream->config.continuous) { 5854 sh_css_sp_init_pipeline(©_pipe->pipeline, 5855 IA_CSS_PIPE_ID_COPY, 5856 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe), 5857 false, 5858 pipe->stream->config.pixels_per_clock == 2, false, 5859 false, pipe->required_bds_factor, 5860 copy_ovrd, 5861 pipe->stream->config.mode, 5862 &pipe->stream->config.metadata_config, 5863 &pipe->stream->info.metadata_info, 5864 #if !defined(HAS_NO_INPUT_SYSTEM) 5865 pipe->stream->config.source.port.port, 5866 #endif 5867 coord, 5868 params); 5869 5870 /* make the video pipe start with mem mode input, copy handles 5871 the actual mode */ 5872 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; 5873 } 5874 5875 /* Construct and load the capture pipe */ 5876 if (pipe->stream->cont_capt) { 5877 sh_css_sp_init_pipeline(&capture_pipe->pipeline, 5878 IA_CSS_PIPE_ID_CAPTURE, 5879 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe), 5880 capture_pipe->config.default_capture_config.enable_xnr != 0, 5881 capture_pipe->stream->config.pixels_per_clock == 2, 5882 true, /* continuous */ 5883 false, /* offline */ 5884 capture_pipe->required_bds_factor, 5885 0, 5886 IA_CSS_INPUT_MODE_MEMORY, 5887 &pipe->stream->config.metadata_config, 5888 &pipe->stream->info.metadata_info, 5889 #if !defined(HAS_NO_INPUT_SYSTEM) 5890 (enum mipi_port_id)0, 5891 #endif 5892 coord, 5893 params); 5894 } 5895 5896 start_pipe(pipe, copy_ovrd, video_pipe_input_mode); 5897 5898 IA_CSS_LEAVE_ERR_PRIVATE(err); 5899 return err; 5900 } 5901 5902 static 5903 enum ia_css_err sh_css_pipe_get_viewfinder_frame_info( 5904 struct ia_css_pipe *pipe, 5905 struct ia_css_frame_info *info, 5906 unsigned int idx) 5907 { 5908 assert(pipe); 5909 assert(info); 5910 5911 /* We could print the pointer as input arg, and the values as output */ 5912 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5913 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n"); 5914 5915 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE && 5916 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || 5917 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)) 5918 return IA_CSS_ERR_MODE_HAS_NO_VIEWFINDER; 5919 /* offline video does not generate viewfinder output */ 5920 *info = pipe->vf_output_info[idx]; 5921 5922 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5923 "sh_css_pipe_get_viewfinder_frame_info() leave: \ 5924 info.res.width=%d, info.res.height=%d, \ 5925 info.padded_width=%d, info.format=%d, \ 5926 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n", 5927 info->res.width, info->res.height, 5928 info->padded_width, info->format, 5929 info->raw_bit_depth, info->raw_bayer_order); 5930 5931 return IA_CSS_SUCCESS; 5932 } 5933 5934 static enum ia_css_err 5935 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width, 5936 unsigned int height, unsigned int min_width, 5937 enum ia_css_frame_format format, 5938 unsigned int idx) { 5939 enum ia_css_err err = IA_CSS_SUCCESS; 5940 5941 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n", 5942 pipe, width, height, min_width, format, idx); 5943 5944 if (!pipe) 5945 { 5946 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 5947 return IA_CSS_ERR_INVALID_ARGUMENTS; 5948 } 5949 5950 err = ia_css_util_check_res(width, height); 5951 if (err != IA_CSS_SUCCESS) 5952 { 5953 IA_CSS_LEAVE_ERR_PRIVATE(err); 5954 return err; 5955 } 5956 if (pipe->vf_output_info[idx].res.width != width || 5957 pipe->vf_output_info[idx].res.height != height || 5958 pipe->vf_output_info[idx].format != format) 5959 { 5960 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height, 5961 format, min_width); 5962 } 5963 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 5964 return IA_CSS_SUCCESS; 5965 } 5966 5967 static enum ia_css_err load_copy_binaries(struct ia_css_pipe *pipe) 5968 { 5969 enum ia_css_err err = IA_CSS_SUCCESS; 5970 5971 assert(pipe); 5972 IA_CSS_ENTER_PRIVATE(""); 5973 5974 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 5975 pipe->mode == IA_CSS_PIPE_ID_COPY); 5976 if (pipe->pipe_settings.capture.copy_binary.info) 5977 return IA_CSS_SUCCESS; 5978 5979 err = ia_css_frame_check_info(&pipe->output_info[0]); 5980 if (err != IA_CSS_SUCCESS) 5981 goto ERR; 5982 5983 err = verify_copy_out_frame_format(pipe); 5984 if (err != IA_CSS_SUCCESS) 5985 goto ERR; 5986 5987 err = load_copy_binary(pipe, 5988 &pipe->pipe_settings.capture.copy_binary, 5989 NULL); 5990 5991 ERR: 5992 IA_CSS_LEAVE_ERR_PRIVATE(err); 5993 return err; 5994 } 5995 5996 static bool need_capture_pp( 5997 const struct ia_css_pipe *pipe) 5998 { 5999 const struct ia_css_frame_info *out_info = &pipe->output_info[0]; 6000 6001 IA_CSS_ENTER_LEAVE_PRIVATE(""); 6002 assert(pipe); 6003 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 6004 6005 if (atomisp_hw_is_isp2401) { 6006 /* ldc and capture_pp are not supported in the same pipeline */ 6007 if (need_capt_ldc(pipe) == true) 6008 return false; 6009 } 6010 6011 /* determine whether we need to use the capture_pp binary. 6012 * This is needed for: 6013 * 1. XNR or 6014 * 2. Digital Zoom or 6015 * 3. YUV downscaling 6016 */ 6017 if (pipe->out_yuv_ds_input_info.res.width && 6018 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) || 6019 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height))) 6020 return true; 6021 6022 if (pipe->config.default_capture_config.enable_xnr != 0) 6023 return true; 6024 6025 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) || 6026 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) || 6027 pipe->config.enable_dz) 6028 return true; 6029 6030 return false; 6031 } 6032 6033 static bool need_capt_ldc( 6034 const struct ia_css_pipe *pipe) 6035 { 6036 IA_CSS_ENTER_LEAVE_PRIVATE(""); 6037 assert(pipe); 6038 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 6039 return (pipe->extra_config.enable_dvs_6axis) ? true : false; 6040 } 6041 6042 static enum ia_css_err set_num_primary_stages(unsigned int *num, 6043 enum ia_css_pipe_version version) 6044 { 6045 enum ia_css_err err = IA_CSS_SUCCESS; 6046 6047 if (!num) 6048 return IA_CSS_ERR_INVALID_ARGUMENTS; 6049 6050 switch (version) { 6051 case IA_CSS_PIPE_VERSION_2_6_1: 6052 *num = NUM_PRIMARY_HQ_STAGES; 6053 break; 6054 case IA_CSS_PIPE_VERSION_2_2: 6055 case IA_CSS_PIPE_VERSION_1: 6056 *num = NUM_PRIMARY_STAGES; 6057 break; 6058 default: 6059 err = IA_CSS_ERR_INVALID_ARGUMENTS; 6060 break; 6061 } 6062 6063 return err; 6064 } 6065 6066 static enum ia_css_err load_primary_binaries( 6067 struct ia_css_pipe *pipe) 6068 { 6069 bool online = false; 6070 bool memory = false; 6071 bool continuous = false; 6072 bool need_pp = false; 6073 bool need_isp_copy_binary = false; 6074 bool need_ldc = false; 6075 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6076 bool sensor = false; 6077 #endif 6078 struct ia_css_frame_info prim_in_info, 6079 prim_out_info, 6080 capt_pp_out_info, vf_info, 6081 *vf_pp_in_info, *pipe_out_info, 6082 *pipe_vf_out_info, *capt_pp_in_info, 6083 capt_ldc_out_info; 6084 enum ia_css_err err = IA_CSS_SUCCESS; 6085 struct ia_css_capture_settings *mycs; 6086 unsigned int i; 6087 bool need_extra_yuv_scaler = false; 6088 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES]; 6089 6090 IA_CSS_ENTER_PRIVATE(""); 6091 assert(pipe); 6092 assert(pipe->stream); 6093 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6094 pipe->mode == IA_CSS_PIPE_ID_COPY); 6095 6096 online = pipe->stream->config.online; 6097 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 6098 continuous = pipe->stream->config.continuous; 6099 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6100 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); 6101 #endif 6102 6103 mycs = &pipe->pipe_settings.capture; 6104 pipe_out_info = &pipe->output_info[0]; 6105 pipe_vf_out_info = &pipe->vf_output_info[0]; 6106 6107 if (mycs->primary_binary[0].info) 6108 return IA_CSS_SUCCESS; 6109 6110 err = set_num_primary_stages(&mycs->num_primary_stage, 6111 pipe->config.isp_pipe_version); 6112 if (err != IA_CSS_SUCCESS) { 6113 IA_CSS_LEAVE_ERR_PRIVATE(err); 6114 return err; 6115 } 6116 6117 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 6118 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info); 6119 if (err != IA_CSS_SUCCESS) { 6120 IA_CSS_LEAVE_ERR_PRIVATE(err); 6121 return err; 6122 } 6123 } else { 6124 err = ia_css_frame_check_info(pipe_out_info); 6125 if (err != IA_CSS_SUCCESS) { 6126 IA_CSS_LEAVE_ERR_PRIVATE(err); 6127 return err; 6128 } 6129 } 6130 need_pp = need_capture_pp(pipe); 6131 6132 /* we use the vf output info to get the primary/capture_pp binary 6133 configured for vf_veceven. It will select the closest downscaling 6134 factor. */ 6135 vf_info = *pipe_vf_out_info; 6136 6137 /* 6138 * WARNING: The #if def flag has been added below as a 6139 * temporary solution to solve the problem of enabling the 6140 * view finder in a single binary in a capture flow. The 6141 * vf-pp stage has been removed for Skycam in the solution 6142 * provided. The vf-pp stage should be re-introduced when 6143 * required. This should not be considered as a clean solution. 6144 * Proper investigation should be done to come up with the clean 6145 * solution. 6146 * */ 6147 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); 6148 6149 /* TODO: All this yuv_scaler and capturepp calculation logic 6150 * can be shared later. Capture_pp is also a yuv_scale binary 6151 * with extra XNR funcionality. Therefore, it can be made as the 6152 * first step of the cascade. */ 6153 capt_pp_out_info = pipe->out_yuv_ds_input_info; 6154 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420; 6155 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP; 6156 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP; 6157 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0); 6158 6159 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res, 6160 pipe_out_info->res); 6161 6162 if (need_extra_yuv_scaler) { 6163 struct ia_css_cas_binary_descr cas_scaler_descr = { }; 6164 6165 err = ia_css_pipe_create_cas_scaler_desc_single_output( 6166 &capt_pp_out_info, 6167 pipe_out_info, 6168 NULL, 6169 &cas_scaler_descr); 6170 if (err != IA_CSS_SUCCESS) { 6171 IA_CSS_LEAVE_ERR_PRIVATE(err); 6172 return err; 6173 } 6174 mycs->num_yuv_scaler = cas_scaler_descr.num_stage; 6175 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * 6176 sizeof(struct ia_css_binary), GFP_KERNEL); 6177 if (!mycs->yuv_scaler_binary) { 6178 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 6179 IA_CSS_LEAVE_ERR_PRIVATE(err); 6180 return err; 6181 } 6182 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage * 6183 sizeof(bool), GFP_KERNEL); 6184 if (!mycs->is_output_stage) { 6185 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 6186 IA_CSS_LEAVE_ERR_PRIVATE(err); 6187 return err; 6188 } 6189 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 6190 struct ia_css_binary_descr yuv_scaler_descr; 6191 6192 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 6193 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 6194 &yuv_scaler_descr, &cas_scaler_descr.in_info[i], 6195 &cas_scaler_descr.out_info[i], 6196 &cas_scaler_descr.internal_out_info[i], 6197 &cas_scaler_descr.vf_info[i]); 6198 err = ia_css_binary_find(&yuv_scaler_descr, 6199 &mycs->yuv_scaler_binary[i]); 6200 if (err != IA_CSS_SUCCESS) { 6201 IA_CSS_LEAVE_ERR_PRIVATE(err); 6202 return err; 6203 } 6204 } 6205 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 6206 6207 } else { 6208 capt_pp_out_info = pipe->output_info[0]; 6209 } 6210 6211 /* TODO Do we disable ldc for skycam */ 6212 need_ldc = need_capt_ldc(pipe); 6213 if (atomisp_hw_is_isp2401 && need_ldc) { 6214 /* ldc and capt_pp are not supported in the same pipeline */ 6215 struct ia_css_binary_descr capt_ldc_descr; 6216 6217 ia_css_pipe_get_ldc_binarydesc(pipe, 6218 &capt_ldc_descr, &prim_out_info, 6219 &capt_pp_out_info); 6220 6221 err = ia_css_binary_find(&capt_ldc_descr, 6222 &mycs->capture_ldc_binary); 6223 if (err != IA_CSS_SUCCESS) { 6224 IA_CSS_LEAVE_ERR_PRIVATE(err); 6225 return err; 6226 } 6227 need_pp = 0; 6228 need_ldc = 0; 6229 } 6230 6231 /* we build up the pipeline starting at the end */ 6232 /* Capture post-processing */ 6233 if (need_pp) { 6234 struct ia_css_binary_descr capture_pp_descr; 6235 6236 if (!atomisp_hw_is_isp2401) 6237 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info; 6238 else 6239 capt_pp_in_info = &prim_out_info; 6240 6241 ia_css_pipe_get_capturepp_binarydesc(pipe, 6242 &capture_pp_descr, capt_pp_in_info, 6243 &capt_pp_out_info, &vf_info); 6244 err = ia_css_binary_find(&capture_pp_descr, 6245 &mycs->capture_pp_binary); 6246 if (err != IA_CSS_SUCCESS) { 6247 IA_CSS_LEAVE_ERR_PRIVATE(err); 6248 return err; 6249 } 6250 6251 if (need_ldc) { 6252 struct ia_css_binary_descr capt_ldc_descr; 6253 6254 ia_css_pipe_get_ldc_binarydesc(pipe, 6255 &capt_ldc_descr, &prim_out_info, 6256 &capt_ldc_out_info); 6257 6258 err = ia_css_binary_find(&capt_ldc_descr, 6259 &mycs->capture_ldc_binary); 6260 if (err != IA_CSS_SUCCESS) { 6261 IA_CSS_LEAVE_ERR_PRIVATE(err); 6262 return err; 6263 } 6264 } 6265 } else { 6266 prim_out_info = *pipe_out_info; 6267 } 6268 6269 /* Primary */ 6270 for (i = 0; i < mycs->num_primary_stage; i++) { 6271 struct ia_css_frame_info *local_vf_info = NULL; 6272 6273 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && 6274 (i == mycs->num_primary_stage - 1)) 6275 local_vf_info = &vf_info; 6276 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info, 6277 &prim_out_info, local_vf_info, i); 6278 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]); 6279 if (err != IA_CSS_SUCCESS) { 6280 IA_CSS_LEAVE_ERR_PRIVATE(err); 6281 return err; 6282 } 6283 } 6284 6285 /* Viewfinder post-processing */ 6286 if (need_pp) 6287 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info; 6288 else 6289 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info; 6290 6291 /* 6292 * WARNING: The #if def flag has been added below as a 6293 * temporary solution to solve the problem of enabling the 6294 * view finder in a single binary in a capture flow. The 6295 * vf-pp stage has been removed for Skycam in the solution 6296 * provided. The vf-pp stage should be re-introduced when 6297 * required. Thisshould not be considered as a clean solution. 6298 * Proper * investigation should be done to come up with the clean 6299 * solution. 6300 * */ 6301 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 6302 struct ia_css_binary_descr vf_pp_descr; 6303 6304 ia_css_pipe_get_vfpp_binarydesc(pipe, 6305 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); 6306 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary); 6307 if (err != IA_CSS_SUCCESS) { 6308 IA_CSS_LEAVE_ERR_PRIVATE(err); 6309 return err; 6310 } 6311 } 6312 err = allocate_delay_frames(pipe); 6313 6314 if (err != IA_CSS_SUCCESS) 6315 return err; 6316 6317 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6318 /* When the input system is 2401, only the Direct Sensor Mode 6319 * Offline Capture uses the ISP copy binary. 6320 */ 6321 need_isp_copy_binary = !online && sensor; 6322 #else 6323 need_isp_copy_binary = !online && !continuous && !memory; 6324 #endif 6325 6326 /* ISP Copy */ 6327 if (need_isp_copy_binary) { 6328 err = load_copy_binary(pipe, 6329 &mycs->copy_binary, 6330 &mycs->primary_binary[0]); 6331 if (err != IA_CSS_SUCCESS) { 6332 IA_CSS_LEAVE_ERR_PRIVATE(err); 6333 return err; 6334 } 6335 } 6336 6337 return IA_CSS_SUCCESS; 6338 } 6339 6340 static enum ia_css_err 6341 allocate_delay_frames(struct ia_css_pipe *pipe) { 6342 unsigned int num_delay_frames = 0, i = 0; 6343 unsigned int dvs_frame_delay = 0; 6344 struct ia_css_frame_info ref_info; 6345 enum ia_css_err err = IA_CSS_SUCCESS; 6346 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO; 6347 struct ia_css_frame **delay_frames = NULL; 6348 6349 IA_CSS_ENTER_PRIVATE(""); 6350 6351 if (!pipe) 6352 { 6353 IA_CSS_ERROR("Invalid args - pipe %p", pipe); 6354 return IA_CSS_ERR_INVALID_ARGUMENTS; 6355 } 6356 6357 mode = pipe->mode; 6358 dvs_frame_delay = pipe->dvs_frame_delay; 6359 6360 if (dvs_frame_delay > 0) 6361 num_delay_frames = dvs_frame_delay + 1; 6362 6363 switch (mode) 6364 { 6365 case IA_CSS_PIPE_ID_CAPTURE: { 6366 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture; 6367 (void)mycs_capture; 6368 return err; 6369 } 6370 break; 6371 case IA_CSS_PIPE_ID_VIDEO: { 6372 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video; 6373 6374 ref_info = mycs_video->video_binary.internal_frame_info; 6375 /*The ref frame expects 6376 * 1. Y plane 6377 * 2. UV plane with line interleaving, like below 6378 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) 6379 * 6380 * This format is not YUV420(which has Y, U and V planes). 6381 * Its closer to NV12, except that the UV plane has UV 6382 * interleaving, like UVUVUVUVUVUVUVUVU... 6383 * 6384 * TODO: make this ref_frame format as a separate frame format 6385 */ 6386 ref_info.format = IA_CSS_FRAME_FORMAT_NV12; 6387 delay_frames = mycs_video->delay_frames; 6388 } 6389 break; 6390 case IA_CSS_PIPE_ID_PREVIEW: { 6391 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview; 6392 6393 ref_info = mycs_preview->preview_binary.internal_frame_info; 6394 /*The ref frame expects 6395 * 1. Y plane 6396 * 2. UV plane with line interleaving, like below 6397 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) 6398 * 6399 * This format is not YUV420(which has Y, U and V planes). 6400 * Its closer to NV12, except that the UV plane has UV 6401 * interleaving, like UVUVUVUVUVUVUVUVU... 6402 * 6403 * TODO: make this ref_frame format as a separate frame format 6404 */ 6405 ref_info.format = IA_CSS_FRAME_FORMAT_NV12; 6406 delay_frames = mycs_preview->delay_frames; 6407 } 6408 break; 6409 default: 6410 return IA_CSS_ERR_INVALID_ARGUMENTS; 6411 } 6412 6413 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH; 6414 6415 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES); 6416 for (i = 0; i < num_delay_frames; i++) 6417 { 6418 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info); 6419 if (err != IA_CSS_SUCCESS) 6420 return err; 6421 } 6422 IA_CSS_LEAVE_PRIVATE(""); 6423 return IA_CSS_SUCCESS; 6424 } 6425 6426 static enum ia_css_err load_advanced_binaries( 6427 struct ia_css_pipe *pipe) { 6428 struct ia_css_frame_info pre_in_info, gdc_in_info, 6429 post_in_info, post_out_info, 6430 vf_info, *vf_pp_in_info, *pipe_out_info, 6431 *pipe_vf_out_info; 6432 bool need_pp; 6433 bool need_isp_copy = true; 6434 enum ia_css_err err = IA_CSS_SUCCESS; 6435 6436 IA_CSS_ENTER_PRIVATE(""); 6437 6438 assert(pipe); 6439 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6440 pipe->mode == IA_CSS_PIPE_ID_COPY); 6441 if (pipe->pipe_settings.capture.pre_isp_binary.info) 6442 return IA_CSS_SUCCESS; 6443 pipe_out_info = &pipe->output_info[0]; 6444 pipe_vf_out_info = &pipe->vf_output_info[0]; 6445 6446 vf_info = *pipe_vf_out_info; 6447 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info); 6448 if (err != IA_CSS_SUCCESS) 6449 return err; 6450 need_pp = need_capture_pp(pipe); 6451 6452 ia_css_frame_info_set_format(&vf_info, 6453 IA_CSS_FRAME_FORMAT_YUV_LINE); 6454 6455 /* we build up the pipeline starting at the end */ 6456 /* Capture post-processing */ 6457 if (need_pp) { 6458 struct ia_css_binary_descr capture_pp_descr; 6459 6460 ia_css_pipe_get_capturepp_binarydesc(pipe, 6461 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info); 6462 err = ia_css_binary_find(&capture_pp_descr, 6463 &pipe->pipe_settings.capture.capture_pp_binary); 6464 if (err != IA_CSS_SUCCESS) 6465 return err; 6466 } else { 6467 post_out_info = *pipe_out_info; 6468 } 6469 6470 /* Post-gdc */ 6471 { 6472 struct ia_css_binary_descr post_gdc_descr; 6473 6474 ia_css_pipe_get_post_gdc_binarydesc(pipe, 6475 &post_gdc_descr, &post_in_info, &post_out_info, &vf_info); 6476 err = ia_css_binary_find(&post_gdc_descr, 6477 &pipe->pipe_settings.capture.post_isp_binary); 6478 if (err != IA_CSS_SUCCESS) 6479 return err; 6480 } 6481 6482 /* Gdc */ 6483 { 6484 struct ia_css_binary_descr gdc_descr; 6485 6486 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info, 6487 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); 6488 err = ia_css_binary_find(&gdc_descr, 6489 &pipe->pipe_settings.capture.anr_gdc_binary); 6490 if (err != IA_CSS_SUCCESS) 6491 return err; 6492 } 6493 pipe->pipe_settings.capture.anr_gdc_binary.left_padding = 6494 pipe->pipe_settings.capture.post_isp_binary.left_padding; 6495 6496 /* Pre-gdc */ 6497 { 6498 struct ia_css_binary_descr pre_gdc_descr; 6499 6500 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info, 6501 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); 6502 err = ia_css_binary_find(&pre_gdc_descr, 6503 &pipe->pipe_settings.capture.pre_isp_binary); 6504 if (err != IA_CSS_SUCCESS) 6505 return err; 6506 } 6507 pipe->pipe_settings.capture.pre_isp_binary.left_padding = 6508 pipe->pipe_settings.capture.anr_gdc_binary.left_padding; 6509 6510 /* Viewfinder post-processing */ 6511 if (need_pp) { 6512 vf_pp_in_info = 6513 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info; 6514 } else { 6515 vf_pp_in_info = 6516 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info; 6517 } 6518 6519 { 6520 struct ia_css_binary_descr vf_pp_descr; 6521 6522 ia_css_pipe_get_vfpp_binarydesc(pipe, 6523 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); 6524 err = ia_css_binary_find(&vf_pp_descr, 6525 &pipe->pipe_settings.capture.vf_pp_binary); 6526 if (err != IA_CSS_SUCCESS) 6527 return err; 6528 } 6529 6530 /* Copy */ 6531 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6532 /* For CSI2+, only the direct sensor mode/online requires ISP copy */ 6533 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 6534 #endif 6535 if (need_isp_copy) 6536 load_copy_binary(pipe, 6537 &pipe->pipe_settings.capture.copy_binary, 6538 &pipe->pipe_settings.capture.pre_isp_binary); 6539 6540 return err; 6541 } 6542 6543 static enum ia_css_err load_bayer_isp_binaries( 6544 struct ia_css_pipe *pipe) { 6545 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info; 6546 enum ia_css_err err = IA_CSS_SUCCESS; 6547 struct ia_css_binary_descr pre_de_descr; 6548 6549 IA_CSS_ENTER_PRIVATE(""); 6550 assert(pipe); 6551 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6552 pipe->mode == IA_CSS_PIPE_ID_COPY); 6553 pipe_out_info = &pipe->output_info[0]; 6554 6555 if (pipe->pipe_settings.capture.pre_isp_binary.info) 6556 return IA_CSS_SUCCESS; 6557 6558 err = ia_css_frame_check_info(pipe_out_info); 6559 if (err != IA_CSS_SUCCESS) 6560 return err; 6561 6562 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr, 6563 &pre_isp_in_info, 6564 pipe_out_info); 6565 6566 err = ia_css_binary_find(&pre_de_descr, 6567 &pipe->pipe_settings.capture.pre_isp_binary); 6568 6569 return err; 6570 } 6571 6572 static enum ia_css_err load_low_light_binaries( 6573 struct ia_css_pipe *pipe) { 6574 struct ia_css_frame_info pre_in_info, anr_in_info, 6575 post_in_info, post_out_info, 6576 vf_info, *pipe_vf_out_info, *pipe_out_info, 6577 *vf_pp_in_info; 6578 bool need_pp; 6579 bool need_isp_copy = true; 6580 enum ia_css_err err = IA_CSS_SUCCESS; 6581 6582 IA_CSS_ENTER_PRIVATE(""); 6583 assert(pipe); 6584 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6585 pipe->mode == IA_CSS_PIPE_ID_COPY); 6586 6587 if (pipe->pipe_settings.capture.pre_isp_binary.info) 6588 return IA_CSS_SUCCESS; 6589 pipe_vf_out_info = &pipe->vf_output_info[0]; 6590 pipe_out_info = &pipe->output_info[0]; 6591 6592 vf_info = *pipe_vf_out_info; 6593 err = ia_css_util_check_vf_out_info(pipe_out_info, 6594 &vf_info); 6595 if (err != IA_CSS_SUCCESS) 6596 return err; 6597 need_pp = need_capture_pp(pipe); 6598 6599 ia_css_frame_info_set_format(&vf_info, 6600 IA_CSS_FRAME_FORMAT_YUV_LINE); 6601 6602 /* we build up the pipeline starting at the end */ 6603 /* Capture post-processing */ 6604 if (need_pp) { 6605 struct ia_css_binary_descr capture_pp_descr; 6606 6607 ia_css_pipe_get_capturepp_binarydesc(pipe, 6608 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info); 6609 err = ia_css_binary_find(&capture_pp_descr, 6610 &pipe->pipe_settings.capture.capture_pp_binary); 6611 if (err != IA_CSS_SUCCESS) 6612 return err; 6613 } else { 6614 post_out_info = *pipe_out_info; 6615 } 6616 6617 /* Post-anr */ 6618 { 6619 struct ia_css_binary_descr post_anr_descr; 6620 6621 ia_css_pipe_get_post_anr_binarydesc(pipe, 6622 &post_anr_descr, &post_in_info, &post_out_info, &vf_info); 6623 err = ia_css_binary_find(&post_anr_descr, 6624 &pipe->pipe_settings.capture.post_isp_binary); 6625 if (err != IA_CSS_SUCCESS) 6626 return err; 6627 } 6628 6629 /* Anr */ 6630 { 6631 struct ia_css_binary_descr anr_descr; 6632 6633 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info, 6634 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); 6635 err = ia_css_binary_find(&anr_descr, 6636 &pipe->pipe_settings.capture.anr_gdc_binary); 6637 if (err != IA_CSS_SUCCESS) 6638 return err; 6639 } 6640 pipe->pipe_settings.capture.anr_gdc_binary.left_padding = 6641 pipe->pipe_settings.capture.post_isp_binary.left_padding; 6642 6643 /* Pre-anr */ 6644 { 6645 struct ia_css_binary_descr pre_anr_descr; 6646 6647 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info, 6648 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); 6649 err = ia_css_binary_find(&pre_anr_descr, 6650 &pipe->pipe_settings.capture.pre_isp_binary); 6651 if (err != IA_CSS_SUCCESS) 6652 return err; 6653 } 6654 pipe->pipe_settings.capture.pre_isp_binary.left_padding = 6655 pipe->pipe_settings.capture.anr_gdc_binary.left_padding; 6656 6657 /* Viewfinder post-processing */ 6658 if (need_pp) { 6659 vf_pp_in_info = 6660 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info; 6661 } else { 6662 vf_pp_in_info = 6663 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info; 6664 } 6665 6666 { 6667 struct ia_css_binary_descr vf_pp_descr; 6668 6669 ia_css_pipe_get_vfpp_binarydesc(pipe, 6670 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); 6671 err = ia_css_binary_find(&vf_pp_descr, 6672 &pipe->pipe_settings.capture.vf_pp_binary); 6673 if (err != IA_CSS_SUCCESS) 6674 return err; 6675 } 6676 6677 /* Copy */ 6678 #ifdef USE_INPUT_SYSTEM_VERSION_2401 6679 /* For CSI2+, only the direct sensor mode/online requires ISP copy */ 6680 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 6681 #endif 6682 if (need_isp_copy) 6683 err = load_copy_binary(pipe, 6684 &pipe->pipe_settings.capture.copy_binary, 6685 &pipe->pipe_settings.capture.pre_isp_binary); 6686 6687 return err; 6688 } 6689 6690 static bool copy_on_sp(struct ia_css_pipe *pipe) { 6691 bool rval; 6692 6693 assert(pipe); 6694 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n"); 6695 6696 rval = true; 6697 6698 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 6699 6700 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW); 6701 6702 rval &= ((pipe->stream->config.input_config.format == 6703 ATOMISP_INPUT_FORMAT_BINARY_8) || 6704 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)); 6705 6706 return rval; 6707 } 6708 6709 static enum ia_css_err load_capture_binaries( 6710 struct ia_css_pipe *pipe) { 6711 enum ia_css_err err = IA_CSS_SUCCESS; 6712 bool must_be_raw; 6713 6714 IA_CSS_ENTER_PRIVATE(""); 6715 assert(pipe); 6716 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6717 pipe->mode == IA_CSS_PIPE_ID_COPY); 6718 6719 if (pipe->pipe_settings.capture.primary_binary[0].info) { 6720 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 6721 return IA_CSS_SUCCESS; 6722 } 6723 6724 /* in primary, advanced,low light or bayer, 6725 the input format must be raw */ 6726 must_be_raw = 6727 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED || 6728 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER || 6729 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT; 6730 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false); 6731 if (err != IA_CSS_SUCCESS) { 6732 IA_CSS_LEAVE_ERR_PRIVATE(err); 6733 return err; 6734 } 6735 if (copy_on_sp(pipe) && 6736 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { 6737 ia_css_frame_info_init( 6738 &pipe->output_info[0], 6739 JPEG_BYTES, 6740 1, 6741 IA_CSS_FRAME_FORMAT_BINARY_8, 6742 0); 6743 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 6744 return IA_CSS_SUCCESS; 6745 } 6746 6747 switch (pipe->config.default_capture_config.mode) { 6748 case IA_CSS_CAPTURE_MODE_RAW: 6749 err = load_copy_binaries(pipe); 6750 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401) 6751 if (err == IA_CSS_SUCCESS) 6752 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; 6753 #endif 6754 break; 6755 case IA_CSS_CAPTURE_MODE_BAYER: 6756 err = load_bayer_isp_binaries(pipe); 6757 break; 6758 case IA_CSS_CAPTURE_MODE_PRIMARY: 6759 err = load_primary_binaries(pipe); 6760 break; 6761 case IA_CSS_CAPTURE_MODE_ADVANCED: 6762 err = load_advanced_binaries(pipe); 6763 break; 6764 case IA_CSS_CAPTURE_MODE_LOW_LIGHT: 6765 err = load_low_light_binaries(pipe); 6766 break; 6767 } 6768 if (err != IA_CSS_SUCCESS) { 6769 IA_CSS_LEAVE_ERR_PRIVATE(err); 6770 return err; 6771 } 6772 6773 IA_CSS_LEAVE_ERR_PRIVATE(err); 6774 return err; 6775 } 6776 6777 static enum ia_css_err 6778 unload_capture_binaries(struct ia_css_pipe *pipe) { 6779 unsigned int i; 6780 6781 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 6782 6783 if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY))) 6784 { 6785 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 6786 return IA_CSS_ERR_INVALID_ARGUMENTS; 6787 } 6788 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary); 6789 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++) 6790 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]); 6791 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary); 6792 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary); 6793 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary); 6794 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary); 6795 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary); 6796 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary); 6797 6798 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++) 6799 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]); 6800 6801 kfree(pipe->pipe_settings.capture.is_output_stage); 6802 pipe->pipe_settings.capture.is_output_stage = NULL; 6803 kfree(pipe->pipe_settings.capture.yuv_scaler_binary); 6804 pipe->pipe_settings.capture.yuv_scaler_binary = NULL; 6805 6806 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 6807 return IA_CSS_SUCCESS; 6808 } 6809 6810 static bool 6811 need_downscaling(const struct ia_css_resolution in_res, 6812 const struct ia_css_resolution out_res) { 6813 if (in_res.width > out_res.width || in_res.height > out_res.height) 6814 return true; 6815 6816 return false; 6817 } 6818 6819 static bool 6820 need_yuv_scaler_stage(const struct ia_css_pipe *pipe) { 6821 unsigned int i; 6822 struct ia_css_resolution in_res, out_res; 6823 6824 bool need_format_conversion = false; 6825 6826 IA_CSS_ENTER_PRIVATE(""); 6827 assert(pipe); 6828 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP); 6829 6830 /* TODO: make generic function */ 6831 need_format_conversion = 6832 ((pipe->stream->config.input_config.format == 6833 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) && 6834 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8)); 6835 6836 in_res = pipe->config.input_effective_res; 6837 6838 if (pipe->config.enable_dz) 6839 return true; 6840 6841 if ((pipe->output_info[0].res.width != 0) && need_format_conversion) 6842 return true; 6843 6844 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 6845 out_res = pipe->output_info[i].res; 6846 6847 /* A non-zero width means it is a valid output port */ 6848 if ((out_res.width != 0) && need_downscaling(in_res, out_res)) 6849 return true; 6850 } 6851 6852 return false; 6853 } 6854 6855 /* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */ 6856 /* which has some hard-coded knowledge which prevents reuse of the function. */ 6857 /* Later, merge this with ia_css_pipe_create_cas_scaler_desc */ 6858 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output( 6859 struct ia_css_frame_info *cas_scaler_in_info, 6860 struct ia_css_frame_info *cas_scaler_out_info, 6861 struct ia_css_frame_info *cas_scaler_vf_info, 6862 struct ia_css_cas_binary_descr *descr) { 6863 unsigned int i; 6864 unsigned int hor_ds_factor = 0, ver_ds_factor = 0; 6865 enum ia_css_err err = IA_CSS_SUCCESS; 6866 struct ia_css_frame_info tmp_in_info; 6867 6868 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP; 6869 6870 assert(cas_scaler_in_info); 6871 assert(cas_scaler_out_info); 6872 6873 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6874 "ia_css_pipe_create_cas_scaler_desc() enter:\n"); 6875 6876 /* We assume that this function is used only for single output port case. */ 6877 descr->num_output_stage = 1; 6878 6879 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width, 6880 cas_scaler_out_info->res.width); 6881 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height, 6882 cas_scaler_out_info->res.height); 6883 /* use the same horizontal and vertical downscaling factor for simplicity */ 6884 assert(hor_ds_factor == ver_ds_factor); 6885 6886 i = 1; 6887 while (i < hor_ds_factor) { 6888 descr->num_stage++; 6889 i *= max_scale_factor_per_stage; 6890 } 6891 6892 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 6893 GFP_KERNEL); 6894 if (!descr->in_info) { 6895 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 6896 goto ERR; 6897 } 6898 descr->internal_out_info = kmalloc(descr->num_stage * sizeof( 6899 struct ia_css_frame_info), GFP_KERNEL); 6900 if (!descr->internal_out_info) { 6901 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 6902 goto ERR; 6903 } 6904 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 6905 GFP_KERNEL); 6906 if (!descr->out_info) { 6907 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 6908 goto ERR; 6909 } 6910 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 6911 GFP_KERNEL); 6912 if (!descr->vf_info) { 6913 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 6914 goto ERR; 6915 } 6916 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL); 6917 if (!descr->is_output_stage) { 6918 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 6919 goto ERR; 6920 } 6921 6922 tmp_in_info = *cas_scaler_in_info; 6923 for (i = 0; i < descr->num_stage; i++) { 6924 descr->in_info[i] = tmp_in_info; 6925 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= 6926 cas_scaler_out_info->res.width) { 6927 descr->is_output_stage[i] = true; 6928 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) { 6929 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width; 6930 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height; 6931 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width; 6932 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 6933 } else { 6934 assert(i == (descr->num_stage - 1)); 6935 descr->internal_out_info[i].res.width = 0; 6936 descr->internal_out_info[i].res.height = 0; 6937 } 6938 descr->out_info[i].res.width = cas_scaler_out_info->res.width; 6939 descr->out_info[i].res.height = cas_scaler_out_info->res.height; 6940 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width; 6941 descr->out_info[i].format = cas_scaler_out_info->format; 6942 if (cas_scaler_vf_info) { 6943 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width; 6944 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height; 6945 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width; 6946 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE); 6947 } else { 6948 descr->vf_info[i].res.width = 0; 6949 descr->vf_info[i].res.height = 0; 6950 descr->vf_info[i].padded_width = 0; 6951 } 6952 } else { 6953 descr->is_output_stage[i] = false; 6954 descr->internal_out_info[i].res.width = tmp_in_info.res.width / 6955 max_scale_factor_per_stage; 6956 descr->internal_out_info[i].res.height = tmp_in_info.res.height / 6957 max_scale_factor_per_stage; 6958 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 6959 ia_css_frame_info_init(&descr->internal_out_info[i], 6960 tmp_in_info.res.width / max_scale_factor_per_stage, 6961 tmp_in_info.res.height / max_scale_factor_per_stage, 6962 IA_CSS_FRAME_FORMAT_YUV420, 0); 6963 descr->out_info[i].res.width = 0; 6964 descr->out_info[i].res.height = 0; 6965 descr->vf_info[i].res.width = 0; 6966 descr->vf_info[i].res.height = 0; 6967 } 6968 tmp_in_info = descr->internal_out_info[i]; 6969 } 6970 ERR: 6971 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6972 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n", 6973 err); 6974 return err; 6975 } 6976 6977 /* FIXME: merge most of this and single output version */ 6978 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc( 6979 struct ia_css_pipe *pipe, 6980 struct ia_css_cas_binary_descr *descr) { 6981 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; 6982 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 6983 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 6984 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; 6985 unsigned int i, j; 6986 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE], 6987 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE], 6988 scale_factor = 0; 6989 unsigned int num_stages = 0; 6990 enum ia_css_err err = IA_CSS_SUCCESS; 6991 6992 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP; 6993 6994 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6995 "ia_css_pipe_create_cas_scaler_desc() enter:\n"); 6996 6997 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 6998 out_info[i] = NULL; 6999 vf_out_info[i] = NULL; 7000 hor_scale_factor[i] = 0; 7001 ver_scale_factor[i] = 0; 7002 } 7003 7004 in_info.res = pipe->config.input_effective_res; 7005 in_info.padded_width = in_info.res.width; 7006 descr->num_output_stage = 0; 7007 /* Find out how much scaling we need for each output */ 7008 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 7009 if (pipe->output_info[i].res.width != 0) { 7010 out_info[i] = &pipe->output_info[i]; 7011 if (pipe->vf_output_info[i].res.width != 0) 7012 vf_out_info[i] = &pipe->vf_output_info[i]; 7013 descr->num_output_stage += 1; 7014 } 7015 7016 if (out_info[i]) { 7017 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width); 7018 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height); 7019 /* use the same horizontal and vertical scaling factor for simplicity */ 7020 assert(hor_scale_factor[i] == ver_scale_factor[i]); 7021 scale_factor = 1; 7022 do { 7023 num_stages++; 7024 scale_factor *= max_scale_factor_per_stage; 7025 } while (scale_factor < hor_scale_factor[i]); 7026 7027 in_info.res = out_info[i]->res; 7028 } 7029 } 7030 7031 if (need_yuv_scaler_stage(pipe) && (num_stages == 0)) 7032 num_stages = 1; 7033 7034 descr->num_stage = num_stages; 7035 7036 descr->in_info = kmalloc_array(descr->num_stage, 7037 sizeof(struct ia_css_frame_info), GFP_KERNEL); 7038 if (!descr->in_info) { 7039 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 7040 goto ERR; 7041 } 7042 descr->internal_out_info = kmalloc(descr->num_stage * sizeof( 7043 struct ia_css_frame_info), GFP_KERNEL); 7044 if (!descr->internal_out_info) { 7045 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 7046 goto ERR; 7047 } 7048 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 7049 GFP_KERNEL); 7050 if (!descr->out_info) { 7051 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 7052 goto ERR; 7053 } 7054 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), 7055 GFP_KERNEL); 7056 if (!descr->vf_info) { 7057 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 7058 goto ERR; 7059 } 7060 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL); 7061 if (!descr->is_output_stage) { 7062 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 7063 goto ERR; 7064 } 7065 7066 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 7067 if (out_info[i]) { 7068 if (i > 0) { 7069 assert((out_info[i - 1]->res.width >= out_info[i]->res.width) && 7070 (out_info[i - 1]->res.height >= out_info[i]->res.height)); 7071 } 7072 } 7073 } 7074 7075 tmp_in_info.res = pipe->config.input_effective_res; 7076 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420; 7077 for (i = 0, j = 0; i < descr->num_stage; i++) { 7078 assert(j < 2); 7079 assert(out_info[j]); 7080 7081 descr->in_info[i] = tmp_in_info; 7082 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= 7083 out_info[j]->res.width) { 7084 descr->is_output_stage[i] = true; 7085 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) { 7086 descr->internal_out_info[i].res.width = out_info[j]->res.width; 7087 descr->internal_out_info[i].res.height = out_info[j]->res.height; 7088 descr->internal_out_info[i].padded_width = out_info[j]->padded_width; 7089 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 7090 } else { 7091 assert(i == (descr->num_stage - 1)); 7092 descr->internal_out_info[i].res.width = 0; 7093 descr->internal_out_info[i].res.height = 0; 7094 } 7095 descr->out_info[i].res.width = out_info[j]->res.width; 7096 descr->out_info[i].res.height = out_info[j]->res.height; 7097 descr->out_info[i].padded_width = out_info[j]->padded_width; 7098 descr->out_info[i].format = out_info[j]->format; 7099 if (vf_out_info[j]) { 7100 descr->vf_info[i].res.width = vf_out_info[j]->res.width; 7101 descr->vf_info[i].res.height = vf_out_info[j]->res.height; 7102 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width; 7103 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE); 7104 } else { 7105 descr->vf_info[i].res.width = 0; 7106 descr->vf_info[i].res.height = 0; 7107 descr->vf_info[i].padded_width = 0; 7108 } 7109 j++; 7110 } else { 7111 descr->is_output_stage[i] = false; 7112 descr->internal_out_info[i].res.width = tmp_in_info.res.width / 7113 max_scale_factor_per_stage; 7114 descr->internal_out_info[i].res.height = tmp_in_info.res.height / 7115 max_scale_factor_per_stage; 7116 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 7117 ia_css_frame_info_init(&descr->internal_out_info[i], 7118 tmp_in_info.res.width / max_scale_factor_per_stage, 7119 tmp_in_info.res.height / max_scale_factor_per_stage, 7120 IA_CSS_FRAME_FORMAT_YUV420, 0); 7121 descr->out_info[i].res.width = 0; 7122 descr->out_info[i].res.height = 0; 7123 descr->vf_info[i].res.width = 0; 7124 descr->vf_info[i].res.height = 0; 7125 } 7126 tmp_in_info = descr->internal_out_info[i]; 7127 } 7128 ERR: 7129 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7130 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n", 7131 err); 7132 return err; 7133 } 7134 7135 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr 7136 *descr) { 7137 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7138 "ia_css_pipe_destroy_cas_scaler_desc() enter:\n"); 7139 kfree(descr->in_info); 7140 descr->in_info = NULL; 7141 kfree(descr->internal_out_info); 7142 descr->internal_out_info = NULL; 7143 kfree(descr->out_info); 7144 descr->out_info = NULL; 7145 kfree(descr->vf_info); 7146 descr->vf_info = NULL; 7147 kfree(descr->is_output_stage); 7148 descr->is_output_stage = NULL; 7149 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7150 "ia_css_pipe_destroy_cas_scaler_desc() leave\n"); 7151 } 7152 7153 static enum ia_css_err 7154 load_yuvpp_binaries(struct ia_css_pipe *pipe) { 7155 enum ia_css_err err = IA_CSS_SUCCESS; 7156 bool need_scaler = false; 7157 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 7158 struct ia_css_yuvpp_settings *mycs; 7159 struct ia_css_binary *next_binary; 7160 struct ia_css_cas_binary_descr cas_scaler_descr = { }; 7161 unsigned int i, j; 7162 bool need_isp_copy_binary = false; 7163 7164 IA_CSS_ENTER_PRIVATE(""); 7165 assert(pipe); 7166 assert(pipe->stream); 7167 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP); 7168 7169 if (pipe->pipe_settings.yuvpp.copy_binary.info) 7170 goto ERR; 7171 7172 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */ 7173 err = ia_css_util_check_input(&pipe->stream->config, false, false); 7174 if (err != IA_CSS_SUCCESS) 7175 goto ERR; 7176 7177 mycs = &pipe->pipe_settings.yuvpp; 7178 7179 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) 7180 { 7181 if (pipe->vf_output_info[i].res.width != 0) { 7182 err = ia_css_util_check_vf_out_info(&pipe->output_info[i], 7183 &pipe->vf_output_info[i]); 7184 if (err != IA_CSS_SUCCESS) 7185 goto ERR; 7186 } 7187 vf_pp_in_info[i] = NULL; 7188 } 7189 7190 need_scaler = need_yuv_scaler_stage(pipe); 7191 7192 /* we build up the pipeline starting at the end */ 7193 /* Capture post-processing */ 7194 if (need_scaler) 7195 { 7196 struct ia_css_binary_descr yuv_scaler_descr; 7197 7198 err = ia_css_pipe_create_cas_scaler_desc(pipe, 7199 &cas_scaler_descr); 7200 if (err != IA_CSS_SUCCESS) 7201 goto ERR; 7202 mycs->num_output = cas_scaler_descr.num_output_stage; 7203 mycs->num_yuv_scaler = cas_scaler_descr.num_stage; 7204 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * 7205 sizeof(struct ia_css_binary), GFP_KERNEL); 7206 if (!mycs->yuv_scaler_binary) { 7207 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 7208 goto ERR; 7209 } 7210 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage * 7211 sizeof(bool), GFP_KERNEL); 7212 if (!mycs->is_output_stage) { 7213 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 7214 goto ERR; 7215 } 7216 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 7217 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 7218 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 7219 &yuv_scaler_descr, &cas_scaler_descr.in_info[i], 7220 &cas_scaler_descr.out_info[i], 7221 &cas_scaler_descr.internal_out_info[i], 7222 &cas_scaler_descr.vf_info[i]); 7223 err = ia_css_binary_find(&yuv_scaler_descr, 7224 &mycs->yuv_scaler_binary[i]); 7225 if (err != IA_CSS_SUCCESS) 7226 goto ERR; 7227 } 7228 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 7229 } else 7230 { 7231 mycs->num_output = 1; 7232 } 7233 7234 if (need_scaler) 7235 { 7236 next_binary = &mycs->yuv_scaler_binary[0]; 7237 } else 7238 { 7239 next_binary = NULL; 7240 } 7241 7242 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 7243 /* 7244 * NOTES 7245 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when 7246 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"? 7247 * 7248 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_ 7249 * binary". However, the "yuv_scale_binary" does NOT support the input-frame 7250 * format as "IA_CSS_STREAM _FORMAT_YUV422_8". 7251 * 7252 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv 7253 * _scale_binary". It would translate the input-frame to the frame formats that 7254 * are supported by the "yuv_scale_binary". 7255 * 7256 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_ 7257 * pp_defs.h" for the list of input-frame formats that are supported by the 7258 * "yuv_scale_binary". 7259 */ 7260 need_isp_copy_binary = 7261 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); 7262 #else /* !USE_INPUT_SYSTEM_VERSION_2401 */ 7263 need_isp_copy_binary = true; 7264 #endif /* USE_INPUT_SYSTEM_VERSION_2401 */ 7265 7266 if (need_isp_copy_binary) 7267 { 7268 err = load_copy_binary(pipe, 7269 &mycs->copy_binary, 7270 next_binary); 7271 7272 if (err != IA_CSS_SUCCESS) 7273 goto ERR; 7274 7275 /* 7276 * NOTES 7277 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified? 7278 * 7279 * In some use cases, the first stage in the "yuvpp" pipe is the 7280 * "isp_copy_binary". The "isp_copy_binary" is designed to process 7281 * the input from either the system DDR or from the IPU internal VMEM. 7282 * So it provides the flag "online" to specify where its input is from, 7283 * i.e.: 7284 * 7285 * (1) "online <= true", the input is from the IPU internal VMEM. 7286 * (2) "online <= false", the input is from the system DDR. 7287 * 7288 * In other use cases, the first stage in the "yuvpp" pipe is the 7289 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the 7290 * input ONLY from the system DDR. So it does not provide the flag "online" 7291 * to specify where its input is from. 7292 */ 7293 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; 7294 } 7295 7296 /* Viewfinder post-processing */ 7297 if (need_scaler) 7298 { 7299 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) { 7300 if (mycs->is_output_stage[i]) { 7301 assert(j < 2); 7302 vf_pp_in_info[j] = 7303 &mycs->yuv_scaler_binary[i].vf_frame_info; 7304 j++; 7305 } 7306 } 7307 mycs->num_vf_pp = j; 7308 } else 7309 { 7310 vf_pp_in_info[0] = 7311 &mycs->copy_binary.vf_frame_info; 7312 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 7313 vf_pp_in_info[i] = NULL; 7314 } 7315 mycs->num_vf_pp = 1; 7316 } 7317 mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary), 7318 GFP_KERNEL); 7319 if (!mycs->vf_pp_binary) 7320 { 7321 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 7322 goto ERR; 7323 } 7324 7325 { 7326 struct ia_css_binary_descr vf_pp_descr; 7327 7328 for (i = 0; i < mycs->num_vf_pp; i++) 7329 { 7330 if (pipe->vf_output_info[i].res.width != 0) { 7331 ia_css_pipe_get_vfpp_binarydesc(pipe, 7332 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]); 7333 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]); 7334 if (err != IA_CSS_SUCCESS) 7335 goto ERR; 7336 } 7337 } 7338 } 7339 7340 if (err != IA_CSS_SUCCESS) 7341 goto ERR; 7342 7343 ERR: 7344 if (need_scaler) 7345 { 7346 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 7347 } 7348 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n", 7349 err); 7350 return err; 7351 } 7352 7353 static enum ia_css_err 7354 unload_yuvpp_binaries(struct ia_css_pipe *pipe) { 7355 unsigned int i; 7356 7357 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7358 7359 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) 7360 { 7361 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 7362 return IA_CSS_ERR_INVALID_ARGUMENTS; 7363 } 7364 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary); 7365 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++) 7366 { 7367 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]); 7368 } 7369 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++) 7370 { 7371 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]); 7372 } 7373 kfree(pipe->pipe_settings.yuvpp.is_output_stage); 7374 pipe->pipe_settings.yuvpp.is_output_stage = NULL; 7375 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary); 7376 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL; 7377 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary); 7378 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL; 7379 7380 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 7381 return IA_CSS_SUCCESS; 7382 } 7383 7384 static enum ia_css_err yuvpp_start(struct ia_css_pipe *pipe) { 7385 struct ia_css_binary *copy_binary; 7386 enum ia_css_err err = IA_CSS_SUCCESS; 7387 enum sh_css_pipe_config_override copy_ovrd; 7388 enum ia_css_input_mode yuvpp_pipe_input_mode; 7389 7390 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7391 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { 7392 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 7393 return IA_CSS_ERR_INVALID_ARGUMENTS; 7394 } 7395 7396 yuvpp_pipe_input_mode = pipe->stream->config.mode; 7397 7398 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary; 7399 7400 sh_css_metrics_start_frame(); 7401 7402 /* multi stream video needs mipi buffers */ 7403 7404 #if !defined(HAS_NO_INPUT_SYSTEM) && (defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)) 7405 err = send_mipi_frames(pipe); 7406 if (err != IA_CSS_SUCCESS) { 7407 IA_CSS_LEAVE_ERR_PRIVATE(err); 7408 return err; 7409 } 7410 #endif 7411 7412 { 7413 unsigned int thread_id; 7414 7415 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 7416 copy_ovrd = 1 << thread_id; 7417 } 7418 7419 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode); 7420 7421 IA_CSS_LEAVE_ERR_PRIVATE(err); 7422 return err; 7423 } 7424 7425 static enum ia_css_err 7426 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) { 7427 enum ia_css_err err = IA_CSS_SUCCESS; 7428 7429 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7430 7431 if (!pipe) 7432 { 7433 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 7434 return IA_CSS_ERR_INVALID_ARGUMENTS; 7435 } 7436 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ 7437 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 7438 { 7439 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 7440 return IA_CSS_SUCCESS; 7441 } 7442 7443 switch (pipe->mode) 7444 { 7445 case IA_CSS_PIPE_ID_PREVIEW: 7446 err = unload_preview_binaries(pipe); 7447 break; 7448 case IA_CSS_PIPE_ID_VIDEO: 7449 err = unload_video_binaries(pipe); 7450 break; 7451 case IA_CSS_PIPE_ID_CAPTURE: 7452 err = unload_capture_binaries(pipe); 7453 break; 7454 case IA_CSS_PIPE_ID_YUVPP: 7455 err = unload_yuvpp_binaries(pipe); 7456 break; 7457 default: 7458 break; 7459 } 7460 IA_CSS_LEAVE_ERR_PRIVATE(err); 7461 return err; 7462 } 7463 7464 static enum ia_css_err 7465 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) { 7466 enum ia_css_err err = IA_CSS_SUCCESS; 7467 7468 assert(pipe); 7469 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n"); 7470 7471 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ 7472 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 7473 return err; 7474 7475 switch (pipe->mode) 7476 { 7477 case IA_CSS_PIPE_ID_PREVIEW: 7478 err = load_preview_binaries(pipe); 7479 break; 7480 case IA_CSS_PIPE_ID_VIDEO: 7481 err = load_video_binaries(pipe); 7482 break; 7483 case IA_CSS_PIPE_ID_CAPTURE: 7484 err = load_capture_binaries(pipe); 7485 break; 7486 case IA_CSS_PIPE_ID_YUVPP: 7487 err = load_yuvpp_binaries(pipe); 7488 break; 7489 case IA_CSS_PIPE_ID_ACC: 7490 break; 7491 default: 7492 err = IA_CSS_ERR_INTERNAL_ERROR; 7493 break; 7494 } 7495 if (err != IA_CSS_SUCCESS) 7496 { 7497 if (sh_css_pipe_unload_binaries(pipe) != IA_CSS_SUCCESS) { 7498 /* currently css does not support multiple error returns in a single function, 7499 * using IA_CSS_ERR_INTERNAL_ERROR in this case */ 7500 err = IA_CSS_ERR_INTERNAL_ERROR; 7501 } 7502 } 7503 return err; 7504 } 7505 7506 static enum ia_css_err 7507 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) { 7508 struct ia_css_pipeline *me; 7509 enum ia_css_err err = IA_CSS_SUCCESS; 7510 struct ia_css_pipeline_stage *vf_pp_stage = NULL, 7511 *copy_stage = NULL, 7512 *yuv_scaler_stage = NULL; 7513 struct ia_css_binary *copy_binary, 7514 *vf_pp_binary, 7515 *yuv_scaler_binary; 7516 bool need_scaler = false; 7517 unsigned int num_stage, num_vf_pp_stage, num_output_stage; 7518 unsigned int i, j; 7519 7520 struct ia_css_frame *in_frame = NULL; 7521 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 7522 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 7523 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 7524 struct ia_css_pipeline_stage_desc stage_desc; 7525 bool need_in_frameinfo_memory = false; 7526 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7527 bool sensor = false; 7528 bool buffered_sensor = false; 7529 bool online = false; 7530 bool continuous = false; 7531 #endif 7532 7533 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7534 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) 7535 { 7536 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 7537 return IA_CSS_ERR_INVALID_ARGUMENTS; 7538 } 7539 me = &pipe->pipeline; 7540 ia_css_pipeline_clean(me); 7541 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) 7542 { 7543 out_frame[i] = NULL; 7544 vf_frame[i] = NULL; 7545 } 7546 ia_css_pipe_util_create_output_frames(bin_out_frame); 7547 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler; 7548 num_vf_pp_stage = pipe->pipe_settings.yuvpp.num_vf_pp; 7549 num_output_stage = pipe->pipe_settings.yuvpp.num_output; 7550 7551 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7552 /* When the input system is 2401, always enable 'in_frameinfo_memory' 7553 * except for the following: 7554 * - Direct Sensor Mode Online Capture 7555 * - Direct Sensor Mode Continuous Capture 7556 * - Buffered Sensor Mode Continuous Capture 7557 */ 7558 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 7559 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; 7560 online = pipe->stream->config.online; 7561 continuous = pipe->stream->config.continuous; 7562 need_in_frameinfo_memory = 7563 !((sensor && (online || continuous)) || (buffered_sensor && continuous)); 7564 #else 7565 /* Construct in_frame info (only in case we have dynamic input */ 7566 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 7567 #endif 7568 /* the input frame can come from: 7569 * a) memory: connect yuvscaler to me->in_frame 7570 * b) sensor, via copy binary: connect yuvscaler to copy binary later on */ 7571 if (need_in_frameinfo_memory) 7572 { 7573 /* TODO: improve for different input formats. */ 7574 7575 /* 7576 * "pipe->stream->config.input_config.format" represents the sensor output 7577 * frame format, e.g. YUV422 8-bit. 7578 * 7579 * "in_frame_format" represents the imaging pipe's input frame format, e.g. 7580 * Bayer-Quad RAW. 7581 */ 7582 int in_frame_format; 7583 7584 if (pipe->stream->config.input_config.format == 7585 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) { 7586 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8; 7587 } else if (pipe->stream->config.input_config.format == 7588 ATOMISP_INPUT_FORMAT_YUV422_8) { 7589 /* 7590 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8", 7591 * the "isp_copy_var" binary is selected as the first stage in the yuvpp 7592 * pipe. 7593 * 7594 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from 7595 * the frame buffer (at DDR) to the frame-line buffer (at VMEM). 7596 * 7597 * By now, the "isp_copy_var" binary does NOT provide a separated 7598 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores 7599 * the YUV422-8 pixels in the frame-line buffer which is designed to 7600 * store the Bayer-Quad RAW pixels. 7601 * 7602 * To direct the "isp_copy_var" binary reading from the RAW frame-line 7603 * buffer, its input frame format must be specified as "IA_CSS_FRAME_ 7604 * FORMAT_RAW". 7605 */ 7606 in_frame_format = IA_CSS_FRAME_FORMAT_RAW; 7607 } else { 7608 in_frame_format = IA_CSS_FRAME_FORMAT_NV12; 7609 } 7610 7611 err = init_in_frameinfo_memory_defaults(pipe, 7612 &me->in_frame, 7613 in_frame_format); 7614 7615 if (err != IA_CSS_SUCCESS) { 7616 IA_CSS_LEAVE_ERR_PRIVATE(err); 7617 return err; 7618 } 7619 7620 in_frame = &me->in_frame; 7621 } else 7622 { 7623 in_frame = NULL; 7624 } 7625 7626 for (i = 0; i < num_output_stage; i++) 7627 { 7628 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE); 7629 if (pipe->output_info[i].res.width != 0) { 7630 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i); 7631 if (err != IA_CSS_SUCCESS) { 7632 IA_CSS_LEAVE_ERR_PRIVATE(err); 7633 return err; 7634 } 7635 out_frame[i] = &me->out_frame[i]; 7636 } 7637 7638 /* Construct vf_frame info (only in case we have VF) */ 7639 if (pipe->vf_output_info[i].res.width != 0) { 7640 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i); 7641 if (err != IA_CSS_SUCCESS) { 7642 IA_CSS_LEAVE_ERR_PRIVATE(err); 7643 return err; 7644 } 7645 vf_frame[i] = &me->vf_frame[i]; 7646 } 7647 } 7648 7649 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary; 7650 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary; 7651 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary; 7652 need_scaler = need_yuv_scaler_stage(pipe); 7653 7654 if (pipe->pipe_settings.yuvpp.copy_binary.info) 7655 { 7656 struct ia_css_frame *in_frame_local = NULL; 7657 7658 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7659 /* After isp copy is enabled in_frame needs to be passed. */ 7660 if (!online) 7661 in_frame_local = in_frame; 7662 #endif 7663 7664 if (need_scaler) { 7665 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL); 7666 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7667 bin_out_frame, in_frame_local, NULL); 7668 } else { 7669 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]); 7670 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7671 bin_out_frame, in_frame_local, NULL); 7672 } 7673 7674 err = ia_css_pipeline_create_and_add_stage(me, 7675 &stage_desc, 7676 ©_stage); 7677 7678 if (err != IA_CSS_SUCCESS) { 7679 IA_CSS_LEAVE_ERR_PRIVATE(err); 7680 return err; 7681 } 7682 7683 if (copy_stage) { 7684 /* if we use yuv scaler binary, vf output should be from there */ 7685 copy_stage->args.copy_vf = !need_scaler; 7686 /* for yuvpp pipe, it should always be enabled */ 7687 copy_stage->args.copy_output = true; 7688 /* connect output of copy binary to input of yuv scaler */ 7689 in_frame = copy_stage->args.out_frame[0]; 7690 } 7691 } 7692 7693 if (need_scaler) 7694 { 7695 struct ia_css_frame *tmp_out_frame = NULL; 7696 struct ia_css_frame *tmp_vf_frame = NULL; 7697 struct ia_css_frame *tmp_in_frame = in_frame; 7698 7699 for (i = 0, j = 0; i < num_stage; i++) { 7700 assert(j < num_output_stage); 7701 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { 7702 tmp_out_frame = out_frame[j]; 7703 tmp_vf_frame = vf_frame[j]; 7704 } else { 7705 tmp_out_frame = NULL; 7706 tmp_vf_frame = NULL; 7707 } 7708 7709 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, 7710 NULL, 7711 &yuv_scaler_binary[i], 7712 &yuv_scaler_stage); 7713 7714 if (err != IA_CSS_SUCCESS) { 7715 IA_CSS_LEAVE_ERR_PRIVATE(err); 7716 return err; 7717 } 7718 /* we use output port 1 as internal output port */ 7719 tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; 7720 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { 7721 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) { 7722 in_frame = yuv_scaler_stage->args.out_vf_frame; 7723 err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j], 7724 &vf_pp_stage); 7725 7726 if (err != IA_CSS_SUCCESS) { 7727 IA_CSS_LEAVE_ERR_PRIVATE(err); 7728 return err; 7729 } 7730 } 7731 j++; 7732 } 7733 } 7734 } else if (copy_stage) 7735 { 7736 if (vf_frame[0] && vf_frame[0]->info.res.width != 0) { 7737 in_frame = copy_stage->args.out_vf_frame; 7738 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0], 7739 &vf_pp_stage); 7740 } 7741 if (err != IA_CSS_SUCCESS) { 7742 IA_CSS_LEAVE_ERR_PRIVATE(err); 7743 return err; 7744 } 7745 } 7746 7747 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 7748 7749 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 7750 7751 return IA_CSS_SUCCESS; 7752 } 7753 7754 static enum ia_css_err 7755 create_host_copy_pipeline(struct ia_css_pipe *pipe, 7756 unsigned int max_input_width, 7757 struct ia_css_frame *out_frame) { 7758 struct ia_css_pipeline *me; 7759 enum ia_css_err err = IA_CSS_SUCCESS; 7760 struct ia_css_pipeline_stage_desc stage_desc; 7761 7762 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7763 "create_host_copy_pipeline() enter:\n"); 7764 7765 /* pipeline already created as part of create_host_pipeline_structure */ 7766 me = &pipe->pipeline; 7767 ia_css_pipeline_clean(me); 7768 7769 /* Construct out_frame info */ 7770 out_frame->contiguous = false; 7771 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; 7772 7773 if (copy_on_sp(pipe) && 7774 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) 7775 { 7776 ia_css_frame_info_init( 7777 &out_frame->info, 7778 JPEG_BYTES, 7779 1, 7780 IA_CSS_FRAME_FORMAT_BINARY_8, 7781 0); 7782 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) 7783 { 7784 out_frame->info.raw_bit_depth = 7785 ia_css_pipe_util_pipe_input_format_bpp(pipe); 7786 } 7787 7788 me->num_stages = 1; 7789 me->pipe_id = IA_CSS_PIPE_ID_COPY; 7790 pipe->mode = IA_CSS_PIPE_ID_COPY; 7791 7792 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, 7793 IA_CSS_PIPELINE_RAW_COPY, max_input_width); 7794 err = ia_css_pipeline_create_and_add_stage(me, 7795 &stage_desc, 7796 NULL); 7797 7798 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 7799 7800 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7801 "create_host_copy_pipeline() leave:\n"); 7802 7803 return err; 7804 } 7805 7806 static enum ia_css_err 7807 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) { 7808 struct ia_css_pipeline *me = &pipe->pipeline; 7809 enum ia_css_err err = IA_CSS_SUCCESS; 7810 struct ia_css_pipeline_stage_desc stage_desc; 7811 struct ia_css_frame *out_frame = &me->out_frame[0]; 7812 struct ia_css_pipeline_stage *out_stage = NULL; 7813 unsigned int thread_id; 7814 enum sh_css_queue_id queue_id; 7815 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS; 7816 7817 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7818 "create_host_isyscopy_capture_pipeline() enter:\n"); 7819 ia_css_pipeline_clean(me); 7820 7821 /* Construct out_frame info */ 7822 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0); 7823 if (err != IA_CSS_SUCCESS) 7824 return err; 7825 out_frame->contiguous = false; 7826 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; 7827 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 7828 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id); 7829 out_frame->dynamic_queue_id = queue_id; 7830 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; 7831 7832 me->num_stages = 1; 7833 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE; 7834 pipe->mode = IA_CSS_PIPE_ID_CAPTURE; 7835 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, 7836 IA_CSS_PIPELINE_ISYS_COPY, max_input_width); 7837 err = ia_css_pipeline_create_and_add_stage(me, 7838 &stage_desc, &out_stage); 7839 if (err != IA_CSS_SUCCESS) 7840 return err; 7841 7842 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous); 7843 7844 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7845 "create_host_isyscopy_capture_pipeline() leave:\n"); 7846 7847 return err; 7848 } 7849 7850 static enum ia_css_err 7851 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) { 7852 struct ia_css_pipeline *me; 7853 enum ia_css_err err = IA_CSS_SUCCESS; 7854 enum ia_css_capture_mode mode; 7855 struct ia_css_pipeline_stage *current_stage = NULL; 7856 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL; 7857 struct ia_css_binary *copy_binary, 7858 *primary_binary[MAX_NUM_PRIMARY_STAGES], 7859 *vf_pp_binary, 7860 *pre_isp_binary, 7861 *anr_gdc_binary, 7862 *post_isp_binary, 7863 *yuv_scaler_binary, 7864 *capture_pp_binary, 7865 *capture_ldc_binary; 7866 bool need_pp = false; 7867 bool raw; 7868 7869 struct ia_css_frame *in_frame; 7870 struct ia_css_frame *out_frame; 7871 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 7872 struct ia_css_frame *vf_frame; 7873 struct ia_css_pipeline_stage_desc stage_desc; 7874 bool need_in_frameinfo_memory = false; 7875 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7876 bool sensor = false; 7877 bool buffered_sensor = false; 7878 bool online = false; 7879 bool continuous = false; 7880 #endif 7881 unsigned int i, num_yuv_scaler, num_primary_stage; 7882 bool need_yuv_pp = false; 7883 bool *is_output_stage = NULL; 7884 bool need_ldc = false; 7885 7886 IA_CSS_ENTER_PRIVATE(""); 7887 assert(pipe); 7888 assert(pipe->stream); 7889 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); 7890 7891 me = &pipe->pipeline; 7892 mode = pipe->config.default_capture_config.mode; 7893 raw = (mode == IA_CSS_CAPTURE_MODE_RAW); 7894 ia_css_pipeline_clean(me); 7895 ia_css_pipe_util_create_output_frames(out_frames); 7896 7897 #ifdef USE_INPUT_SYSTEM_VERSION_2401 7898 /* When the input system is 2401, always enable 'in_frameinfo_memory' 7899 * except for the following: 7900 * - Direct Sensor Mode Online Capture 7901 * - Direct Sensor Mode Online Capture 7902 * - Direct Sensor Mode Continuous Capture 7903 * - Buffered Sensor Mode Continuous Capture 7904 */ 7905 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); 7906 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 7907 online = pipe->stream->config.online; 7908 continuous = pipe->stream->config.continuous; 7909 need_in_frameinfo_memory = 7910 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); 7911 #else 7912 /* Construct in_frame info (only in case we have dynamic input */ 7913 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 7914 #endif 7915 if (need_in_frameinfo_memory) 7916 { 7917 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, 7918 IA_CSS_FRAME_FORMAT_RAW); 7919 if (err != IA_CSS_SUCCESS) { 7920 IA_CSS_LEAVE_ERR_PRIVATE(err); 7921 return err; 7922 } 7923 7924 in_frame = &me->in_frame; 7925 } else 7926 { 7927 in_frame = NULL; 7928 } 7929 7930 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); 7931 if (err != IA_CSS_SUCCESS) 7932 { 7933 IA_CSS_LEAVE_ERR_PRIVATE(err); 7934 return err; 7935 } 7936 out_frame = &me->out_frame[0]; 7937 7938 /* Construct vf_frame info (only in case we have VF) */ 7939 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) 7940 { 7941 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) { 7942 /* These modes don't support viewfinder output */ 7943 vf_frame = NULL; 7944 } else { 7945 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0); 7946 vf_frame = &me->vf_frame[0]; 7947 } 7948 } else 7949 { 7950 vf_frame = NULL; 7951 } 7952 7953 copy_binary = &pipe->pipe_settings.capture.copy_binary; 7954 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage; 7955 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) 7956 { 7957 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); 7958 return IA_CSS_ERR_INTERNAL_ERROR; 7959 } 7960 for (i = 0; i < num_primary_stage; i++) 7961 { 7962 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i]; 7963 } 7964 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary; 7965 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary; 7966 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary; 7967 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary; 7968 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary; 7969 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary; 7970 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler; 7971 is_output_stage = pipe->pipe_settings.capture.is_output_stage; 7972 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary; 7973 7974 need_pp = (need_capture_pp(pipe) || pipe->output_stage) && 7975 mode != IA_CSS_CAPTURE_MODE_RAW && 7976 mode != IA_CSS_CAPTURE_MODE_BAYER; 7977 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info); 7978 need_ldc = (capture_ldc_binary && capture_ldc_binary->info); 7979 7980 if (pipe->pipe_settings.capture.copy_binary.info) 7981 { 7982 if (raw) { 7983 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 7984 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401) 7985 if (!continuous) { 7986 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7987 out_frames, in_frame, NULL); 7988 } else { 7989 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 7990 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7991 out_frames, in_frame, NULL); 7992 } 7993 #else 7994 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 7995 out_frames, NULL, NULL); 7996 #endif 7997 } else { 7998 ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame); 7999 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, 8000 out_frames, NULL, NULL); 8001 } 8002 8003 err = ia_css_pipeline_create_and_add_stage(me, 8004 &stage_desc, 8005 ¤t_stage); 8006 if (err != IA_CSS_SUCCESS) { 8007 IA_CSS_LEAVE_ERR_PRIVATE(err); 8008 return err; 8009 } 8010 } else if (pipe->stream->config.continuous) 8011 { 8012 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 8013 } 8014 8015 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) 8016 { 8017 struct ia_css_frame *local_in_frame = NULL; 8018 struct ia_css_frame *local_out_frame = NULL; 8019 8020 for (i = 0; i < num_primary_stage; i++) { 8021 if (i == 0) 8022 local_in_frame = in_frame; 8023 else 8024 local_in_frame = NULL; 8025 #ifndef ISP2401 8026 if (!need_pp && (i == num_primary_stage - 1)) 8027 #else 8028 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc) 8029 #endif 8030 local_out_frame = out_frame; 8031 else 8032 local_out_frame = NULL; 8033 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame); 8034 /* 8035 * WARNING: The #if def flag has been added below as a 8036 * temporary solution to solve the problem of enabling the 8037 * view finder in a single binary in a capture flow. The 8038 * vf-pp stage has been removed from Skycam in the solution 8039 * provided. The vf-pp stage should be re-introduced when 8040 * required. This * should not be considered as a clean solution. 8041 * Proper investigation should be done to come up with the clean 8042 * solution. 8043 * */ 8044 ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i], 8045 out_frames, local_in_frame, NULL); 8046 err = ia_css_pipeline_create_and_add_stage(me, 8047 &stage_desc, 8048 ¤t_stage); 8049 if (err != IA_CSS_SUCCESS) { 8050 IA_CSS_LEAVE_ERR_PRIVATE(err); 8051 return err; 8052 } 8053 } 8054 /* If we use copy iso primary, 8055 the input must be yuv iso raw */ 8056 current_stage->args.copy_vf = 8057 primary_binary[0]->info->sp.pipeline.mode == 8058 IA_CSS_BINARY_MODE_COPY; 8059 current_stage->args.copy_output = current_stage->args.copy_vf; 8060 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED || 8061 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) 8062 { 8063 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 8064 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, 8065 out_frames, in_frame, NULL); 8066 err = ia_css_pipeline_create_and_add_stage(me, 8067 &stage_desc, NULL); 8068 if (err != IA_CSS_SUCCESS) { 8069 IA_CSS_LEAVE_ERR_PRIVATE(err); 8070 return err; 8071 } 8072 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 8073 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary, 8074 out_frames, NULL, NULL); 8075 err = ia_css_pipeline_create_and_add_stage(me, 8076 &stage_desc, NULL); 8077 if (err != IA_CSS_SUCCESS) { 8078 IA_CSS_LEAVE_ERR_PRIVATE(err); 8079 return err; 8080 } 8081 8082 if (need_pp) { 8083 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 8084 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary, 8085 out_frames, NULL, NULL); 8086 } else { 8087 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 8088 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary, 8089 out_frames, NULL, NULL); 8090 } 8091 8092 err = ia_css_pipeline_create_and_add_stage(me, 8093 &stage_desc, ¤t_stage); 8094 if (err != IA_CSS_SUCCESS) { 8095 IA_CSS_LEAVE_ERR_PRIVATE(err); 8096 return err; 8097 } 8098 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) 8099 { 8100 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 8101 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, 8102 out_frames, in_frame, NULL); 8103 err = ia_css_pipeline_create_and_add_stage(me, 8104 &stage_desc, 8105 NULL); 8106 if (err != IA_CSS_SUCCESS) { 8107 IA_CSS_LEAVE_ERR_PRIVATE(err); 8108 return err; 8109 } 8110 } 8111 8112 #ifndef ISP2401 8113 if (need_pp && current_stage) 8114 { 8115 struct ia_css_frame *local_in_frame = NULL; 8116 8117 local_in_frame = current_stage->args.out_frame[0]; 8118 8119 if (need_ldc) { 8120 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 8121 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, 8122 out_frames, local_in_frame, NULL); 8123 err = ia_css_pipeline_create_and_add_stage(me, 8124 &stage_desc, 8125 ¤t_stage); 8126 local_in_frame = current_stage->args.out_frame[0]; 8127 } 8128 err = add_capture_pp_stage(pipe, me, local_in_frame, 8129 need_yuv_pp ? NULL : out_frame, 8130 #else 8131 /* ldc and capture_pp not supported in same pipeline */ 8132 if (need_ldc && current_stage) 8133 { 8134 in_frame = current_stage->args.out_frame[0]; 8135 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 8136 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, 8137 out_frames, in_frame, NULL); 8138 err = ia_css_pipeline_create_and_add_stage(me, 8139 &stage_desc, 8140 NULL); 8141 } else if (need_pp && current_stage) 8142 { 8143 in_frame = current_stage->args.out_frame[0]; 8144 err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame, 8145 #endif 8146 capture_pp_binary, 8147 ¤t_stage); 8148 if (err != IA_CSS_SUCCESS) { 8149 IA_CSS_LEAVE_ERR_PRIVATE(err); 8150 return err; 8151 } 8152 } 8153 8154 if (need_yuv_pp && current_stage) 8155 { 8156 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0]; 8157 struct ia_css_frame *tmp_out_frame = NULL; 8158 8159 for (i = 0; i < num_yuv_scaler; i++) { 8160 if (is_output_stage[i] == true) 8161 tmp_out_frame = out_frame; 8162 else 8163 tmp_out_frame = NULL; 8164 8165 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, 8166 NULL, 8167 &yuv_scaler_binary[i], 8168 &yuv_scaler_stage); 8169 if (err != IA_CSS_SUCCESS) { 8170 IA_CSS_LEAVE_ERR_PRIVATE(err); 8171 return err; 8172 } 8173 /* we use output port 1 as internal output port */ 8174 tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; 8175 } 8176 } 8177 8178 /* 8179 * WARNING: The #if def flag has been added below as a 8180 * temporary solution to solve the problem of enabling the 8181 * view finder in a single binary in a capture flow. The vf-pp 8182 * stage has been removed from Skycam in the solution provided. 8183 * The vf-pp stage should be re-introduced when required. This 8184 * should not be considered as a clean solution. Proper 8185 * investigation should be done to come up with the clean solution. 8186 * */ 8187 if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) 8188 { 8189 in_frame = current_stage->args.out_vf_frame; 8190 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary, 8191 ¤t_stage); 8192 if (err != IA_CSS_SUCCESS) { 8193 IA_CSS_LEAVE_ERR_PRIVATE(err); 8194 return err; 8195 } 8196 } 8197 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 8198 8199 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8200 "create_host_regular_capture_pipeline() leave:\n"); 8201 8202 return IA_CSS_SUCCESS; 8203 } 8204 8205 static enum ia_css_err 8206 create_host_capture_pipeline(struct ia_css_pipe *pipe) { 8207 enum ia_css_err err = IA_CSS_SUCCESS; 8208 8209 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 8210 8211 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 8212 err = create_host_isyscopy_capture_pipeline(pipe); 8213 else 8214 err = create_host_regular_capture_pipeline(pipe); 8215 if (err != IA_CSS_SUCCESS) 8216 { 8217 IA_CSS_LEAVE_ERR_PRIVATE(err); 8218 return err; 8219 } 8220 8221 IA_CSS_LEAVE_ERR_PRIVATE(err); 8222 8223 return err; 8224 } 8225 8226 static enum ia_css_err capture_start( 8227 struct ia_css_pipe *pipe) { 8228 struct ia_css_pipeline *me; 8229 8230 enum ia_css_err err = IA_CSS_SUCCESS; 8231 enum sh_css_pipe_config_override copy_ovrd; 8232 8233 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 8234 if (!pipe) { 8235 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 8236 return IA_CSS_ERR_INVALID_ARGUMENTS; 8237 } 8238 8239 me = &pipe->pipeline; 8240 8241 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || 8242 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) && 8243 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { 8244 if (copy_on_sp(pipe)) { 8245 err = start_copy_on_sp(pipe, &me->out_frame[0]); 8246 IA_CSS_LEAVE_ERR_PRIVATE(err); 8247 return err; 8248 } 8249 } 8250 8251 #if defined(USE_INPUT_SYSTEM_VERSION_2) 8252 /* old isys: need to send_mipi_frames() in all pipe modes */ 8253 err = send_mipi_frames(pipe); 8254 if (err != IA_CSS_SUCCESS) { 8255 IA_CSS_LEAVE_ERR_PRIVATE(err); 8256 return err; 8257 } 8258 #elif defined(USE_INPUT_SYSTEM_VERSION_2401) 8259 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) { 8260 err = send_mipi_frames(pipe); 8261 if (err != IA_CSS_SUCCESS) { 8262 IA_CSS_LEAVE_ERR_PRIVATE(err); 8263 return err; 8264 } 8265 } 8266 8267 #endif 8268 8269 { 8270 unsigned int thread_id; 8271 8272 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 8273 copy_ovrd = 1 << thread_id; 8274 } 8275 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode); 8276 8277 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401) 8278 /* 8279 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured, 8280 * which is currently done in start_binary(); but COPY pipe contains no binary, 8281 * and does not call start_binary(); so we need to configure the rx here. 8282 */ 8283 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY && 8284 pipe->stream->reconfigure_css_rx) { 8285 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, 8286 pipe->stream->config.mode); 8287 pipe->stream->reconfigure_css_rx = false; 8288 } 8289 #endif 8290 8291 IA_CSS_LEAVE_ERR_PRIVATE(err); 8292 return err; 8293 } 8294 8295 static enum ia_css_err 8296 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, 8297 struct ia_css_frame_info *info, 8298 unsigned int idx) { 8299 assert(pipe); 8300 assert(info); 8301 8302 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8303 "sh_css_pipe_get_output_frame_info() enter:\n"); 8304 8305 *info = pipe->output_info[idx]; 8306 if (copy_on_sp(pipe) && 8307 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) 8308 { 8309 ia_css_frame_info_init( 8310 info, 8311 JPEG_BYTES, 8312 1, 8313 IA_CSS_FRAME_FORMAT_BINARY_8, 8314 0); 8315 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW || 8316 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) 8317 { 8318 info->raw_bit_depth = 8319 ia_css_pipe_util_pipe_input_format_bpp(pipe); 8320 } 8321 8322 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8323 "sh_css_pipe_get_output_frame_info() leave:\n"); 8324 return IA_CSS_SUCCESS; 8325 } 8326 8327 #if !defined(HAS_NO_INPUT_SYSTEM) 8328 void 8329 ia_css_stream_send_input_frame(const struct ia_css_stream *stream, 8330 const unsigned short *data, 8331 unsigned int width, 8332 unsigned int height) { 8333 assert(stream); 8334 8335 ia_css_inputfifo_send_input_frame( 8336 data, width, height, 8337 stream->config.channel_id, 8338 stream->config.input_config.format, 8339 stream->config.pixels_per_clock == 2); 8340 } 8341 8342 void 8343 ia_css_stream_start_input_frame(const struct ia_css_stream *stream) { 8344 assert(stream); 8345 8346 ia_css_inputfifo_start_frame( 8347 stream->config.channel_id, 8348 stream->config.input_config.format, 8349 stream->config.pixels_per_clock == 2); 8350 } 8351 8352 void 8353 ia_css_stream_send_input_line(const struct ia_css_stream *stream, 8354 const unsigned short *data, 8355 unsigned int width, 8356 const unsigned short *data2, 8357 unsigned int width2) { 8358 assert(stream); 8359 8360 ia_css_inputfifo_send_line(stream->config.channel_id, 8361 data, width, data2, width2); 8362 } 8363 8364 void 8365 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream, 8366 enum atomisp_input_format format, 8367 const unsigned short *data, 8368 unsigned int width) { 8369 assert(stream); 8370 if (!data || width == 0) 8371 return; 8372 ia_css_inputfifo_send_embedded_line(stream->config.channel_id, 8373 format, data, width); 8374 } 8375 8376 void 8377 ia_css_stream_end_input_frame(const struct ia_css_stream *stream) { 8378 assert(stream); 8379 8380 ia_css_inputfifo_end_frame(stream->config.channel_id); 8381 } 8382 #endif 8383 8384 static void 8385 append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) { 8386 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware); 8387 if (!l) { 8388 IA_CSS_ERROR("NULL fw_info"); 8389 IA_CSS_LEAVE_PRIVATE(""); 8390 return; 8391 } 8392 while (*l) 8393 l = &(*l)->next; 8394 *l = firmware; 8395 /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */ 8396 IA_CSS_LEAVE_PRIVATE(""); 8397 } 8398 8399 static void 8400 remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) { 8401 assert(*l); 8402 assert(firmware); 8403 (void)l; 8404 (void)firmware; 8405 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n"); 8406 8407 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n"); 8408 return; /* removing single and multiple firmware is handled in acc_unload_extension() */ 8409 } 8410 8411 static enum ia_css_err upload_isp_code(struct ia_css_fw_info *firmware) { 8412 ia_css_ptr binary; 8413 8414 if (!firmware) { 8415 IA_CSS_ERROR("NULL input parameter"); 8416 return IA_CSS_ERR_INVALID_ARGUMENTS; 8417 } 8418 binary = firmware->info.isp.xmem_addr; 8419 8420 if (!binary) { 8421 unsigned int size = firmware->blob.size; 8422 const unsigned char *blob; 8423 const unsigned char *binary_name; 8424 8425 binary_name = 8426 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME( 8427 firmware)); 8428 blob = binary_name + 8429 strlen((const char *)binary_name) + 8430 1; 8431 binary = sh_css_load_blob(blob, size); 8432 firmware->info.isp.xmem_addr = binary; 8433 } 8434 8435 if (!binary) 8436 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 8437 return IA_CSS_SUCCESS; 8438 } 8439 8440 static enum ia_css_err 8441 acc_load_extension(struct ia_css_fw_info *firmware) { 8442 enum ia_css_err err; 8443 struct ia_css_fw_info *hd = firmware; 8444 8445 while (hd) 8446 { 8447 err = upload_isp_code(hd); 8448 if (err != IA_CSS_SUCCESS) 8449 return err; 8450 hd = hd->next; 8451 } 8452 8453 if (!firmware) 8454 return IA_CSS_ERR_INVALID_ARGUMENTS; 8455 firmware->loaded = true; 8456 return IA_CSS_SUCCESS; 8457 } 8458 8459 static void 8460 acc_unload_extension(struct ia_css_fw_info *firmware) { 8461 struct ia_css_fw_info *hd = firmware; 8462 struct ia_css_fw_info *hdn = NULL; 8463 8464 if (!firmware) /* should not happen */ 8465 return; 8466 /* unload and remove multiple firmwares */ 8467 while (hd) { 8468 hdn = (hd->next) ? &(*hd->next) : NULL; 8469 if (hd->info.isp.xmem_addr) { 8470 hmm_free(hd->info.isp.xmem_addr); 8471 hd->info.isp.xmem_addr = mmgr_NULL; 8472 } 8473 hd->isp_code = NULL; 8474 hd->next = NULL; 8475 hd = hdn; 8476 } 8477 8478 firmware->loaded = false; 8479 } 8480 8481 /* Load firmware for extension */ 8482 static enum ia_css_err 8483 ia_css_pipe_load_extension(struct ia_css_pipe *pipe, 8484 struct ia_css_fw_info *firmware) { 8485 enum ia_css_err err = IA_CSS_SUCCESS; 8486 8487 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); 8488 8489 if ((!firmware) || (!pipe)) 8490 { 8491 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 8492 return IA_CSS_ERR_INVALID_ARGUMENTS; 8493 } 8494 8495 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT) 8496 { 8497 if (&pipe->output_stage) 8498 append_firmware(&pipe->output_stage, firmware); 8499 else { 8500 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); 8501 return IA_CSS_ERR_INTERNAL_ERROR; 8502 } 8503 } else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER) 8504 { 8505 if (&pipe->vf_stage) 8506 append_firmware(&pipe->vf_stage, firmware); 8507 else { 8508 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); 8509 return IA_CSS_ERR_INTERNAL_ERROR; 8510 } 8511 } 8512 err = acc_load_extension(firmware); 8513 8514 IA_CSS_LEAVE_ERR_PRIVATE(err); 8515 return err; 8516 } 8517 8518 /* Unload firmware for extension */ 8519 static void 8520 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe, 8521 struct ia_css_fw_info *firmware) { 8522 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); 8523 8524 if ((!firmware) || (!pipe)) { 8525 IA_CSS_ERROR("NULL input parameters"); 8526 IA_CSS_LEAVE_PRIVATE(""); 8527 return; 8528 } 8529 8530 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT) 8531 remove_firmware(&pipe->output_stage, firmware); 8532 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER) 8533 remove_firmware(&pipe->vf_stage, firmware); 8534 acc_unload_extension(firmware); 8535 8536 IA_CSS_LEAVE_PRIVATE(""); 8537 } 8538 8539 bool 8540 ia_css_pipeline_uses_params(struct ia_css_pipeline *me) { 8541 struct ia_css_pipeline_stage *stage; 8542 8543 assert(me); 8544 8545 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8546 "ia_css_pipeline_uses_params() enter: me=%p\n", me); 8547 8548 for (stage = me->stages; stage; stage = stage->next) 8549 if (stage->binary_info && stage->binary_info->enable.params) { 8550 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8551 "ia_css_pipeline_uses_params() leave: return_bool=true\n"); 8552 return true; 8553 } 8554 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8555 "ia_css_pipeline_uses_params() leave: return_bool=false\n"); 8556 return false; 8557 } 8558 8559 static enum ia_css_err 8560 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, 8561 const void *acc_fw) { 8562 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw; 8563 /* In QoS case, load_extension already called, so skipping */ 8564 enum ia_css_err err = IA_CSS_SUCCESS; 8565 8566 if (fw->loaded == false) 8567 err = acc_load_extension(fw); 8568 8569 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8570 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n", 8571 pipeline, acc_fw); 8572 8573 if (err == IA_CSS_SUCCESS) 8574 { 8575 struct ia_css_pipeline_stage_desc stage_desc; 8576 8577 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw); 8578 err = ia_css_pipeline_create_and_add_stage(pipeline, 8579 &stage_desc, 8580 NULL); 8581 } 8582 8583 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8584 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n", err); 8585 return err; 8586 } 8587 8588 /* 8589 * @brief Tag a specific frame in continuous capture. 8590 * Refer to "sh_css_internal.h" for details. 8591 */ 8592 enum ia_css_err ia_css_stream_capture_frame(struct ia_css_stream *stream, 8593 unsigned int exp_id) { 8594 struct sh_css_tag_descr tag_descr; 8595 u32 encoded_tag_descr; 8596 enum ia_css_err err; 8597 8598 assert(stream); 8599 IA_CSS_ENTER("exp_id=%d", exp_id); 8600 8601 /* Only continuous streams have a tagger */ 8602 if (exp_id == 0 || !stream->config.continuous) { 8603 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 8604 return IA_CSS_ERR_INVALID_ARGUMENTS; 8605 } 8606 8607 if (!sh_css_sp_is_running()) { 8608 /* SP is not running. The queues are not valid */ 8609 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); 8610 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 8611 } 8612 8613 /* Create the tag descriptor from the parameters */ 8614 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr); 8615 /* Encode the tag descriptor into a 32-bit value */ 8616 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); 8617 /* Enqueue the encoded tag to the host2sp queue. 8618 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 8619 * on both host and the SP side. 8620 * It is mainly because it is enough to have only one tag_cmd queue */ 8621 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr); 8622 8623 IA_CSS_LEAVE_ERR(err); 8624 return err; 8625 } 8626 8627 /* 8628 * @brief Configure the continuous capture. 8629 * Refer to "sh_css_internal.h" for details. 8630 */ 8631 enum ia_css_err ia_css_stream_capture( 8632 struct ia_css_stream *stream, 8633 int num_captures, 8634 unsigned int skip, 8635 int offset) { 8636 struct sh_css_tag_descr tag_descr; 8637 unsigned int encoded_tag_descr; 8638 enum ia_css_err return_err; 8639 8640 if (!stream) 8641 return IA_CSS_ERR_INVALID_ARGUMENTS; 8642 8643 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8644 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n", 8645 num_captures, skip, offset); 8646 8647 /* Check if the tag descriptor is valid */ 8648 if (num_captures < SH_CSS_MINIMUM_TAG_ID) { 8649 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8650 "ia_css_stream_capture() leave: return_err=%d\n", 8651 IA_CSS_ERR_INVALID_ARGUMENTS); 8652 return IA_CSS_ERR_INVALID_ARGUMENTS; 8653 } 8654 8655 /* Create the tag descriptor from the parameters */ 8656 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr); 8657 8658 /* Encode the tag descriptor into a 32-bit value */ 8659 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); 8660 8661 if (!sh_css_sp_is_running()) { 8662 /* SP is not running. The queues are not valid */ 8663 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8664 "ia_css_stream_capture() leaving:queues unavailable\n"); 8665 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 8666 } 8667 8668 /* Enqueue the encoded tag to the host2sp queue. 8669 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 8670 * on both host and the SP side. 8671 * It is mainly because it is enough to have only one tag_cmd queue */ 8672 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr); 8673 8674 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8675 "ia_css_stream_capture() leave: return_err=%d\n", 8676 return_err); 8677 8678 return return_err; 8679 } 8680 8681 void ia_css_stream_request_flash(struct ia_css_stream *stream) { 8682 (void)stream; 8683 8684 assert(stream); 8685 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8686 "ia_css_stream_request_flash() enter: void\n"); 8687 8688 #ifndef ISP2401 8689 sh_css_write_host2sp_command(host2sp_cmd_start_flash); 8690 #else 8691 if (sh_css_sp_is_running()) { 8692 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) { 8693 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); 8694 ia_css_debug_dump_sp_sw_debug_info(); 8695 ia_css_debug_dump_debug_info(NULL); 8696 } 8697 } else 8698 IA_CSS_LOG("SP is not running!"); 8699 8700 #endif 8701 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8702 "ia_css_stream_request_flash() leave: return_void\n"); 8703 } 8704 8705 static void 8706 sh_css_init_host_sp_control_vars(void) { 8707 const struct ia_css_fw_info *fw; 8708 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started; 8709 8710 unsigned int HIVE_ADDR_host_sp_queues_initialized; 8711 unsigned int HIVE_ADDR_sp_sleep_mode; 8712 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; 8713 #ifndef ISP2401 8714 unsigned int HIVE_ADDR_sp_stop_copy_preview; 8715 #endif 8716 unsigned int HIVE_ADDR_host_sp_com; 8717 unsigned int o = offsetof(struct host_sp_communication, host2sp_command) 8718 / sizeof(int); 8719 8720 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 8721 unsigned int i; 8722 #endif 8723 8724 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8725 "sh_css_init_host_sp_control_vars() enter: void\n"); 8726 8727 fw = &sh_css_sp_fw; 8728 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started; 8729 8730 HIVE_ADDR_host_sp_queues_initialized = 8731 fw->info.sp.host_sp_queues_initialized; 8732 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode; 8733 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb; 8734 #ifndef ISP2401 8735 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview; 8736 #endif 8737 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; 8738 8739 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */ 8740 8741 (void)HIVE_ADDR_sp_sleep_mode; 8742 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; 8743 #ifndef ISP2401 8744 (void)HIVE_ADDR_sp_stop_copy_preview; 8745 #endif 8746 (void)HIVE_ADDR_host_sp_com; 8747 8748 sp_dmem_store_uint32(SP0_ID, 8749 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started), 8750 (uint32_t)(0)); 8751 8752 sp_dmem_store_uint32(SP0_ID, 8753 (unsigned int)sp_address_of(host_sp_queues_initialized), 8754 (uint32_t)(0)); 8755 sp_dmem_store_uint32(SP0_ID, 8756 (unsigned int)sp_address_of(sp_sleep_mode), 8757 (uint32_t)(0)); 8758 sp_dmem_store_uint32(SP0_ID, 8759 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb), 8760 (uint32_t)(false)); 8761 #ifndef ISP2401 8762 sp_dmem_store_uint32(SP0_ID, 8763 (unsigned int)sp_address_of(sp_stop_copy_preview), 8764 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0)); 8765 #endif 8766 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready); 8767 8768 #if !defined(HAS_NO_INPUT_SYSTEM) 8769 for (i = 0; i < N_CSI_PORTS; i++) { 8770 sh_css_update_host2sp_num_mipi_frames 8771 (my_css.num_mipi_frames[i]); 8772 } 8773 #endif 8774 8775 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 8776 "sh_css_init_host_sp_control_vars() leave: return_void\n"); 8777 } 8778 8779 /* 8780 * create the internal structures and fill in the configuration data 8781 */ 8782 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config) { 8783 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n"); 8784 *pipe_config = DEFAULT_PIPE_CONFIG; 8785 } 8786 8787 void 8788 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config 8789 *extra_config) { 8790 if (!extra_config) { 8791 IA_CSS_ERROR("NULL input parameter"); 8792 return; 8793 } 8794 8795 extra_config->enable_raw_binning = false; 8796 extra_config->enable_yuv_ds = false; 8797 extra_config->enable_high_speed = false; 8798 extra_config->enable_dvs_6axis = false; 8799 extra_config->enable_reduced_pipe = false; 8800 extra_config->disable_vf_pp = false; 8801 extra_config->enable_fractional_ds = false; 8802 } 8803 8804 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config) { 8805 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n"); 8806 assert(stream_config); 8807 memset(stream_config, 0, sizeof(*stream_config)); 8808 stream_config->online = true; 8809 stream_config->left_padding = -1; 8810 stream_config->pixels_per_clock = 1; 8811 /* temporary default value for backwards compatibility. 8812 * This field used to be hardcoded within CSS but this has now 8813 * been moved to the stream_config struct. */ 8814 stream_config->source.port.rxcount = 0x04040404; 8815 } 8816 8817 static enum ia_css_err 8818 ia_css_acc_pipe_create(struct ia_css_pipe *pipe) { 8819 enum ia_css_err err = IA_CSS_SUCCESS; 8820 8821 if (!pipe) 8822 { 8823 IA_CSS_ERROR("NULL input parameter"); 8824 return IA_CSS_ERR_INVALID_ARGUMENTS; 8825 } 8826 8827 /* There is not meaning for num_execs = 0 semantically. Run atleast once. */ 8828 if (pipe->config.acc_num_execs == 0) 8829 pipe->config.acc_num_execs = 1; 8830 8831 if (pipe->config.acc_extension) 8832 { 8833 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension); 8834 } 8835 8836 return err; 8837 } 8838 8839 enum ia_css_err 8840 ia_css_pipe_create(const struct ia_css_pipe_config *config, 8841 struct ia_css_pipe **pipe) { 8842 #ifndef ISP2401 8843 if (!config) 8844 #else 8845 enum ia_css_err err = IA_CSS_SUCCESS; 8846 8847 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe); 8848 8849 if (!config) 8850 { 8851 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 8852 #endif 8853 return IA_CSS_ERR_INVALID_ARGUMENTS; 8854 #ifndef ISP2401 8855 if (!pipe) 8856 #else 8857 } 8858 if (!pipe) 8859 { 8860 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 8861 #endif 8862 return IA_CSS_ERR_INVALID_ARGUMENTS; 8863 #ifndef ISP2401 8864 return ia_css_pipe_create_extra(config, NULL, pipe); 8865 #else 8866 } 8867 8868 err = ia_css_pipe_create_extra(config, NULL, pipe); 8869 8870 if (err == IA_CSS_SUCCESS) 8871 { 8872 IA_CSS_LOG("pipe created successfully = %p", *pipe); 8873 } 8874 8875 IA_CSS_LEAVE_ERR_PRIVATE(err); 8876 8877 return err; 8878 #endif 8879 } 8880 8881 enum ia_css_err 8882 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config, 8883 const struct ia_css_pipe_extra_config *extra_config, 8884 struct ia_css_pipe **pipe) { 8885 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR; 8886 struct ia_css_pipe *internal_pipe = NULL; 8887 unsigned int i; 8888 8889 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe); 8890 8891 /* do not allow to create more than the maximum limit */ 8892 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) 8893 { 8894 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_EXHAUSTED); 8895 return IA_CSS_ERR_INVALID_ARGUMENTS; 8896 } 8897 8898 if ((!pipe) || (!config)) 8899 { 8900 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 8901 return IA_CSS_ERR_INVALID_ARGUMENTS; 8902 } 8903 8904 ia_css_debug_dump_pipe_config(config); 8905 ia_css_debug_dump_pipe_extra_config(extra_config); 8906 8907 err = create_pipe(config->mode, &internal_pipe, false); 8908 if (err != IA_CSS_SUCCESS) 8909 { 8910 IA_CSS_LEAVE_ERR_PRIVATE(err); 8911 return err; 8912 } 8913 8914 /* now we have a pipe structure to fill */ 8915 internal_pipe->config = *config; 8916 if (extra_config) 8917 internal_pipe->extra_config = *extra_config; 8918 else 8919 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config); 8920 8921 if (config->mode == IA_CSS_PIPE_MODE_ACC) 8922 { 8923 /* Temporary hack to migrate acceleration to CSS 2.0. 8924 * In the future the code for all pipe types should be 8925 * unified. */ 8926 *pipe = internal_pipe; 8927 if (!internal_pipe->config.acc_extension && 8928 internal_pipe->config.num_acc_stages == 8929 0) { /* if no acc binary and no standalone stage */ 8930 *pipe = NULL; 8931 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 8932 return IA_CSS_SUCCESS; 8933 } 8934 return ia_css_acc_pipe_create(internal_pipe); 8935 } 8936 8937 /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */ 8938 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2) 8939 internal_pipe->dvs_frame_delay = 2; 8940 else 8941 internal_pipe->dvs_frame_delay = 1; 8942 8943 /* we still keep enable_raw_binning for backward compatibility, for any new 8944 fractional bayer downscaling, we should use bayer_ds_out_res. if both are 8945 specified, bayer_ds_out_res will take precedence.if none is specified, we 8946 set bayer_ds_out_res equal to IF output resolution(IF may do cropping on 8947 sensor output) or use default decimation factor 1. */ 8948 if (internal_pipe->extra_config.enable_raw_binning && 8949 internal_pipe->config.bayer_ds_out_res.width) 8950 { 8951 /* fill some code here, if no code is needed, please remove it during integration */ 8952 } 8953 8954 /* YUV downscaling */ 8955 if ((internal_pipe->config.vf_pp_in_res.width || 8956 internal_pipe->config.capt_pp_in_res.width)) 8957 { 8958 enum ia_css_frame_format format; 8959 8960 if (internal_pipe->config.vf_pp_in_res.width) { 8961 format = IA_CSS_FRAME_FORMAT_YUV_LINE; 8962 ia_css_frame_info_init( 8963 &internal_pipe->vf_yuv_ds_input_info, 8964 internal_pipe->config.vf_pp_in_res.width, 8965 internal_pipe->config.vf_pp_in_res.height, 8966 format, 0); 8967 } 8968 if (internal_pipe->config.capt_pp_in_res.width) { 8969 format = IA_CSS_FRAME_FORMAT_YUV420; 8970 ia_css_frame_info_init( 8971 &internal_pipe->out_yuv_ds_input_info, 8972 internal_pipe->config.capt_pp_in_res.width, 8973 internal_pipe->config.capt_pp_in_res.height, 8974 format, 0); 8975 } 8976 } 8977 if (internal_pipe->config.vf_pp_in_res.width && 8978 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 8979 { 8980 ia_css_frame_info_init( 8981 &internal_pipe->vf_yuv_ds_input_info, 8982 internal_pipe->config.vf_pp_in_res.width, 8983 internal_pipe->config.vf_pp_in_res.height, 8984 IA_CSS_FRAME_FORMAT_YUV_LINE, 0); 8985 } 8986 /* handle bayer downscaling output info */ 8987 if (internal_pipe->config.bayer_ds_out_res.width) 8988 { 8989 ia_css_frame_info_init( 8990 &internal_pipe->bds_output_info, 8991 internal_pipe->config.bayer_ds_out_res.width, 8992 internal_pipe->config.bayer_ds_out_res.height, 8993 IA_CSS_FRAME_FORMAT_RAW, 0); 8994 } 8995 8996 /* handle output info, assume always needed */ 8997 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) 8998 { 8999 if (internal_pipe->config.output_info[i].res.width) { 9000 err = sh_css_pipe_configure_output( 9001 internal_pipe, 9002 internal_pipe->config.output_info[i].res.width, 9003 internal_pipe->config.output_info[i].res.height, 9004 internal_pipe->config.output_info[i].padded_width, 9005 internal_pipe->config.output_info[i].format, 9006 i); 9007 if (err != IA_CSS_SUCCESS) { 9008 IA_CSS_LEAVE_ERR_PRIVATE(err); 9009 kvfree(internal_pipe); 9010 internal_pipe = NULL; 9011 return err; 9012 } 9013 } 9014 9015 /* handle vf output info, when configured */ 9016 internal_pipe->enable_viewfinder[i] = 9017 (internal_pipe->config.vf_output_info[i].res.width != 0); 9018 if (internal_pipe->config.vf_output_info[i].res.width) { 9019 err = sh_css_pipe_configure_viewfinder( 9020 internal_pipe, 9021 internal_pipe->config.vf_output_info[i].res.width, 9022 internal_pipe->config.vf_output_info[i].res.height, 9023 internal_pipe->config.vf_output_info[i].padded_width, 9024 internal_pipe->config.vf_output_info[i].format, 9025 i); 9026 if (err != IA_CSS_SUCCESS) { 9027 IA_CSS_LEAVE_ERR_PRIVATE(err); 9028 kvfree(internal_pipe); 9029 internal_pipe = NULL; 9030 return err; 9031 } 9032 } 9033 } 9034 if (internal_pipe->config.acc_extension) 9035 { 9036 err = ia_css_pipe_load_extension(internal_pipe, 9037 internal_pipe->config.acc_extension); 9038 if (err != IA_CSS_SUCCESS) { 9039 IA_CSS_LEAVE_ERR_PRIVATE(err); 9040 kvfree(internal_pipe); 9041 return err; 9042 } 9043 } 9044 /* set all info to zeroes first */ 9045 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info)); 9046 9047 /* all went well, return the pipe */ 9048 *pipe = internal_pipe; 9049 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 9050 return IA_CSS_SUCCESS; 9051 } 9052 9053 enum ia_css_err 9054 ia_css_pipe_get_info(const struct ia_css_pipe *pipe, 9055 struct ia_css_pipe_info *pipe_info) { 9056 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 9057 "ia_css_pipe_get_info()\n"); 9058 assert(pipe_info); 9059 if (!pipe_info) 9060 { 9061 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 9062 "ia_css_pipe_get_info: pipe_info cannot be NULL\n"); 9063 return IA_CSS_ERR_INVALID_ARGUMENTS; 9064 } 9065 if (!pipe || !pipe->stream) 9066 { 9067 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 9068 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n"); 9069 return IA_CSS_ERR_INVALID_ARGUMENTS; 9070 } 9071 /* we succeeded return the info */ 9072 *pipe_info = pipe->info; 9073 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n"); 9074 return IA_CSS_SUCCESS; 9075 } 9076 9077 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info) { 9078 unsigned int i; 9079 9080 if (pipe_info) { 9081 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) { 9082 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable) 9083 return true; 9084 } 9085 } 9086 9087 return false; 9088 } 9089 9090 enum ia_css_err 9091 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe, 9092 int pin_index, 9093 enum ia_css_frame_format new_format) { 9094 enum ia_css_err err = IA_CSS_SUCCESS; 9095 9096 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format); 9097 9098 if (!pipe) 9099 { 9100 IA_CSS_ERROR("pipe is not set"); 9101 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9102 IA_CSS_LEAVE_ERR_PRIVATE(err); 9103 return err; 9104 } 9105 if (0 != pin_index && 1 != pin_index) 9106 { 9107 IA_CSS_ERROR("pin index is not valid"); 9108 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9109 IA_CSS_LEAVE_ERR_PRIVATE(err); 9110 return err; 9111 } 9112 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) 9113 { 9114 IA_CSS_ERROR("new format is not valid"); 9115 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9116 IA_CSS_LEAVE_ERR_PRIVATE(err); 9117 return err; 9118 } else 9119 { 9120 err = ia_css_pipe_check_format(pipe, new_format); 9121 if (err == IA_CSS_SUCCESS) { 9122 if (pin_index == 0) { 9123 pipe->output_info[0].format = new_format; 9124 } else { 9125 pipe->vf_output_info[0].format = new_format; 9126 } 9127 } 9128 } 9129 IA_CSS_LEAVE_ERR_PRIVATE(err); 9130 return err; 9131 } 9132 9133 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9134 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */ 9135 static enum ia_css_err 9136 ia_css_stream_configure_rx(struct ia_css_stream *stream) { 9137 struct ia_css_input_port *config; 9138 9139 assert(stream); 9140 9141 config = &stream->config.source.port; 9142 /* AM: this code is not reliable, especially for 2400 */ 9143 if (config->num_lanes == 1) 9144 stream->csi_rx_config.mode = MONO_1L_1L_0L; 9145 else if (config->num_lanes == 2) 9146 stream->csi_rx_config.mode = MONO_2L_1L_0L; 9147 else if (config->num_lanes == 3) 9148 stream->csi_rx_config.mode = MONO_3L_1L_0L; 9149 else if (config->num_lanes == 4) 9150 stream->csi_rx_config.mode = MONO_4L_1L_0L; 9151 else if (config->num_lanes != 0) 9152 return IA_CSS_ERR_INVALID_ARGUMENTS; 9153 9154 if (config->port > MIPI_PORT2_ID) 9155 return IA_CSS_ERR_INVALID_ARGUMENTS; 9156 stream->csi_rx_config.port = 9157 ia_css_isys_port_to_mipi_port(config->port); 9158 stream->csi_rx_config.timeout = config->timeout; 9159 stream->csi_rx_config.initcount = 0; 9160 stream->csi_rx_config.synccount = 0x28282828; 9161 stream->csi_rx_config.rxcount = config->rxcount; 9162 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE) 9163 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE; 9164 else 9165 { 9166 /* not implemented yet, requires extension of the rx_cfg_t 9167 * struct */ 9168 return IA_CSS_ERR_INVALID_ARGUMENTS; 9169 } 9170 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2); 9171 stream->reconfigure_css_rx = true; 9172 return IA_CSS_SUCCESS; 9173 } 9174 #endif 9175 9176 static struct ia_css_pipe * 9177 find_pipe(struct ia_css_pipe *pipes[], 9178 unsigned int num_pipes, 9179 enum ia_css_pipe_mode mode, 9180 bool copy_pipe) { 9181 unsigned int i; 9182 9183 assert(pipes); 9184 for (i = 0; i < num_pipes; i++) { 9185 assert(pipes[i]); 9186 if (pipes[i]->config.mode != mode) 9187 continue; 9188 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY) 9189 continue; 9190 return pipes[i]; 9191 } 9192 return NULL; 9193 } 9194 9195 static enum ia_css_err 9196 ia_css_acc_stream_create(struct ia_css_stream *stream) { 9197 int i; 9198 enum ia_css_err err = IA_CSS_SUCCESS; 9199 9200 assert(stream); 9201 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 9202 9203 if (!stream) 9204 { 9205 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 9206 return IA_CSS_ERR_INVALID_ARGUMENTS; 9207 } 9208 9209 for (i = 0; i < stream->num_pipes; i++) 9210 { 9211 struct ia_css_pipe *pipe = stream->pipes[i]; 9212 9213 assert(pipe); 9214 if (!pipe) { 9215 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); 9216 return IA_CSS_ERR_INVALID_ARGUMENTS; 9217 } 9218 9219 pipe->stream = stream; 9220 } 9221 9222 /* Map SP threads before doing anything. */ 9223 err = map_sp_threads(stream, true); 9224 if (err != IA_CSS_SUCCESS) 9225 { 9226 IA_CSS_LEAVE_ERR_PRIVATE(err); 9227 return err; 9228 } 9229 9230 for (i = 0; i < stream->num_pipes; i++) 9231 { 9232 struct ia_css_pipe *pipe = stream->pipes[i]; 9233 9234 assert(pipe); 9235 ia_css_pipe_map_queue(pipe, true); 9236 } 9237 9238 err = create_host_pipeline_structure(stream); 9239 if (err != IA_CSS_SUCCESS) 9240 { 9241 IA_CSS_LEAVE_ERR_PRIVATE(err); 9242 return err; 9243 } 9244 9245 stream->started = false; 9246 9247 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); 9248 9249 return IA_CSS_SUCCESS; 9250 } 9251 9252 static enum ia_css_err 9253 metadata_info_init(const struct ia_css_metadata_config *mdc, 9254 struct ia_css_metadata_info *md) { 9255 /* Either both width and height should be set or neither */ 9256 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0)) 9257 return IA_CSS_ERR_INVALID_ARGUMENTS; 9258 9259 md->resolution = mdc->resolution; 9260 /* We round up the stride to a multiple of the width 9261 * of the port going to DDR, this is a HW requirements (DMA). */ 9262 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES); 9263 md->size = mdc->resolution.height * md->stride; 9264 return IA_CSS_SUCCESS; 9265 } 9266 9267 /* ISP2401 */ 9268 static enum ia_css_err check_pipe_resolutions(const struct ia_css_pipe *pipe) { 9269 enum ia_css_err err = IA_CSS_SUCCESS; 9270 9271 IA_CSS_ENTER_PRIVATE(""); 9272 9273 if (!pipe || !pipe->stream) { 9274 IA_CSS_ERROR("null arguments"); 9275 err = IA_CSS_ERR_INTERNAL_ERROR; 9276 goto EXIT; 9277 } 9278 9279 if (ia_css_util_check_res(pipe->config.input_effective_res.width, 9280 pipe->config.input_effective_res.height) != IA_CSS_SUCCESS) { 9281 IA_CSS_ERROR("effective resolution not supported"); 9282 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9283 goto EXIT; 9284 } 9285 if (!ia_css_util_resolution_is_zero( 9286 pipe->stream->config.input_config.input_res)) { 9287 if (!ia_css_util_res_leq(pipe->config.input_effective_res, 9288 pipe->stream->config.input_config.input_res)) { 9289 IA_CSS_ERROR("effective resolution is larger than input resolution"); 9290 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9291 goto EXIT; 9292 } 9293 } 9294 if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) { 9295 IA_CSS_ERROR("output resolution must be even"); 9296 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9297 goto EXIT; 9298 } 9299 if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) { 9300 IA_CSS_ERROR("VF resolution must be even"); 9301 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9302 goto EXIT; 9303 } 9304 EXIT: 9305 IA_CSS_LEAVE_ERR_PRIVATE(err); 9306 return err; 9307 } 9308 9309 enum ia_css_err 9310 ia_css_stream_create(const struct ia_css_stream_config *stream_config, 9311 int num_pipes, 9312 struct ia_css_pipe *pipes[], 9313 struct ia_css_stream **stream) { 9314 struct ia_css_pipe *curr_pipe; 9315 struct ia_css_stream *curr_stream = NULL; 9316 bool spcopyonly; 9317 bool sensor_binning_changed; 9318 int i, j; 9319 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR; 9320 struct ia_css_metadata_info md_info; 9321 struct ia_css_resolution effective_res; 9322 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9323 bool aspect_ratio_crop_enabled = false; 9324 #endif 9325 9326 IA_CSS_ENTER("num_pipes=%d", num_pipes); 9327 ia_css_debug_dump_stream_config(stream_config, num_pipes); 9328 9329 /* some checks */ 9330 if (num_pipes == 0 || 9331 !stream || 9332 !pipes) 9333 { 9334 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9335 IA_CSS_LEAVE_ERR(err); 9336 return err; 9337 } 9338 9339 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9340 /* We don't support metadata for JPEG stream, since they both use str2mem */ 9341 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && 9342 stream_config->metadata_config.resolution.height > 0) 9343 { 9344 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9345 IA_CSS_LEAVE_ERR(err); 9346 return err; 9347 } 9348 #endif 9349 9350 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9351 if (stream_config->online && stream_config->pack_raw_pixels) 9352 { 9353 IA_CSS_LOG("online and pack raw is invalid on input system 2401"); 9354 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9355 IA_CSS_LEAVE_ERR(err); 9356 return err; 9357 } 9358 #endif 9359 9360 #if !defined(HAS_NO_INPUT_SYSTEM) 9361 ia_css_debug_pipe_graph_dump_stream_config(stream_config); 9362 9363 /* check if mipi size specified */ 9364 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 9365 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9366 if (!stream_config->online) 9367 #endif 9368 { 9369 unsigned int port = (unsigned int)stream_config->source.port.port; 9370 9371 if (port >= N_MIPI_PORT_ID) { 9372 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9373 IA_CSS_LEAVE_ERR(err); 9374 return err; 9375 } 9376 9377 if (my_css.size_mem_words != 0) { 9378 my_css.mipi_frame_size[port] = my_css.size_mem_words; 9379 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) { 9380 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words; 9381 } else { 9382 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 9383 "ia_css_stream_create() exit: error, need to set mipi frame size.\n"); 9384 assert(stream_config->mipi_buffer_config.size_mem_words != 0); 9385 err = IA_CSS_ERR_INTERNAL_ERROR; 9386 IA_CSS_LEAVE_ERR(err); 9387 return err; 9388 } 9389 9390 if (my_css.size_mem_words != 0) { 9391 my_css.num_mipi_frames[port] = 9392 2; /* Temp change: Default for backwards compatibility. */ 9393 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) { 9394 my_css.num_mipi_frames[port] = 9395 stream_config->mipi_buffer_config.nof_mipi_buffers; 9396 } else { 9397 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 9398 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n"); 9399 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0); 9400 err = IA_CSS_ERR_INTERNAL_ERROR; 9401 IA_CSS_LEAVE_ERR(err); 9402 return err; 9403 } 9404 } 9405 #endif 9406 9407 /* Currently we only supported metadata up to a certain size. */ 9408 err = metadata_info_init(&stream_config->metadata_config, &md_info); 9409 if (err != IA_CSS_SUCCESS) 9410 { 9411 IA_CSS_LEAVE_ERR(err); 9412 return err; 9413 } 9414 9415 /* allocate the stream instance */ 9416 curr_stream = kmalloc(sizeof(struct ia_css_stream), GFP_KERNEL); 9417 if (!curr_stream) 9418 { 9419 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 9420 IA_CSS_LEAVE_ERR(err); 9421 return err; 9422 } 9423 /* default all to 0 */ 9424 memset(curr_stream, 0, sizeof(struct ia_css_stream)); 9425 curr_stream->info.metadata_info = md_info; 9426 9427 /* allocate pipes */ 9428 curr_stream->num_pipes = num_pipes; 9429 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL); 9430 if (!curr_stream->pipes) 9431 { 9432 curr_stream->num_pipes = 0; 9433 kfree(curr_stream); 9434 curr_stream = NULL; 9435 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 9436 IA_CSS_LEAVE_ERR(err); 9437 return err; 9438 } 9439 /* store pipes */ 9440 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY); 9441 for (i = 0; i < num_pipes; i++) 9442 curr_stream->pipes[i] = pipes[i]; 9443 curr_stream->last_pipe = curr_stream->pipes[0]; 9444 /* take over stream config */ 9445 curr_stream->config = *stream_config; 9446 9447 #if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE) 9448 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR && 9449 stream_config->online) 9450 curr_stream->config.online = false; 9451 #endif 9452 9453 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9454 if (curr_stream->config.online) 9455 { 9456 curr_stream->config.source.port.num_lanes = 9457 stream_config->source.port.num_lanes; 9458 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; 9459 } 9460 #endif 9461 /* in case driver doesn't configure init number of raw buffers, configure it here */ 9462 if (curr_stream->config.target_num_cont_raw_buf == 0) 9463 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES; 9464 if (curr_stream->config.init_num_cont_raw_buf == 0) 9465 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf; 9466 9467 /* Enable locking & unlocking of buffers in RAW buffer pool */ 9468 if (curr_stream->config.ia_css_enable_raw_buffer_locking) 9469 sh_css_sp_configure_enable_raw_pool_locking( 9470 curr_stream->config.lock_all); 9471 9472 /* copy mode specific stuff */ 9473 switch (curr_stream->config.mode) 9474 { 9475 case IA_CSS_INPUT_MODE_SENSOR: 9476 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: 9477 #if defined(USE_INPUT_SYSTEM_VERSION_2) 9478 ia_css_stream_configure_rx(curr_stream); 9479 #endif 9480 break; 9481 case IA_CSS_INPUT_MODE_TPG: 9482 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) 9483 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d", 9484 curr_stream->config.source.tpg.x_mask, 9485 curr_stream->config.source.tpg.y_mask, 9486 curr_stream->config.source.tpg.x_delta, 9487 curr_stream->config.source.tpg.y_delta, 9488 curr_stream->config.source.tpg.xy_mask); 9489 9490 sh_css_sp_configure_tpg( 9491 curr_stream->config.source.tpg.x_mask, 9492 curr_stream->config.source.tpg.y_mask, 9493 curr_stream->config.source.tpg.x_delta, 9494 curr_stream->config.source.tpg.y_delta, 9495 curr_stream->config.source.tpg.xy_mask); 9496 #endif 9497 break; 9498 case IA_CSS_INPUT_MODE_PRBS: 9499 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) 9500 IA_CSS_LOG("mode prbs"); 9501 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed); 9502 #endif 9503 break; 9504 case IA_CSS_INPUT_MODE_MEMORY: 9505 IA_CSS_LOG("mode memory"); 9506 curr_stream->reconfigure_css_rx = false; 9507 break; 9508 default: 9509 IA_CSS_LOG("mode sensor/default"); 9510 } 9511 9512 #ifdef USE_INPUT_SYSTEM_VERSION_2401 9513 err = aspect_ratio_crop_init(curr_stream, 9514 pipes, 9515 &aspect_ratio_crop_enabled); 9516 if (err != IA_CSS_SUCCESS) 9517 { 9518 IA_CSS_LEAVE_ERR(err); 9519 return err; 9520 } 9521 #endif 9522 for (i = 0; i < num_pipes; i++) 9523 { 9524 struct ia_css_resolution effective_res; 9525 9526 curr_pipe = pipes[i]; 9527 /* set current stream */ 9528 curr_pipe->stream = curr_stream; 9529 /* take over effective info */ 9530 9531 effective_res = curr_pipe->config.input_effective_res; 9532 if (effective_res.height == 0 || effective_res.width == 0) { 9533 effective_res = curr_pipe->stream->config.input_config.effective_res; 9534 9535 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 9536 /* The aspect ratio cropping is currently only 9537 * supported on the new input system. */ 9538 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) { 9539 struct ia_css_resolution crop_res; 9540 9541 err = aspect_ratio_crop(curr_pipe, &crop_res); 9542 if (err == IA_CSS_SUCCESS) { 9543 effective_res = crop_res; 9544 } else { 9545 /* in case of error fallback to default 9546 * effective resolution from driver. */ 9547 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err); 9548 } 9549 } 9550 #endif 9551 curr_pipe->config.input_effective_res = effective_res; 9552 } 9553 IA_CSS_LOG("effective_res=%dx%d", 9554 effective_res.width, 9555 effective_res.height); 9556 } 9557 9558 if (atomisp_hw_is_isp2401) { 9559 for (i = 0; i < num_pipes; i++) { 9560 if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC && 9561 pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) { 9562 err = check_pipe_resolutions(pipes[i]); 9563 if (err != IA_CSS_SUCCESS) { 9564 goto ERR; 9565 } 9566 } 9567 } 9568 } 9569 9570 err = ia_css_stream_isp_parameters_init(curr_stream); 9571 if (err != IA_CSS_SUCCESS) 9572 goto ERR; 9573 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs); 9574 9575 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) 9576 { 9577 *stream = curr_stream; 9578 err = ia_css_acc_stream_create(curr_stream); 9579 goto ERR; 9580 } 9581 /* sensor binning */ 9582 if (!spcopyonly) 9583 { 9584 sensor_binning_changed = 9585 sh_css_params_set_binning_factor(curr_stream, 9586 curr_stream->config.sensor_binning_factor); 9587 } else 9588 { 9589 sensor_binning_changed = false; 9590 } 9591 9592 IA_CSS_LOG("sensor_binning=%d, changed=%d", 9593 curr_stream->config.sensor_binning_factor, sensor_binning_changed); 9594 /* loop over pipes */ 9595 IA_CSS_LOG("num_pipes=%d", num_pipes); 9596 curr_stream->cont_capt = false; 9597 /* Temporary hack: we give the preview pipe a reference to the capture 9598 * pipe in continuous capture mode. */ 9599 if (curr_stream->config.continuous) 9600 { 9601 /* Search for the preview pipe and create the copy pipe */ 9602 struct ia_css_pipe *preview_pipe; 9603 struct ia_css_pipe *video_pipe; 9604 struct ia_css_pipe *acc_pipe; 9605 struct ia_css_pipe *capture_pipe = NULL; 9606 struct ia_css_pipe *copy_pipe = NULL; 9607 9608 if (num_pipes >= 2) { 9609 curr_stream->cont_capt = true; 9610 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder; 9611 9612 if (!atomisp_hw_is_isp2401) 9613 curr_stream->stop_copy_preview = my_css.stop_copy_preview; 9614 } 9615 9616 /* Create copy pipe here, since it may not be exposed to the driver */ 9617 preview_pipe = find_pipe(pipes, num_pipes, 9618 IA_CSS_PIPE_MODE_PREVIEW, false); 9619 video_pipe = find_pipe(pipes, num_pipes, 9620 IA_CSS_PIPE_MODE_VIDEO, false); 9621 acc_pipe = find_pipe(pipes, num_pipes, 9622 IA_CSS_PIPE_MODE_ACC, false); 9623 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true) 9624 curr_stream->cont_capt = 9625 false; /* preview + QoS case will not need cont_capt switch */ 9626 if (curr_stream->cont_capt == true) { 9627 capture_pipe = find_pipe(pipes, num_pipes, 9628 IA_CSS_PIPE_MODE_CAPTURE, false); 9629 if (!capture_pipe) { 9630 err = IA_CSS_ERR_INTERNAL_ERROR; 9631 goto ERR; 9632 } 9633 } 9634 /* We do not support preview and video pipe at the same time */ 9635 if (preview_pipe && video_pipe) { 9636 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9637 goto ERR; 9638 } 9639 9640 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) { 9641 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); 9642 if (err != IA_CSS_SUCCESS) 9643 goto ERR; 9644 ia_css_pipe_config_defaults(©_pipe->config); 9645 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe; 9646 copy_pipe->stream = curr_stream; 9647 } 9648 if (preview_pipe && (curr_stream->cont_capt == true)) { 9649 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe; 9650 } 9651 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) { 9652 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); 9653 if (err != IA_CSS_SUCCESS) 9654 goto ERR; 9655 ia_css_pipe_config_defaults(©_pipe->config); 9656 video_pipe->pipe_settings.video.copy_pipe = copy_pipe; 9657 copy_pipe->stream = curr_stream; 9658 } 9659 if (video_pipe && (curr_stream->cont_capt == true)) { 9660 video_pipe->pipe_settings.video.capture_pipe = capture_pipe; 9661 } 9662 if (preview_pipe && acc_pipe) { 9663 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe; 9664 } 9665 } 9666 for (i = 0; i < num_pipes; i++) 9667 { 9668 curr_pipe = pipes[i]; 9669 /* set current stream */ 9670 curr_pipe->stream = curr_stream; 9671 9672 if (!atomisp_hw_is_isp2401) { 9673 /* take over effective info */ 9674 9675 effective_res = curr_pipe->config.input_effective_res; 9676 err = ia_css_util_check_res( 9677 effective_res.width, 9678 effective_res.height); 9679 if (err != IA_CSS_SUCCESS) 9680 goto ERR; 9681 } 9682 /* sensor binning per pipe */ 9683 if (sensor_binning_changed) 9684 sh_css_pipe_free_shading_table(curr_pipe); 9685 } 9686 9687 /* now pipes have been configured, info should be available */ 9688 for (i = 0; i < num_pipes; i++) 9689 { 9690 struct ia_css_pipe_info *pipe_info = NULL; 9691 9692 curr_pipe = pipes[i]; 9693 9694 err = sh_css_pipe_load_binaries(curr_pipe); 9695 if (err != IA_CSS_SUCCESS) 9696 goto ERR; 9697 9698 /* handle each pipe */ 9699 pipe_info = &curr_pipe->info; 9700 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { 9701 err = sh_css_pipe_get_output_frame_info(curr_pipe, 9702 &pipe_info->output_info[j], j); 9703 if (err != IA_CSS_SUCCESS) 9704 goto ERR; 9705 } 9706 9707 if (atomisp_hw_is_isp2401) 9708 pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res; 9709 9710 if (!spcopyonly) { 9711 if (!atomisp_hw_is_isp2401) 9712 err = sh_css_pipe_get_shading_info(curr_pipe, 9713 &pipe_info->shading_info, NULL); 9714 else 9715 err = sh_css_pipe_get_shading_info(curr_pipe, 9716 &pipe_info->shading_info, &curr_pipe->config); 9717 9718 if (err != IA_CSS_SUCCESS) 9719 goto ERR; 9720 err = sh_css_pipe_get_grid_info(curr_pipe, 9721 &pipe_info->grid_info); 9722 if (err != IA_CSS_SUCCESS) 9723 goto ERR; 9724 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { 9725 sh_css_pipe_get_viewfinder_frame_info(curr_pipe, 9726 &pipe_info->vf_output_info[j], j); 9727 if (err != IA_CSS_SUCCESS) 9728 goto ERR; 9729 } 9730 } 9731 9732 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe; 9733 } 9734 9735 curr_stream->started = false; 9736 9737 /* Map SP threads before doing anything. */ 9738 err = map_sp_threads(curr_stream, true); 9739 if (err != IA_CSS_SUCCESS) 9740 { 9741 IA_CSS_LOG("map_sp_threads: return_err=%d", err); 9742 goto ERR; 9743 } 9744 9745 for (i = 0; i < num_pipes; i++) 9746 { 9747 curr_pipe = pipes[i]; 9748 ia_css_pipe_map_queue(curr_pipe, true); 9749 } 9750 9751 /* Create host side pipeline objects without stages */ 9752 err = create_host_pipeline_structure(curr_stream); 9753 if (err != IA_CSS_SUCCESS) 9754 { 9755 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err); 9756 goto ERR; 9757 } 9758 9759 /* assign curr_stream */ 9760 *stream = curr_stream; 9761 9762 ERR: 9763 if (err == IA_CSS_SUCCESS) { 9764 /* working mode: enter into the seed list */ 9765 if (my_css_save.mode == sh_css_mode_working) { 9766 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { 9767 if (!my_css_save.stream_seeds[i].stream) { 9768 IA_CSS_LOG("entered stream into loc=%d", i); 9769 my_css_save.stream_seeds[i].orig_stream = stream; 9770 my_css_save.stream_seeds[i].stream = curr_stream; 9771 my_css_save.stream_seeds[i].num_pipes = num_pipes; 9772 my_css_save.stream_seeds[i].stream_config = *stream_config; 9773 for (j = 0; j < num_pipes; j++) { 9774 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config; 9775 my_css_save.stream_seeds[i].pipes[j] = pipes[j]; 9776 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j]; 9777 } 9778 break; 9779 } 9780 } 9781 } else { 9782 ia_css_stream_destroy(curr_stream); 9783 } 9784 } else { 9785 ia_css_stream_destroy(curr_stream); 9786 } 9787 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode); 9788 return err; 9789 } 9790 9791 enum ia_css_err 9792 ia_css_stream_destroy(struct ia_css_stream *stream) { 9793 int i; 9794 enum ia_css_err err = IA_CSS_SUCCESS; 9795 9796 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 9797 if (!stream) 9798 { 9799 err = IA_CSS_ERR_INVALID_ARGUMENTS; 9800 IA_CSS_LEAVE_ERR_PRIVATE(err); 9801 return err; 9802 } 9803 9804 ia_css_stream_isp_parameters_uninit(stream); 9805 9806 if ((stream->last_pipe) && 9807 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) 9808 { 9809 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 9810 bool free_mpi; 9811 9812 for (i = 0; i < stream->num_pipes; i++) { 9813 struct ia_css_pipe *entry = stream->pipes[i]; 9814 unsigned int sp_thread_id; 9815 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal; 9816 9817 assert(entry); 9818 if (entry) { 9819 /* get the SP thread id */ 9820 if (ia_css_pipeline_get_sp_thread_id( 9821 ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true) 9822 return IA_CSS_ERR_INTERNAL_ERROR; 9823 /* get the target input terminal */ 9824 sp_pipeline_input_terminal = 9825 &sh_css_sp_group.pipe_io[sp_thread_id].input; 9826 9827 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) { 9828 ia_css_isys_stream_h isys_stream = 9829 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]; 9830 if (stream->config.isys_config[i].valid && isys_stream->valid) 9831 ia_css_isys_stream_destroy(isys_stream); 9832 } 9833 } 9834 } 9835 free_mpi = stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; 9836 if (atomisp_hw_is_isp2401) { 9837 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_TPG; 9838 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_PRBS; 9839 } 9840 9841 if (free_mpi) { 9842 for (i = 0; i < stream->num_pipes; i++) { 9843 struct ia_css_pipe *entry = stream->pipes[i]; 9844 /* free any mipi frames that are remaining: 9845 * some test stream create-destroy cycles do not generate output frames 9846 * and the mipi buffer is not freed in the deque function 9847 */ 9848 if (entry) 9849 free_mipi_frames(entry); 9850 } 9851 } 9852 stream_unregister_with_csi_rx(stream); 9853 #endif 9854 9855 for (i = 0; i < stream->num_pipes; i++) { 9856 struct ia_css_pipe *curr_pipe = stream->pipes[i]; 9857 9858 assert(curr_pipe); 9859 ia_css_pipe_map_queue(curr_pipe, false); 9860 } 9861 9862 err = map_sp_threads(stream, false); 9863 if (err != IA_CSS_SUCCESS) { 9864 IA_CSS_LEAVE_ERR_PRIVATE(err); 9865 return err; 9866 } 9867 } 9868 9869 /* remove references from pipes to stream */ 9870 for (i = 0; i < stream->num_pipes; i++) 9871 { 9872 struct ia_css_pipe *entry = stream->pipes[i]; 9873 9874 assert(entry); 9875 if (entry) { 9876 /* clear reference to stream */ 9877 entry->stream = NULL; 9878 /* check internal copy pipe */ 9879 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW && 9880 entry->pipe_settings.preview.copy_pipe) { 9881 IA_CSS_LOG("clearing stream on internal preview copy pipe"); 9882 entry->pipe_settings.preview.copy_pipe->stream = NULL; 9883 } 9884 if (entry->mode == IA_CSS_PIPE_ID_VIDEO && 9885 entry->pipe_settings.video.copy_pipe) { 9886 IA_CSS_LOG("clearing stream on internal video copy pipe"); 9887 entry->pipe_settings.video.copy_pipe->stream = NULL; 9888 } 9889 err = sh_css_pipe_unload_binaries(entry); 9890 } 9891 } 9892 /* free associated memory of stream struct */ 9893 kfree(stream->pipes); 9894 stream->pipes = NULL; 9895 stream->num_pipes = 0; 9896 9897 /* working mode: take out of the seed list */ 9898 if (my_css_save.mode == sh_css_mode_working) { 9899 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { 9900 if (my_css_save.stream_seeds[i].stream == stream) 9901 { 9902 IA_CSS_LOG("took out stream %d", i); 9903 my_css_save.stream_seeds[i].stream = NULL; 9904 break; 9905 } 9906 } 9907 } 9908 9909 kfree(stream); 9910 IA_CSS_LEAVE_ERR(err); 9911 9912 return err; 9913 } 9914 9915 enum ia_css_err 9916 ia_css_stream_get_info(const struct ia_css_stream *stream, 9917 struct ia_css_stream_info *stream_info) { 9918 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n"); 9919 assert(stream); 9920 assert(stream_info); 9921 9922 *stream_info = stream->info; 9923 return IA_CSS_SUCCESS; 9924 } 9925 9926 /* 9927 * Rebuild a stream, including allocating structs, setting configuration and 9928 * building the required pipes. 9929 * The data is taken from the css_save struct updated upon stream creation. 9930 * The stream handle is used to identify the correct entry in the css_save struct 9931 */ 9932 enum ia_css_err 9933 ia_css_stream_load(struct ia_css_stream *stream) { 9934 9935 if (!atomisp_hw_is_isp2401) { 9936 int i; 9937 enum ia_css_err err; 9938 9939 assert(stream); 9940 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n"); 9941 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) 9942 { 9943 if (my_css_save.stream_seeds[i].stream == stream) { 9944 int j; 9945 9946 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) { 9947 if ((err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j], 9948 &my_css_save.stream_seeds[i].pipes[j])) != IA_CSS_SUCCESS) { 9949 if (j) { 9950 int k; 9951 9952 for (k = 0; k < j; k++) 9953 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]); 9954 } 9955 return err; 9956 } 9957 } 9958 err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config, 9959 my_css_save.stream_seeds[i].num_pipes, 9960 my_css_save.stream_seeds[i].pipes, 9961 &my_css_save.stream_seeds[i].stream); 9962 if (err != IA_CSS_SUCCESS) { 9963 ia_css_stream_destroy(stream); 9964 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) 9965 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]); 9966 return err; 9967 } 9968 break; 9969 } 9970 } 9971 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n"); 9972 return IA_CSS_SUCCESS; 9973 } else { 9974 /* TODO remove function - DEPRECATED */ 9975 (void)stream; 9976 return IA_CSS_ERR_NOT_SUPPORTED; 9977 } 9978 } 9979 9980 enum ia_css_err 9981 ia_css_stream_start(struct ia_css_stream *stream) { 9982 enum ia_css_err err = IA_CSS_SUCCESS; 9983 9984 IA_CSS_ENTER("stream = %p", stream); 9985 if ((!stream) || (!stream->last_pipe)) 9986 { 9987 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); 9988 return IA_CSS_ERR_INVALID_ARGUMENTS; 9989 } 9990 IA_CSS_LOG("starting %d", stream->last_pipe->mode); 9991 9992 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf); 9993 9994 /* Create host side pipeline. */ 9995 err = create_host_pipeline(stream); 9996 if (err != IA_CSS_SUCCESS) 9997 { 9998 IA_CSS_LEAVE_ERR(err); 9999 return err; 10000 } 10001 10002 #if !defined(HAS_NO_INPUT_SYSTEM) 10003 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 10004 if ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) || 10005 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)) 10006 stream_register_with_csi_rx(stream); 10007 #endif 10008 #endif 10009 10010 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) 10011 /* Initialize mipi size checks */ 10012 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 10013 { 10014 unsigned int idx; 10015 unsigned int port = (unsigned int)(stream->config.source.port.port); 10016 10017 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) { 10018 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 10019 sh_css_get_mipi_sizes_for_check(port, idx); 10020 } 10021 } 10022 #endif 10023 10024 #if !defined(HAS_NO_INPUT_SYSTEM) 10025 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) 10026 { 10027 err = sh_css_config_input_network(stream); 10028 if (err != IA_CSS_SUCCESS) 10029 return err; 10030 } 10031 #endif /* !HAS_NO_INPUT_SYSTEM */ 10032 10033 err = sh_css_pipe_start(stream); 10034 IA_CSS_LEAVE_ERR(err); 10035 return err; 10036 } 10037 10038 enum ia_css_err 10039 ia_css_stream_stop(struct ia_css_stream *stream) { 10040 enum ia_css_err err = IA_CSS_SUCCESS; 10041 10042 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n"); 10043 assert(stream); 10044 assert(stream->last_pipe); 10045 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n", 10046 stream->last_pipe->mode); 10047 10048 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) 10049 /* De-initialize mipi size checks */ 10050 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 10051 { 10052 unsigned int idx; 10053 unsigned int port = (unsigned int)(stream->config.source.port.port); 10054 10055 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) { 10056 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0; 10057 } 10058 } 10059 #endif 10060 10061 if (!atomisp_hw_is_isp2401) { 10062 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline); 10063 } else { 10064 err = sh_css_pipes_stop(stream); 10065 } 10066 10067 if (err != IA_CSS_SUCCESS) 10068 return err; 10069 10070 /* Ideally, unmapping should happen after pipeline_stop, but current 10071 * semantics do not allow that. */ 10072 /* err = map_sp_threads(stream, false); */ 10073 10074 return err; 10075 } 10076 10077 bool 10078 ia_css_stream_has_stopped(struct ia_css_stream *stream) { 10079 bool stopped; 10080 10081 assert(stream); 10082 10083 if (!atomisp_hw_is_isp2401) { 10084 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline); 10085 } else { 10086 stopped = sh_css_pipes_have_stopped(stream); 10087 } 10088 10089 return stopped; 10090 } 10091 10092 /* ISP2400 */ 10093 /* 10094 * Destroy the stream and all the pipes related to it. 10095 * The stream handle is used to identify the correct entry in the css_save struct 10096 */ 10097 enum ia_css_err 10098 ia_css_stream_unload(struct ia_css_stream *stream) { 10099 int i; 10100 10101 assert(stream); 10102 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n"); 10103 /* some checks */ 10104 assert(stream); 10105 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) 10106 if (my_css_save.stream_seeds[i].stream == stream) 10107 { 10108 int j; 10109 10110 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 10111 "ia_css_stream_unload(): unloading %d (%p)\n", i, 10112 my_css_save.stream_seeds[i].stream); 10113 ia_css_stream_destroy(stream); 10114 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) 10115 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]); 10116 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 10117 "ia_css_stream_unload(): after unloading %d (%p)\n", i, 10118 my_css_save.stream_seeds[i].stream); 10119 break; 10120 } 10121 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n"); 10122 return IA_CSS_SUCCESS; 10123 } 10124 10125 enum ia_css_err 10126 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, 10127 enum ia_css_pipe_id *pipe_id) { 10128 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n"); 10129 if (pipe) 10130 *pipe_id = pipe->mode; 10131 else 10132 *pipe_id = IA_CSS_PIPE_ID_COPY; 10133 10134 return IA_CSS_SUCCESS; 10135 } 10136 10137 enum atomisp_input_format 10138 ia_css_stream_get_format(const struct ia_css_stream *stream) { 10139 return stream->config.input_config.format; 10140 } 10141 10142 bool 10143 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) { 10144 return (stream->config.pixels_per_clock == 2); 10145 } 10146 10147 struct ia_css_binary * 10148 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream 10149 *stream) { 10150 struct ia_css_pipe *pipe; 10151 10152 assert(stream); 10153 10154 pipe = stream->pipes[0]; 10155 10156 if (stream->num_pipes == 2) { 10157 assert(stream->pipes[1]); 10158 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO || 10159 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 10160 pipe = stream->pipes[1]; 10161 } 10162 10163 return ia_css_pipe_get_shading_correction_binary(pipe); 10164 } 10165 10166 struct ia_css_binary * 10167 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) { 10168 int i; 10169 struct ia_css_pipe *video_pipe = NULL; 10170 10171 /* First we find the video pipe */ 10172 for (i = 0; i < stream->num_pipes; i++) { 10173 struct ia_css_pipe *pipe = stream->pipes[i]; 10174 10175 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) { 10176 video_pipe = pipe; 10177 break; 10178 } 10179 } 10180 if (video_pipe) 10181 return &video_pipe->pipe_settings.video.video_binary; 10182 return NULL; 10183 } 10184 10185 struct ia_css_binary * 10186 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) { 10187 struct ia_css_pipe *pipe; 10188 struct ia_css_binary *s3a_binary = NULL; 10189 10190 assert(stream); 10191 10192 pipe = stream->pipes[0]; 10193 10194 if (stream->num_pipes == 2) { 10195 assert(stream->pipes[1]); 10196 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO || 10197 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 10198 pipe = stream->pipes[1]; 10199 } 10200 10201 s3a_binary = ia_css_pipe_get_s3a_binary(pipe); 10202 10203 return s3a_binary; 10204 } 10205 10206 enum ia_css_err 10207 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, 10208 unsigned int output_padded_width) { 10209 struct ia_css_pipe *pipe; 10210 10211 assert(stream); 10212 10213 pipe = stream->last_pipe; 10214 10215 assert(pipe); 10216 10217 /* set the config also just in case (redundant info? why do we save config in pipe?) */ 10218 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width; 10219 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width; 10220 10221 return IA_CSS_SUCCESS; 10222 } 10223 10224 static struct ia_css_binary * 10225 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) { 10226 struct ia_css_binary *binary = NULL; 10227 10228 assert(pipe); 10229 10230 switch (pipe->config.mode) { 10231 case IA_CSS_PIPE_MODE_PREVIEW: 10232 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary; 10233 break; 10234 case IA_CSS_PIPE_MODE_VIDEO: 10235 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 10236 break; 10237 case IA_CSS_PIPE_MODE_CAPTURE: 10238 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 10239 unsigned int i; 10240 10241 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 10242 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) { 10243 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i]; 10244 break; 10245 } 10246 } 10247 } else if (pipe->config.default_capture_config.mode == 10248 IA_CSS_CAPTURE_MODE_BAYER) 10249 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 10250 else if (pipe->config.default_capture_config.mode == 10251 IA_CSS_CAPTURE_MODE_ADVANCED || 10252 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { 10253 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) 10254 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 10255 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2) 10256 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary; 10257 } 10258 break; 10259 default: 10260 break; 10261 } 10262 10263 if (binary && binary->info->sp.enable.sc) 10264 return binary; 10265 10266 return NULL; 10267 } 10268 10269 static struct ia_css_binary * 10270 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) { 10271 struct ia_css_binary *binary = NULL; 10272 10273 assert(pipe); 10274 10275 switch (pipe->config.mode) { 10276 case IA_CSS_PIPE_MODE_PREVIEW: 10277 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary; 10278 break; 10279 case IA_CSS_PIPE_MODE_VIDEO: 10280 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 10281 break; 10282 case IA_CSS_PIPE_MODE_CAPTURE: 10283 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 10284 unsigned int i; 10285 10286 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 10287 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) { 10288 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i]; 10289 break; 10290 } 10291 } 10292 } else if (pipe->config.default_capture_config.mode == 10293 IA_CSS_CAPTURE_MODE_BAYER) 10294 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 10295 else if (pipe->config.default_capture_config.mode == 10296 IA_CSS_CAPTURE_MODE_ADVANCED || 10297 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { 10298 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) 10299 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 10300 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2) 10301 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary; 10302 else 10303 assert(0); 10304 } 10305 break; 10306 default: 10307 break; 10308 } 10309 10310 if (binary && !binary->info->sp.enable.s3a) 10311 binary = NULL; 10312 10313 return binary; 10314 } 10315 10316 static struct ia_css_binary * 10317 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) { 10318 struct ia_css_binary *binary = NULL; 10319 10320 assert(pipe); 10321 10322 switch (pipe->config.mode) { 10323 case IA_CSS_PIPE_MODE_VIDEO: 10324 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 10325 break; 10326 default: 10327 break; 10328 } 10329 10330 if (binary && !binary->info->sp.enable.dis) 10331 binary = NULL; 10332 10333 return binary; 10334 } 10335 10336 struct ia_css_pipeline * 10337 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) { 10338 assert(pipe); 10339 10340 return (struct ia_css_pipeline *)&pipe->pipeline; 10341 } 10342 10343 unsigned int 10344 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) { 10345 assert(pipe); 10346 10347 /* KW was not sure this function was not returning a value 10348 that was out of range; so added an assert, and, for the 10349 case when asserts are not enabled, clip to the largest 10350 value; pipe_num is unsigned so the value cannot be too small 10351 */ 10352 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX); 10353 10354 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX) 10355 return (IA_CSS_PIPELINE_NUM_MAX - 1); 10356 10357 return pipe->pipe_num; 10358 } 10359 10360 unsigned int 10361 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) { 10362 assert(pipe); 10363 10364 return (unsigned int)pipe->config.isp_pipe_version; 10365 } 10366 10367 #define SP_START_TIMEOUT_US 30000000 10368 10369 enum ia_css_err 10370 ia_css_start_sp(void) { 10371 unsigned long timeout; 10372 enum ia_css_err err = IA_CSS_SUCCESS; 10373 10374 IA_CSS_ENTER(""); 10375 sh_css_sp_start_isp(); 10376 10377 /* waiting for the SP is completely started */ 10378 timeout = SP_START_TIMEOUT_US; 10379 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) 10380 { 10381 timeout--; 10382 hrt_sleep(); 10383 } 10384 if (timeout == 0) 10385 { 10386 IA_CSS_ERROR("timeout during SP initialization"); 10387 return IA_CSS_ERR_INTERNAL_ERROR; 10388 } 10389 10390 /* Workaround, in order to run two streams in parallel. See TASK 4271*/ 10391 /* TODO: Fix this. */ 10392 10393 sh_css_init_host_sp_control_vars(); 10394 10395 /* buffers should be initialized only when sp is started */ 10396 /* AM: At the moment it will be done only when there is no stream active. */ 10397 10398 sh_css_setup_queues(); 10399 ia_css_bufq_dump_queue_info(); 10400 10401 IA_CSS_LEAVE_ERR(err); 10402 return err; 10403 } 10404 10405 /* 10406 * Time to wait SP for termincate. Only condition when this can happen 10407 * is a fatal hw failure, but we must be able to detect this and emit 10408 * a proper error trace. 10409 */ 10410 #define SP_SHUTDOWN_TIMEOUT_US 200000 10411 10412 enum ia_css_err 10413 ia_css_stop_sp(void) { 10414 unsigned long timeout; 10415 enum ia_css_err err = IA_CSS_SUCCESS; 10416 10417 IA_CSS_ENTER("void"); 10418 10419 if (!sh_css_sp_is_running()) 10420 { 10421 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10422 IA_CSS_LEAVE("SP already stopped : return_err=%d", err); 10423 10424 /* Return an error - stop SP should not have been called by driver */ 10425 return err; 10426 } 10427 10428 /* For now, stop whole SP */ 10429 if (!atomisp_hw_is_isp2401) { 10430 sh_css_write_host2sp_command(host2sp_cmd_terminate); 10431 } else { 10432 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) 10433 { 10434 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); 10435 ia_css_debug_dump_sp_sw_debug_info(); 10436 ia_css_debug_dump_debug_info(NULL); 10437 } 10438 } 10439 10440 sh_css_sp_set_sp_running(false); 10441 10442 timeout = SP_SHUTDOWN_TIMEOUT_US; 10443 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) 10444 { 10445 timeout--; 10446 hrt_sleep(); 10447 } 10448 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED)) 10449 IA_CSS_WARNING("SP has not terminated (SW)"); 10450 10451 if (timeout == 0) 10452 { 10453 IA_CSS_WARNING("SP is not idle"); 10454 ia_css_debug_dump_sp_sw_debug_info(); 10455 } 10456 timeout = SP_SHUTDOWN_TIMEOUT_US; 10457 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) 10458 { 10459 timeout--; 10460 hrt_sleep(); 10461 } 10462 if (timeout == 0) 10463 { 10464 IA_CSS_WARNING("ISP is not idle"); 10465 ia_css_debug_dump_sp_sw_debug_info(); 10466 } 10467 10468 sh_css_hmm_buffer_record_uninit(); 10469 10470 /* clear pending param sets from refcount */ 10471 sh_css_param_clear_param_sets(); 10472 10473 IA_CSS_LEAVE_ERR(err); 10474 return err; 10475 } 10476 10477 enum ia_css_err 10478 ia_css_update_continuous_frames(struct ia_css_stream *stream) { 10479 struct ia_css_pipe *pipe; 10480 unsigned int i; 10481 10482 ia_css_debug_dtrace( 10483 IA_CSS_DEBUG_TRACE, 10484 "sh_css_update_continuous_frames() enter:\n"); 10485 10486 if (!stream) 10487 { 10488 ia_css_debug_dtrace( 10489 IA_CSS_DEBUG_TRACE, 10490 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n"); 10491 return IA_CSS_ERR_INVALID_ARGUMENTS; 10492 } 10493 10494 pipe = stream->continuous_pipe; 10495 10496 for (i = stream->config.init_num_cont_raw_buf; 10497 i < stream->config.target_num_cont_raw_buf; i++) 10498 { 10499 sh_css_update_host2sp_offline_frame(i, 10500 pipe->continuous_frames[i], pipe->cont_md_buffers[i]); 10501 } 10502 sh_css_update_host2sp_cont_num_raw_frames 10503 (stream->config.target_num_cont_raw_buf, true); 10504 ia_css_debug_dtrace( 10505 IA_CSS_DEBUG_TRACE, 10506 "sh_css_update_continuous_frames() leave: return_void\n"); 10507 10508 return IA_CSS_SUCCESS; 10509 } 10510 10511 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) { 10512 unsigned int thread_id; 10513 enum ia_css_pipe_id pipe_id; 10514 unsigned int pipe_num; 10515 bool need_input_queue; 10516 10517 IA_CSS_ENTER(""); 10518 assert(pipe); 10519 10520 pipe_id = pipe->mode; 10521 pipe_num = pipe->pipe_num; 10522 10523 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 10524 10525 #if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401) 10526 need_input_queue = true; 10527 #else 10528 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 10529 #endif 10530 10531 /* map required buffer queues to resources */ 10532 /* TODO: to be improved */ 10533 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) { 10534 if (need_input_queue) 10535 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10536 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10537 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10538 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 10539 #if defined SH_CSS_ENABLE_METADATA 10540 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10541 #endif 10542 if (pipe->pipe_settings.preview.preview_binary.info && 10543 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a) 10544 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 10545 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) { 10546 unsigned int i; 10547 10548 if (need_input_queue) 10549 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10550 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10551 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); 10552 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10553 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 10554 #if defined SH_CSS_ENABLE_METADATA 10555 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10556 #endif 10557 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 10558 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 10559 if (pipe->pipe_settings.capture.primary_binary[i].info && 10560 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) { 10561 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 10562 break; 10563 } 10564 } 10565 } else if (pipe->config.default_capture_config.mode == 10566 IA_CSS_CAPTURE_MODE_ADVANCED || 10567 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT || 10568 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) { 10569 if (pipe->pipe_settings.capture.pre_isp_binary.info && 10570 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a) 10571 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 10572 } 10573 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) { 10574 if (need_input_queue) 10575 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10576 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10577 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) 10578 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); 10579 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10580 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 10581 #if defined SH_CSS_ENABLE_METADATA 10582 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10583 #endif 10584 if (pipe->pipe_settings.video.video_binary.info && 10585 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a) 10586 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 10587 if (pipe->pipe_settings.video.video_binary.info && 10588 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis 10589 )) 10590 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map); 10591 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) { 10592 if (need_input_queue) 10593 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10594 if (!pipe->stream->config.continuous) 10595 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10596 #if defined SH_CSS_ENABLE_METADATA 10597 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10598 #endif 10599 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) { 10600 if (need_input_queue) 10601 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10602 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 10603 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10604 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 10605 #if defined SH_CSS_ENABLE_METADATA 10606 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10607 #endif 10608 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) { 10609 unsigned int idx; 10610 10611 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) { 10612 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map); 10613 if (pipe->enable_viewfinder[idx]) 10614 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map); 10615 } 10616 if (need_input_queue) 10617 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 10618 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 10619 #if defined SH_CSS_ENABLE_METADATA 10620 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 10621 #endif 10622 } 10623 IA_CSS_LEAVE(""); 10624 } 10625 10626 #if CONFIG_ON_FRAME_ENQUEUE() 10627 static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info 10628 *info, struct frame_data_wrapper *frame) { 10629 frame->config_on_frame_enqueue.padded_width = 0; 10630 10631 /* currently we support configuration on frame enqueue only on YUV formats */ 10632 /* on other formats the padded_width is zeroed for no configuration override */ 10633 switch (info->format) { 10634 case IA_CSS_FRAME_FORMAT_YUV420: 10635 case IA_CSS_FRAME_FORMAT_NV12: 10636 if (info->padded_width > info->res.width) { 10637 frame->config_on_frame_enqueue.padded_width = info->padded_width; 10638 } else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) { 10639 return IA_CSS_ERR_INVALID_ARGUMENTS; 10640 } 10641 /* nothing to do if width == padded width or padded width is zeroed (the same) */ 10642 break; 10643 default: 10644 break; 10645 } 10646 10647 return IA_CSS_SUCCESS; 10648 } 10649 #endif 10650 10651 enum ia_css_err 10652 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) { 10653 enum ia_css_err ret; 10654 10655 IA_CSS_ENTER(""); 10656 10657 /* Only continuous streams have a tagger to which we can send the 10658 * unlock message. */ 10659 if (!stream || !stream->config.continuous) 10660 { 10661 IA_CSS_ERROR("invalid stream pointer"); 10662 return IA_CSS_ERR_INVALID_ARGUMENTS; 10663 } 10664 10665 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID || 10666 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) 10667 { 10668 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id); 10669 return IA_CSS_ERR_INVALID_ARGUMENTS; 10670 } 10671 10672 /* Send the event. Since we verified that the exp_id is valid, 10673 * we can safely assign it to an 8-bit argument here. */ 10674 ret = ia_css_bufq_enqueue_psys_event( 10675 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0); 10676 10677 IA_CSS_LEAVE_ERR(ret); 10678 return ret; 10679 } 10680 10681 /* @brief Set the state (Enable or Disable) of the Extension stage in the 10682 * given pipe. 10683 */ 10684 enum ia_css_err 10685 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, 10686 bool enable) { 10687 unsigned int thread_id; 10688 struct ia_css_pipeline_stage *stage; 10689 enum ia_css_err err = IA_CSS_SUCCESS; 10690 10691 IA_CSS_ENTER(""); 10692 10693 /* Parameter Check */ 10694 if (!pipe || !pipe->stream) 10695 { 10696 IA_CSS_ERROR("Invalid Pipe."); 10697 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10698 } else if (!(pipe->config.acc_extension)) 10699 { 10700 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)"); 10701 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10702 } else if (!sh_css_sp_is_running()) 10703 { 10704 IA_CSS_ERROR("Leaving: queue unavailable."); 10705 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 10706 } else 10707 { 10708 /* Query the threadid and stage_num for the Extension firmware*/ 10709 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 10710 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); 10711 if (err == IA_CSS_SUCCESS) { 10712 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/ 10713 err = ia_css_bufq_enqueue_psys_event( 10714 (uint8_t)IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE, 10715 (uint8_t)thread_id, 10716 (uint8_t)stage->stage_num, 10717 enable ? 1 : 0); 10718 if (err == IA_CSS_SUCCESS) { 10719 if (enable) 10720 SH_CSS_QOS_STAGE_ENABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num); 10721 else 10722 SH_CSS_QOS_STAGE_DISABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num); 10723 } 10724 } 10725 } 10726 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable); 10727 return err; 10728 } 10729 10730 /* @brief Get the state (Enable or Disable) of the Extension stage in the 10731 * given pipe. 10732 */ 10733 enum ia_css_err 10734 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, 10735 bool *enable) { 10736 struct ia_css_pipeline_stage *stage; 10737 unsigned int thread_id; 10738 enum ia_css_err err = IA_CSS_SUCCESS; 10739 10740 IA_CSS_ENTER(""); 10741 10742 /* Parameter Check */ 10743 if (!pipe || !pipe->stream) 10744 { 10745 IA_CSS_ERROR("Invalid Pipe."); 10746 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10747 } else if (!(pipe->config.acc_extension)) 10748 { 10749 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); 10750 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10751 } else if (!sh_css_sp_is_running()) 10752 { 10753 IA_CSS_ERROR("Leaving: queue unavailable."); 10754 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 10755 } else 10756 { 10757 /* Query the threadid and stage_num corresponding to the Extension firmware*/ 10758 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 10759 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); 10760 10761 if (err == IA_CSS_SUCCESS) { 10762 /* Get the Extension State */ 10763 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id], 10764 stage->stage_num)) ? true : false; 10765 } 10766 } 10767 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable); 10768 return err; 10769 } 10770 10771 /* ISP2401 */ 10772 enum ia_css_err 10773 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, 10774 uint32_t fw_handle, 10775 struct ia_css_isp_param_css_segments *css_seg, 10776 struct ia_css_isp_param_isp_segments *isp_seg) { 10777 unsigned int HIVE_ADDR_sp_group; 10778 static struct sh_css_sp_group sp_group; 10779 static struct sh_css_sp_stage sp_stage; 10780 static struct sh_css_isp_stage isp_stage; 10781 const struct ia_css_fw_info *fw; 10782 unsigned int thread_id; 10783 struct ia_css_pipeline_stage *stage; 10784 enum ia_css_err err = IA_CSS_SUCCESS; 10785 int stage_num = 0; 10786 enum ia_css_isp_memories mem; 10787 bool enabled; 10788 10789 IA_CSS_ENTER(""); 10790 10791 fw = &sh_css_sp_fw; 10792 10793 /* Parameter Check */ 10794 if (!pipe || !pipe->stream) 10795 { 10796 IA_CSS_ERROR("Invalid Pipe."); 10797 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10798 } else if (!(pipe->config.acc_extension)) 10799 { 10800 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); 10801 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10802 } else if (!sh_css_sp_is_running()) 10803 { 10804 IA_CSS_ERROR("Leaving: queue unavailable."); 10805 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 10806 } else 10807 { 10808 /* Query the thread_id and stage_num corresponding to the Extension firmware */ 10809 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 10810 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); 10811 if (err == IA_CSS_SUCCESS) { 10812 /* Get the Extension State */ 10813 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id], 10814 stage->stage_num)) ? true : false; 10815 /* Update mapped arg only when extension stage is not enabled */ 10816 if (enabled) { 10817 IA_CSS_ERROR("Leaving: cannot update when stage is enabled."); 10818 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; 10819 } else { 10820 stage_num = stage->stage_num; 10821 10822 HIVE_ADDR_sp_group = fw->info.sp.group; 10823 sp_dmem_load(SP0_ID, 10824 (unsigned int)sp_address_of(sp_group), 10825 &sp_group, sizeof(struct sh_css_sp_group)); 10826 hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num], 10827 &sp_stage, sizeof(struct sh_css_sp_stage)); 10828 10829 hmm_load(sp_stage.isp_stage_addr, 10830 &isp_stage, sizeof(struct sh_css_isp_stage)); 10831 10832 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) { 10833 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address = 10834 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address; 10835 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size = 10836 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size; 10837 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address 10838 = 10839 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address; 10840 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size 10841 = 10842 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size; 10843 } 10844 10845 hmm_store(sp_stage.isp_stage_addr, 10846 &isp_stage, sizeof(struct sh_css_isp_stage)); 10847 } 10848 } 10849 } 10850 IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle); 10851 return err; 10852 } 10853 10854 #ifdef USE_INPUT_SYSTEM_VERSION_2401 10855 static enum ia_css_err 10856 aspect_ratio_crop_init(struct ia_css_stream *curr_stream, 10857 struct ia_css_pipe *pipes[], 10858 bool *do_crop_status) { 10859 enum ia_css_err err = IA_CSS_SUCCESS; 10860 int i; 10861 struct ia_css_pipe *curr_pipe; 10862 u32 pipe_mask = 0; 10863 10864 if ((!curr_stream) || 10865 (curr_stream->num_pipes == 0) || 10866 (!pipes) || 10867 (!do_crop_status)) 10868 { 10869 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10870 IA_CSS_LEAVE_ERR(err); 10871 return err; 10872 } 10873 10874 for (i = 0; i < curr_stream->num_pipes; i++) 10875 { 10876 curr_pipe = pipes[i]; 10877 pipe_mask |= (1 << curr_pipe->config.mode); 10878 } 10879 10880 *do_crop_status = 10881 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) || 10882 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) && 10883 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) && 10884 curr_stream->config.continuous); 10885 return IA_CSS_SUCCESS; 10886 } 10887 10888 static bool 10889 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) { 10890 bool status = false; 10891 10892 if ((curr_pipe) && enabled) { 10893 if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) || 10894 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) || 10895 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE)) 10896 status = true; 10897 } 10898 10899 return status; 10900 } 10901 10902 static enum ia_css_err 10903 aspect_ratio_crop(struct ia_css_pipe *curr_pipe, 10904 struct ia_css_resolution *effective_res) { 10905 enum ia_css_err err = IA_CSS_SUCCESS; 10906 struct ia_css_resolution crop_res; 10907 struct ia_css_resolution *in_res = NULL; 10908 struct ia_css_resolution *out_res = NULL; 10909 bool use_bds_output_info = false; 10910 bool use_vf_pp_in_res = false; 10911 bool use_capt_pp_in_res = false; 10912 10913 if ((!curr_pipe) || 10914 (!effective_res)) 10915 { 10916 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10917 IA_CSS_LEAVE_ERR(err); 10918 return err; 10919 } 10920 10921 if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) && 10922 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) && 10923 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) 10924 { 10925 err = IA_CSS_ERR_INVALID_ARGUMENTS; 10926 IA_CSS_LEAVE_ERR(err); 10927 return err; 10928 } 10929 10930 use_bds_output_info = 10931 ((curr_pipe->bds_output_info.res.width != 0) && 10932 (curr_pipe->bds_output_info.res.height != 0)); 10933 10934 use_vf_pp_in_res = 10935 ((curr_pipe->config.vf_pp_in_res.width != 0) && 10936 (curr_pipe->config.vf_pp_in_res.height != 0)); 10937 10938 use_capt_pp_in_res = 10939 ((curr_pipe->config.capt_pp_in_res.width != 0) && 10940 (curr_pipe->config.capt_pp_in_res.height != 0)); 10941 10942 in_res = &curr_pipe->stream->config.input_config.effective_res; 10943 out_res = &curr_pipe->output_info[0].res; 10944 10945 switch (curr_pipe->config.mode) 10946 { 10947 case IA_CSS_PIPE_MODE_PREVIEW: 10948 if (use_bds_output_info) 10949 out_res = &curr_pipe->bds_output_info.res; 10950 else if (use_vf_pp_in_res) 10951 out_res = &curr_pipe->config.vf_pp_in_res; 10952 break; 10953 case IA_CSS_PIPE_MODE_VIDEO: 10954 if (use_bds_output_info) 10955 out_res = &curr_pipe->bds_output_info.res; 10956 break; 10957 case IA_CSS_PIPE_MODE_CAPTURE: 10958 if (use_capt_pp_in_res) 10959 out_res = &curr_pipe->config.capt_pp_in_res; 10960 break; 10961 case IA_CSS_PIPE_MODE_ACC: 10962 case IA_CSS_PIPE_MODE_COPY: 10963 case IA_CSS_PIPE_MODE_YUVPP: 10964 default: 10965 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n", 10966 curr_pipe->config.mode); 10967 assert(0); 10968 break; 10969 } 10970 10971 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res); 10972 if (err == IA_CSS_SUCCESS) 10973 { 10974 *effective_res = crop_res; 10975 } else 10976 { 10977 /* in case of error fallback to default 10978 * effective resolution from driver. */ 10979 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err); 10980 } 10981 return err; 10982 } 10983 #endif 10984 10985 static void 10986 sh_css_hmm_buffer_record_init(void) { 10987 int i; 10988 10989 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) 10990 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]); 10991 } 10992 10993 static void 10994 sh_css_hmm_buffer_record_uninit(void) { 10995 int i; 10996 struct sh_css_hmm_buffer_record *buffer_record = NULL; 10997 10998 buffer_record = &hmm_buffer_record[0]; 10999 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 11000 if (buffer_record->in_use) { 11001 if (buffer_record->h_vbuf) 11002 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf); 11003 sh_css_hmm_buffer_record_reset(buffer_record); 11004 } 11005 buffer_record++; 11006 } 11007 } 11008 11009 static void 11010 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) { 11011 assert(buffer_record); 11012 buffer_record->in_use = false; 11013 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID; 11014 buffer_record->h_vbuf = NULL; 11015 buffer_record->kernel_ptr = 0; 11016 } 11017 11018 static struct sh_css_hmm_buffer_record 11019 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf, 11020 enum ia_css_buffer_type type, 11021 hrt_address kernel_ptr) { 11022 int i; 11023 struct sh_css_hmm_buffer_record *buffer_record = NULL; 11024 struct sh_css_hmm_buffer_record *out_buffer_record = NULL; 11025 11026 assert(h_vbuf); 11027 assert((type > IA_CSS_BUFFER_TYPE_INVALID) && 11028 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE)); 11029 assert(kernel_ptr != 0); 11030 11031 buffer_record = &hmm_buffer_record[0]; 11032 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 11033 if (!buffer_record->in_use) { 11034 buffer_record->in_use = true; 11035 buffer_record->type = type; 11036 buffer_record->h_vbuf = h_vbuf; 11037 buffer_record->kernel_ptr = kernel_ptr; 11038 out_buffer_record = buffer_record; 11039 break; 11040 } 11041 buffer_record++; 11042 } 11043 11044 return out_buffer_record; 11045 } 11046 11047 static struct sh_css_hmm_buffer_record 11048 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr, 11049 enum ia_css_buffer_type type) { 11050 int i; 11051 struct sh_css_hmm_buffer_record *buffer_record = NULL; 11052 bool found_record = false; 11053 11054 buffer_record = &hmm_buffer_record[0]; 11055 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 11056 if ((buffer_record->in_use) && 11057 (buffer_record->type == type) && 11058 (buffer_record->h_vbuf) && 11059 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) { 11060 found_record = true; 11061 break; 11062 } 11063 buffer_record++; 11064 } 11065 11066 if (found_record) 11067 return buffer_record; 11068 else 11069 return NULL; 11070 } 11071