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