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