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