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