FILE
sh_css.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/media/atomisp/pci/sh_css.c
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/vmalloc.h> 11 12#include "hmm.h" 13 14#include "atomisp_internal.h" 15 16#include "ia_css.h" 17#include "sh_css_hrt.h" /* only for file 2 MIPI */ 18#include "ia_css_buffer.h" 19#include "ia_css_binary.h" 20#include "sh_css_internal.h" 21#include "sh_css_mipi.h" 22#include "sh_css_sp.h" /* sh_css_sp_group */ 23#include "ia_css_isys.h" 24#include "ia_css_frame.h" 25#include "sh_css_defs.h" 26#include "sh_css_firmware.h" 27#include "sh_css_params.h" 28#include "sh_css_params_internal.h" 29#include "sh_css_param_shading.h" 30#include "ia_css_refcount.h" 31#include "ia_css_rmgr.h" 32#include "ia_css_debug.h" 33#include "ia_css_debug_pipe.h" 34#include "ia_css_device_access.h" 35#include "device_access.h" 36#include "sh_css_legacy.h" 37#include "ia_css_pipeline.h" 38#include "ia_css_stream.h" 39#include "sh_css_stream_format.h" 40#include "ia_css_pipe.h" 41#include "ia_css_util.h" 42#include "ia_css_pipe_util.h" 43#include "ia_css_pipe_binarydesc.h" 44#include "ia_css_pipe_stagedesc.h" 45 46#include "tag.h" 47#include "assert_support.h" 48#include "math_support.h" 49#include "sw_event_global.h" /* Event IDs.*/ 50#include "ia_css_ifmtr.h" 51#include "input_system.h" 52#include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */ 53#include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */ 54#include "gdc_device.h" /* HRT_GDC_N */ 55#include "dma.h" /* dma_set_max_burst_size() */ 56#include "irq.h" /* virq */ 57#include "sp.h" /* cnd_sp_irq_enable() */ 58#include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */ 59#include "gp_device.h" /* gp_device_reg_store() */ 60#include <gpio_global.h> 61#include <gpio_private.h> 62#include "timed_ctrl.h" 63#include "ia_css_inputfifo.h" 64#define WITH_PC_MONITORING 0 65 66#define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0 67 68 69#include "ia_css_spctrl.h" 70#include "ia_css_version_data.h" 71#include "sh_css_struct.h" 72#include "ia_css_bufq.h" 73#include "ia_css_timer.h" /* clock_value_t */ 74 75#include "isp/modes/interface/input_buf.isp.h" 76 77/* Name of the sp program: should not be built-in */ 78#define SP_PROG_NAME "sp" 79/* Size of Refcount List */ 80#define REFCOUNT_SIZE 1000 81 82/* 83 * for JPEG, we don't know the length of the image upfront, 84 * but since we support sensor up to 16MP, we take this as 85 * upper limit. 86 */ 87#define JPEG_BYTES (16 * 1024 * 1024) 88 89struct sh_css my_css; 90 91int __printf(1, 0) (*sh_css_printf)(const char *fmt, va_list args) = NULL; 92 93/* 94 * modes of work: stream_create and stream_destroy will update the save/restore 95 * data only when in working mode, not suspend/resume 96 */ 97enum ia_sh_css_modes { 98 sh_css_mode_none = 0, 99 sh_css_mode_working, 100 sh_css_mode_suspend, 101 sh_css_mode_resume 102}; 103 104/** 105 * struct sh_css_stream_seed - a stream seed, to save and restore the 106 * stream data. 107 * 108 * @orig_stream: pointer to restore the original handle 109 * @stream: handle, used as ID too. 110 * @stream_config: stream config struct 111 * @num_pipes: number of pipes 112 * @pipes: pipe handles 113 * @orig_pipes: pointer to restore original handle 114 * @pipe_config: pipe config structs 115 * 116 * the stream seed contains all the data required to "grow" the seed again 117 * after it was closed. 118*/ 119struct sh_css_stream_seed { 120 struct ia_css_stream **orig_stream; 121 struct ia_css_stream *stream; 122 struct ia_css_stream_config stream_config; 123 int num_pipes; 124 struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; 125 struct ia_css_pipe **orig_pipes[IA_CSS_PIPE_ID_NUM]; 126 struct ia_css_pipe_config pipe_config[IA_CSS_PIPE_ID_NUM]; 127}; 128 129#define MAX_ACTIVE_STREAMS 5 130/* 131 * A global struct for save/restore to hold all the data that should 132 * sustain power-down: MMU base, IRQ type, env for routines, binary loaded FW 133 * and the stream seeds. 134 */ 135struct sh_css_save { 136 enum ia_sh_css_modes mode; 137 u32 mmu_base; /* the last mmu_base */ 138 enum ia_css_irq_type irq_type; 139 struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS]; 140 struct ia_css_fw *loaded_fw; /* fw struct previously loaded */ 141 struct ia_css_env driver_env; /* driver-supplied env copy */ 142}; 143 144static bool my_css_save_initialized; /* if my_css_save was initialized */ 145static struct sh_css_save my_css_save; 146 147/* 148 * pqiao NOTICE: this is for css internal buffer recycling when stopping 149 * pipeline, 150 * this array is temporary and will be replaced by resource manager 151 */ 152 153/* Taking the biggest Size for number of Elements */ 154#define MAX_HMM_BUFFER_NUM \ 155 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2)) 156 157struct sh_css_hmm_buffer_record { 158 bool in_use; 159 enum ia_css_buffer_type type; 160 struct ia_css_rmgr_vbuf_handle *h_vbuf; 161 hrt_address kernel_ptr; 162}; 163 164static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM]; 165 166#define GPIO_FLASH_PIN_MASK BIT(HIVE_GPIO_STROBE_TRIGGER_PIN) 167 168/* 169 * Local prototypes 170 */ 171 172static int 173allocate_delay_frames(struct ia_css_pipe *pipe); 174 175static int 176sh_css_pipe_start(struct ia_css_stream *stream); 177 178/* 179 * @brief Check if all "ia_css_pipe" instances in the target 180 * "ia_css_stream" instance have stopped. 181 * 182 * @param[in] stream Point to the target "ia_css_stream" instance. 183 * 184 * @return 185 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream" 186 * instance have ben stopped. 187 * - false, otherwise. 188 */ 189 190/* ISP 2401 */ 191static int 192ia_css_pipe_check_format(struct ia_css_pipe *pipe, 193 enum ia_css_frame_format format); 194 195/* ISP 2401 */ 196static void 197ia_css_reset_defaults(struct sh_css *css); 198 199static void 200sh_css_init_host_sp_control_vars(void); 201 202static int 203set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version); 204 205static bool 206need_capture_pp(const struct ia_css_pipe *pipe); 207 208static bool 209need_yuv_scaler_stage(const struct ia_css_pipe *pipe); 210 211static int ia_css_pipe_create_cas_scaler_desc_single_output( 212 struct ia_css_frame_info *cas_scaler_in_info, 213 struct ia_css_frame_info *cas_scaler_out_info, 214 struct ia_css_frame_info *cas_scaler_vf_info, 215 struct ia_css_cas_binary_descr *descr); 216 217static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr 218 *descr); 219 220static bool 221need_downscaling(const struct ia_css_resolution in_res, 222 const struct ia_css_resolution out_res); 223 224static bool need_capt_ldc(const struct ia_css_pipe *pipe); 225 226static int 227sh_css_pipe_load_binaries(struct ia_css_pipe *pipe); 228 229static 230int sh_css_pipe_get_viewfinder_frame_info( 231 struct ia_css_pipe *pipe, 232 struct ia_css_frame_info *info, 233 unsigned int idx); 234 235static int 236sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, 237 struct ia_css_frame_info *info, 238 unsigned int idx); 239 240static int 241capture_start(struct ia_css_pipe *pipe); 242 243static int 244video_start(struct ia_css_pipe *pipe); 245 246static int 247preview_start(struct ia_css_pipe *pipe); 248 249static int 250yuvpp_start(struct ia_css_pipe *pipe); 251 252static bool copy_on_sp(struct ia_css_pipe *pipe); 253 254static int 255init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, 256 struct ia_css_frame *vf_frame, unsigned int idx); 257 258static int 259init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe, 260 struct ia_css_frame *frame, enum ia_css_frame_format format); 261 262static int 263init_out_frameinfo_defaults(struct ia_css_pipe *pipe, 264 struct ia_css_frame *out_frame, unsigned int idx); 265 266static int 267alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time); 268 269static void 270pipe_global_init(void); 271 272static int 273pipe_generate_pipe_num(const struct ia_css_pipe *pipe, 274 unsigned int *pipe_number); 275 276static void 277pipe_release_pipe_num(unsigned int pipe_num); 278 279static int 280create_host_pipeline_structure(struct ia_css_stream *stream); 281 282static int 283create_host_pipeline(struct ia_css_stream *stream); 284 285static int 286create_host_preview_pipeline(struct ia_css_pipe *pipe); 287 288static int 289create_host_video_pipeline(struct ia_css_pipe *pipe); 290 291static int 292create_host_copy_pipeline(struct ia_css_pipe *pipe, 293 unsigned int max_input_width, 294 struct ia_css_frame *out_frame); 295 296static int 297create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe); 298 299static int 300create_host_capture_pipeline(struct ia_css_pipe *pipe); 301 302static int 303create_host_yuvpp_pipeline(struct ia_css_pipe *pipe); 304 305static unsigned int 306sh_css_get_sw_interrupt_value(unsigned int irq); 307 308static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary( 309 const struct ia_css_pipe *pipe); 310 311static struct ia_css_binary * 312ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe); 313 314static struct ia_css_binary * 315ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe); 316 317static void 318sh_css_hmm_buffer_record_init(void); 319 320static void 321sh_css_hmm_buffer_record_uninit(void); 322 323static void 324sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record); 325 326static struct sh_css_hmm_buffer_record 327*sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf, 328 enum ia_css_buffer_type type, 329 hrt_address kernel_ptr); 330 331static struct sh_css_hmm_buffer_record 332*sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr, 333 enum ia_css_buffer_type type); 334 335static unsigned int get_crop_lines_for_bayer_order(const struct 336 ia_css_stream_config *config); 337static unsigned int get_crop_columns_for_bayer_order(const struct 338 ia_css_stream_config *config); 339static void get_pipe_extra_pixel(struct ia_css_pipe *pipe, 340 unsigned int *extra_row, unsigned int *extra_column); 341 342static void 343sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe) 344{ 345 if (!pipe) { 346 IA_CSS_ERROR("NULL input parameter"); 347 return; 348 } 349 350 if (pipe->shading_table) 351 ia_css_shading_table_free(pipe->shading_table); 352 pipe->shading_table = NULL; 353} 354 355static enum ia_css_frame_format yuv420_copy_formats[] = { 356 IA_CSS_FRAME_FORMAT_NV12, 357 IA_CSS_FRAME_FORMAT_NV21, 358 IA_CSS_FRAME_FORMAT_YV12, 359 IA_CSS_FRAME_FORMAT_YUV420, 360 IA_CSS_FRAME_FORMAT_YUV420_16, 361 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8, 362 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8 363}; 364 365static enum ia_css_frame_format yuv422_copy_formats[] = { 366 IA_CSS_FRAME_FORMAT_NV12, 367 IA_CSS_FRAME_FORMAT_NV16, 368 IA_CSS_FRAME_FORMAT_NV21, 369 IA_CSS_FRAME_FORMAT_NV61, 370 IA_CSS_FRAME_FORMAT_YV12, 371 IA_CSS_FRAME_FORMAT_YV16, 372 IA_CSS_FRAME_FORMAT_YUV420, 373 IA_CSS_FRAME_FORMAT_YUV420_16, 374 IA_CSS_FRAME_FORMAT_YUV422, 375 IA_CSS_FRAME_FORMAT_YUV422_16, 376 IA_CSS_FRAME_FORMAT_UYVY, 377 IA_CSS_FRAME_FORMAT_YUYV 378}; 379 380/* 381 * Verify whether the selected output format is can be produced 382 * by the copy binary given the stream format. 383 */ 384static int 385verify_copy_out_frame_format(struct ia_css_pipe *pipe) 386{ 387 enum ia_css_frame_format out_fmt = pipe->output_info[0].format; 388 unsigned int i, found = 0; 389 390 assert(pipe); 391 assert(pipe->stream); 392 393 switch (pipe->stream->config.input_config.format) { 394 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: 395 case ATOMISP_INPUT_FORMAT_YUV420_8: 396 for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++) 397 found = (out_fmt == yuv420_copy_formats[i]); 398 break; 399 case ATOMISP_INPUT_FORMAT_YUV420_10: 400 case ATOMISP_INPUT_FORMAT_YUV420_16: 401 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16); 402 break; 403 case ATOMISP_INPUT_FORMAT_YUV422_8: 404 for (i = 0; i < ARRAY_SIZE(yuv422_copy_formats) && !found; i++) 405 found = (out_fmt == yuv422_copy_formats[i]); 406 break; 407 case ATOMISP_INPUT_FORMAT_YUV422_10: 408 case ATOMISP_INPUT_FORMAT_YUV422_16: 409 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 || 410 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16); 411 break; 412 case ATOMISP_INPUT_FORMAT_RGB_444: 413 case ATOMISP_INPUT_FORMAT_RGB_555: 414 case ATOMISP_INPUT_FORMAT_RGB_565: 415 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 || 416 out_fmt == IA_CSS_FRAME_FORMAT_RGB565); 417 break; 418 case ATOMISP_INPUT_FORMAT_RGB_666: 419 case ATOMISP_INPUT_FORMAT_RGB_888: 420 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 || 421 out_fmt == IA_CSS_FRAME_FORMAT_YUV420); 422 break; 423 case ATOMISP_INPUT_FORMAT_RAW_6: 424 case ATOMISP_INPUT_FORMAT_RAW_7: 425 case ATOMISP_INPUT_FORMAT_RAW_8: 426 case ATOMISP_INPUT_FORMAT_RAW_10: 427 case ATOMISP_INPUT_FORMAT_RAW_12: 428 case ATOMISP_INPUT_FORMAT_RAW_14: 429 case ATOMISP_INPUT_FORMAT_RAW_16: 430 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) || 431 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED); 432 break; 433 case ATOMISP_INPUT_FORMAT_BINARY_8: 434 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8); 435 break; 436 default: 437 break; 438 } 439 if (!found) 440 return -EINVAL; 441 return 0; 442} 443 444unsigned int 445ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream) 446{ 447 int bpp = 0; 448 449 if (stream) 450 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format, 451 stream->config.pixels_per_clock == 2); 452 453 return bpp; 454} 455 456static int 457sh_css_config_input_network_2400(struct ia_css_stream *stream) 458{ 459 unsigned int fmt_type; 460 struct ia_css_pipe *pipe = stream->last_pipe; 461 struct ia_css_binary *binary = NULL; 462 int err = 0; 463 464 assert(stream); 465 assert(pipe); 466 467 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 468 "sh_css_config_input_network() enter:\n"); 469 470 if (pipe->pipeline.stages) 471 binary = pipe->pipeline.stages->binary; 472 473 err = ia_css_isys_convert_stream_format_to_mipi_format( 474 stream->config.input_config.format, 475 stream->csi_rx_config.comp, 476 &fmt_type); 477 if (err) 478 return err; 479 sh_css_sp_program_input_circuit(fmt_type, 480 stream->config.channel_id, 481 stream->config.mode); 482 483 if ((binary && (binary->online || stream->config.continuous)) || 484 pipe->config.mode == IA_CSS_PIPE_MODE_COPY) { 485 err = ia_css_ifmtr_configure(&stream->config, 486 binary); 487 if (err) 488 return err; 489 } 490 491 if (stream->config.mode == IA_CSS_INPUT_MODE_PRBS) { 492 unsigned int width, height, vblank_cycles; 493 const unsigned int hblank_cycles = 100; 494 const unsigned int vblank_lines = 6; 495 496 width = (stream->config.input_config.input_res.width) / 497 (1 + (stream->config.pixels_per_clock == 2)); 498 height = stream->config.input_config.input_res.height; 499 vblank_cycles = vblank_lines * (width + hblank_cycles); 500 sh_css_sp_configure_sync_gen(width, height, hblank_cycles, vblank_cycles); 501 } 502 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 503 "sh_css_config_input_network() leave:\n"); 504 return 0; 505} 506 507static unsigned int csi2_protocol_calculate_max_subpixels_per_line( 508 enum atomisp_input_format format, 509 unsigned int pixels_per_line) 510{ 511 unsigned int rval; 512 513 switch (format) { 514 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: 515 /* 516 * The frame format layout is shown below. 517 * 518 * Line 0: UYY0 UYY0 ... UYY0 519 * Line 1: VYY0 VYY0 ... VYY0 520 * Line 2: UYY0 UYY0 ... UYY0 521 * Line 3: VYY0 VYY0 ... VYY0 522 * ... 523 * Line (n-2): UYY0 UYY0 ... UYY0 524 * Line (n-1): VYY0 VYY0 ... VYY0 525 * 526 * In this frame format, the even-line is 527 * as wide as the odd-line. 528 * The 0 is introduced by the input system 529 * (mipi backend). 530 */ 531 rval = pixels_per_line * 2; 532 break; 533 case ATOMISP_INPUT_FORMAT_YUV420_8: 534 case ATOMISP_INPUT_FORMAT_YUV420_10: 535 case ATOMISP_INPUT_FORMAT_YUV420_16: 536 /* 537 * The frame format layout is shown below. 538 * 539 * Line 0: YYYY YYYY ... YYYY 540 * Line 1: UYVY UYVY ... UYVY UYVY 541 * Line 2: YYYY YYYY ... YYYY 542 * Line 3: UYVY UYVY ... UYVY UYVY 543 * ... 544 * Line (n-2): YYYY YYYY ... YYYY 545 * Line (n-1): UYVY UYVY ... UYVY UYVY 546 * 547 * In this frame format, the odd-line is twice 548 * wider than the even-line. 549 */ 550 rval = pixels_per_line * 2; 551 break; 552 case ATOMISP_INPUT_FORMAT_YUV422_8: 553 case ATOMISP_INPUT_FORMAT_YUV422_10: 554 case ATOMISP_INPUT_FORMAT_YUV422_16: 555 /* 556 * The frame format layout is shown below. 557 * 558 * Line 0: UYVY UYVY ... UYVY 559 * Line 1: UYVY UYVY ... UYVY 560 * Line 2: UYVY UYVY ... UYVY 561 * Line 3: UYVY UYVY ... UYVY 562 * ... 563 * Line (n-2): UYVY UYVY ... UYVY 564 * Line (n-1): UYVY UYVY ... UYVY 565 * 566 * In this frame format, the even-line is 567 * as wide as the odd-line. 568 */ 569 rval = pixels_per_line * 2; 570 break; 571 case ATOMISP_INPUT_FORMAT_RGB_444: 572 case ATOMISP_INPUT_FORMAT_RGB_555: 573 case ATOMISP_INPUT_FORMAT_RGB_565: 574 case ATOMISP_INPUT_FORMAT_RGB_666: 575 case ATOMISP_INPUT_FORMAT_RGB_888: 576 /* 577 * The frame format layout is shown below. 578 * 579 * Line 0: ABGR ABGR ... ABGR 580 * Line 1: ABGR ABGR ... ABGR 581 * Line 2: ABGR ABGR ... ABGR 582 * Line 3: ABGR ABGR ... ABGR 583 * ... 584 * Line (n-2): ABGR ABGR ... ABGR 585 * Line (n-1): ABGR ABGR ... ABGR 586 * 587 * In this frame format, the even-line is 588 * as wide as the odd-line. 589 */ 590 rval = pixels_per_line * 4; 591 break; 592 case ATOMISP_INPUT_FORMAT_RAW_6: 593 case ATOMISP_INPUT_FORMAT_RAW_7: 594 case ATOMISP_INPUT_FORMAT_RAW_8: 595 case ATOMISP_INPUT_FORMAT_RAW_10: 596 case ATOMISP_INPUT_FORMAT_RAW_12: 597 case ATOMISP_INPUT_FORMAT_RAW_14: 598 case ATOMISP_INPUT_FORMAT_RAW_16: 599 case ATOMISP_INPUT_FORMAT_BINARY_8: 600 case ATOMISP_INPUT_FORMAT_USER_DEF1: 601 case ATOMISP_INPUT_FORMAT_USER_DEF2: 602 case ATOMISP_INPUT_FORMAT_USER_DEF3: 603 case ATOMISP_INPUT_FORMAT_USER_DEF4: 604 case ATOMISP_INPUT_FORMAT_USER_DEF5: 605 case ATOMISP_INPUT_FORMAT_USER_DEF6: 606 case ATOMISP_INPUT_FORMAT_USER_DEF7: 607 case ATOMISP_INPUT_FORMAT_USER_DEF8: 608 /* 609 * The frame format layout is shown below. 610 * 611 * Line 0: Pixel ... Pixel 612 * Line 1: Pixel ... Pixel 613 * Line 2: Pixel ... Pixel 614 * Line 3: Pixel ... Pixel 615 * ... 616 * Line (n-2): Pixel ... Pixel 617 * Line (n-1): Pixel ... Pixel 618 * 619 * In this frame format, the even-line is 620 * as wide as the odd-line. 621 */ 622 rval = pixels_per_line; 623 break; 624 default: 625 rval = 0; 626 break; 627 } 628 629 return rval; 630} 631 632static bool sh_css_translate_stream_cfg_to_input_system_input_port_id( 633 struct ia_css_stream_config *stream_cfg, 634 ia_css_isys_descr_t *isys_stream_descr) 635{ 636 bool rc; 637 638 rc = true; 639 switch (stream_cfg->mode) { 640 case IA_CSS_INPUT_MODE_PRBS: 641 642 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) 643 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID; 644 else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) 645 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID; 646 else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) 647 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID; 648 649 break; 650 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: 651 652 if (stream_cfg->source.port.port == MIPI_PORT0_ID) 653 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID; 654 else if (stream_cfg->source.port.port == MIPI_PORT1_ID) 655 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID; 656 else if (stream_cfg->source.port.port == MIPI_PORT2_ID) 657 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID; 658 659 break; 660 default: 661 rc = false; 662 break; 663 } 664 665 return rc; 666} 667 668static bool sh_css_translate_stream_cfg_to_input_system_input_port_type( 669 struct ia_css_stream_config *stream_cfg, 670 ia_css_isys_descr_t *isys_stream_descr) 671{ 672 bool rc; 673 674 rc = true; 675 switch (stream_cfg->mode) { 676 case IA_CSS_INPUT_MODE_PRBS: 677 678 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS; 679 680 break; 681 case IA_CSS_INPUT_MODE_SENSOR: 682 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: 683 684 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR; 685 break; 686 687 default: 688 rc = false; 689 break; 690 } 691 692 return rc; 693} 694 695static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr( 696 struct ia_css_stream_config *stream_cfg, 697 ia_css_isys_descr_t *isys_stream_descr, 698 int isys_stream_idx) 699{ 700 bool rc; 701 702 rc = true; 703 switch (stream_cfg->mode) { 704 case IA_CSS_INPUT_MODE_PRBS: 705 706 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed; 707 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1; 708 709 /* 710 * TODO 711 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config". 712 */ 713 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100; 714 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100; 715 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock = 716 stream_cfg->pixels_per_clock; 717 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0); 718 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line = 719 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width; 720 isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame = 721 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height; 722 723 break; 724 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: { 725 int err; 726 unsigned int fmt_type; 727 728 err = ia_css_isys_convert_stream_format_to_mipi_format( 729 stream_cfg->isys_config[isys_stream_idx].format, 730 MIPI_PREDICTOR_NONE, 731 &fmt_type); 732 if (err) 733 rc = false; 734 735 isys_stream_descr->csi_port_attr.active_lanes = 736 stream_cfg->source.port.num_lanes; 737 isys_stream_descr->csi_port_attr.fmt_type = fmt_type; 738 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id; 739 740 if (IS_ISP2401) 741 isys_stream_descr->online = stream_cfg->online; 742 743 err |= ia_css_isys_convert_compressed_format( 744 &stream_cfg->source.port.compression, 745 isys_stream_descr); 746 if (err) 747 rc = false; 748 749 /* metadata */ 750 isys_stream_descr->metadata.enable = false; 751 if (stream_cfg->metadata_config.resolution.height > 0) { 752 err = ia_css_isys_convert_stream_format_to_mipi_format( 753 stream_cfg->metadata_config.data_type, 754 MIPI_PREDICTOR_NONE, 755 &fmt_type); 756 if (err) 757 rc = false; 758 isys_stream_descr->metadata.fmt_type = fmt_type; 759 isys_stream_descr->metadata.bits_per_pixel = 760 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true); 761 isys_stream_descr->metadata.pixels_per_line = 762 stream_cfg->metadata_config.resolution.width; 763 isys_stream_descr->metadata.lines_per_frame = 764 stream_cfg->metadata_config.resolution.height; 765 766 /* 767 * For new input system, number of str2mmio requests must be even. 768 * So we round up number of metadata lines to be even. 769 */ 770 if (IS_ISP2401 && isys_stream_descr->metadata.lines_per_frame > 0) 771 isys_stream_descr->metadata.lines_per_frame += 772 (isys_stream_descr->metadata.lines_per_frame & 1); 773 774 isys_stream_descr->metadata.align_req_in_bytes = 775 ia_css_csi2_calculate_input_system_alignment( 776 stream_cfg->metadata_config.data_type); 777 isys_stream_descr->metadata.enable = true; 778 } 779 780 break; 781 } 782 default: 783 rc = false; 784 break; 785 } 786 787 return rc; 788} 789 790static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution( 791 struct ia_css_stream_config *stream_cfg, 792 ia_css_isys_descr_t *isys_stream_descr, 793 int isys_stream_idx) 794{ 795 unsigned int bits_per_subpixel; 796 unsigned int max_subpixels_per_line; 797 unsigned int lines_per_frame; 798 unsigned int align_req_in_bytes; 799 enum atomisp_input_format fmt_type; 800 801 fmt_type = stream_cfg->isys_config[isys_stream_idx].format; 802 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR || 803 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) && 804 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) { 805 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == 806 UNCOMPRESSED_BITS_PER_PIXEL_10) 807 fmt_type = ATOMISP_INPUT_FORMAT_RAW_10; 808 else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == 809 UNCOMPRESSED_BITS_PER_PIXEL_12) 810 fmt_type = ATOMISP_INPUT_FORMAT_RAW_12; 811 else 812 return false; 813 } 814 815 bits_per_subpixel = 816 sh_css_stream_format_2_bits_per_subpixel(fmt_type); 817 if (bits_per_subpixel == 0) 818 return false; 819 820 max_subpixels_per_line = 821 csi2_protocol_calculate_max_subpixels_per_line(fmt_type, 822 stream_cfg->isys_config[isys_stream_idx].input_res.width); 823 if (max_subpixels_per_line == 0) 824 return false; 825 826 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height; 827 if (lines_per_frame == 0) 828 return false; 829 830 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type); 831 832 /* HW needs subpixel info for their settings */ 833 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel; 834 isys_stream_descr->input_port_resolution.pixels_per_line = 835 max_subpixels_per_line; 836 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame; 837 isys_stream_descr->input_port_resolution.align_req_in_bytes = 838 align_req_in_bytes; 839 840 return true; 841} 842 843static bool sh_css_translate_stream_cfg_to_isys_stream_descr( 844 struct ia_css_stream_config *stream_cfg, 845 bool early_polling, 846 ia_css_isys_descr_t *isys_stream_descr, 847 int isys_stream_idx) 848{ 849 bool rc; 850 851 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 852 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n"); 853 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg, 854 isys_stream_descr); 855 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg, 856 isys_stream_descr); 857 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg, 858 isys_stream_descr, isys_stream_idx); 859 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution( 860 stream_cfg, isys_stream_descr, isys_stream_idx); 861 862 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels; 863 isys_stream_descr->linked_isys_stream_id = (int8_t) 864 stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id; 865 866 if (IS_ISP2401) 867 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 868 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n"); 869 870 return rc; 871} 872 873static bool sh_css_translate_binary_info_to_input_system_output_port_attr( 874 struct ia_css_binary *binary, 875 ia_css_isys_descr_t *isys_stream_descr) 876{ 877 if (!binary) 878 return false; 879 880 isys_stream_descr->output_port_attr.left_padding = binary->left_padding; 881 isys_stream_descr->output_port_attr.max_isp_input_width = 882 binary->info->sp.input.max_width; 883 884 return true; 885} 886 887static int 888sh_css_config_input_network_2401(struct ia_css_stream *stream) 889{ 890 bool rc; 891 ia_css_isys_descr_t isys_stream_descr; 892 unsigned int sp_thread_id; 893 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal; 894 struct ia_css_pipe *pipe = NULL; 895 struct ia_css_binary *binary = NULL; 896 int i; 897 u32 isys_stream_id; 898 bool early_polling = false; 899 900 assert(stream); 901 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 902 "sh_css_config_input_network() enter 0x%p:\n", stream); 903 904 if (stream->config.continuous) { 905 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) 906 pipe = stream->last_pipe; 907 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) 908 pipe = stream->last_pipe; 909 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 910 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe; 911 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) 912 pipe = stream->last_pipe->pipe_settings.video.copy_pipe; 913 } else { 914 pipe = stream->last_pipe; 915 } 916 917 if (!pipe) 918 return -EINVAL; 919 920 if (pipe->pipeline.stages) 921 if (pipe->pipeline.stages->binary) 922 binary = pipe->pipeline.stages->binary; 923 924 if (binary) { 925 /* 926 * this was being done in ifmtr in 2400. 927 * online and cont bypass the init_in_frameinfo_memory_defaults 928 * so need to do it here 929 */ 930 ia_css_get_crop_offsets(pipe, &binary->in_frame_info); 931 } 932 933 /* get the SP thread id */ 934 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id); 935 if (!rc) 936 return -EINVAL; 937 /* get the target input terminal */ 938 sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input; 939 940 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) { 941 /* initialization */ 942 memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t)); 943 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0; 944 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0; 945 946 if (!stream->config.isys_config[i].valid) 947 continue; 948 949 /* translate the stream configuration to the Input System (2401) configuration */ 950 rc = sh_css_translate_stream_cfg_to_isys_stream_descr( 951 &stream->config, 952 early_polling, 953 &(isys_stream_descr), i); 954 955 if (stream->config.online) { 956 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr( 957 binary, 958 &(isys_stream_descr)); 959 } 960 961 if (!rc) 962 return -EINVAL; 963 964 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i); 965 966 /* create the virtual Input System (2401) */ 967 rc = ia_css_isys_stream_create( 968 &(isys_stream_descr), 969 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i], 970 isys_stream_id); 971 if (!rc) 972 return -EINVAL; 973 974 /* calculate the configuration of the virtual Input System (2401) */ 975 rc = ia_css_isys_stream_calculate_cfg( 976 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i], 977 &(isys_stream_descr), 978 &sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]); 979 if (!rc) { 980 ia_css_isys_stream_destroy( 981 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]); 982 return -EINVAL; 983 } 984 } 985 986 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 987 "sh_css_config_input_network() leave:\n"); 988 989 return 0; 990} 991 992static inline struct ia_css_pipe *stream_get_last_pipe( 993 struct ia_css_stream *stream) 994{ 995 struct ia_css_pipe *last_pipe = NULL; 996 997 if (stream) 998 last_pipe = stream->last_pipe; 999 1000 return last_pipe; 1001} 1002 1003static inline struct ia_css_pipe *stream_get_copy_pipe( 1004 struct ia_css_stream *stream) 1005{ 1006 struct ia_css_pipe *copy_pipe = NULL; 1007 struct ia_css_pipe *last_pipe = NULL; 1008 enum ia_css_pipe_id pipe_id; 1009 1010 last_pipe = stream_get_last_pipe(stream); 1011 1012 if ((stream) && 1013 (last_pipe) && 1014 (stream->config.continuous)) { 1015 pipe_id = last_pipe->mode; 1016 switch (pipe_id) { 1017 case IA_CSS_PIPE_ID_PREVIEW: 1018 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe; 1019 break; 1020 case IA_CSS_PIPE_ID_VIDEO: 1021 copy_pipe = last_pipe->pipe_settings.video.copy_pipe; 1022 break; 1023 default: 1024 copy_pipe = NULL; 1025 break; 1026 } 1027 } 1028 1029 return copy_pipe; 1030} 1031 1032static inline struct ia_css_pipe *stream_get_target_pipe( 1033 struct ia_css_stream *stream) 1034{ 1035 struct ia_css_pipe *target_pipe; 1036 1037 /* get the pipe that consumes the stream */ 1038 if (stream->config.continuous) 1039 target_pipe = stream_get_copy_pipe(stream); 1040 else 1041 target_pipe = stream_get_last_pipe(stream); 1042 1043 return target_pipe; 1044} 1045 1046static int stream_csi_rx_helper( 1047 struct ia_css_stream *stream, 1048 int (*func)(enum mipi_port_id, uint32_t)) 1049{ 1050 int retval = -EINVAL; 1051 u32 sp_thread_id, stream_id; 1052 bool rc; 1053 struct ia_css_pipe *target_pipe = NULL; 1054 1055 if ((!stream) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)) 1056 goto exit; 1057 1058 target_pipe = stream_get_target_pipe(stream); 1059 1060 if (!target_pipe) 1061 goto exit; 1062 1063 rc = ia_css_pipeline_get_sp_thread_id( 1064 ia_css_pipe_get_pipe_num(target_pipe), 1065 &sp_thread_id); 1066 1067 if (!rc) 1068 goto exit; 1069 1070 /* (un)register all valid "virtual isys streams" within the ia_css_stream */ 1071 stream_id = 0; 1072 do { 1073 if (stream->config.isys_config[stream_id].valid) { 1074 u32 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id); 1075 1076 retval = func(stream->config.source.port.port, isys_stream_id); 1077 } 1078 stream_id++; 1079 } while ((retval == 0) && 1080 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)); 1081 1082exit: 1083 return retval; 1084} 1085 1086static inline int stream_register_with_csi_rx( 1087 struct ia_css_stream *stream) 1088{ 1089 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream); 1090} 1091 1092static inline int stream_unregister_with_csi_rx( 1093 struct ia_css_stream *stream) 1094{ 1095 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream); 1096} 1097 1098 1099static void 1100start_binary(struct ia_css_pipe *pipe, 1101 struct ia_css_binary *binary) 1102{ 1103 assert(pipe); 1104 /* Acceleration uses firmware, the binary thus can be NULL */ 1105 1106 if (binary) 1107 sh_css_metrics_start_binary(&binary->metrics); 1108 1109 if (!IS_ISP2401 && pipe->stream->reconfigure_css_rx) { 1110 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, 1111 pipe->stream->config.mode); 1112 pipe->stream->reconfigure_css_rx = false; 1113 } 1114} 1115 1116/* start the copy function on the SP */ 1117static int 1118start_copy_on_sp(struct ia_css_pipe *pipe, 1119 struct ia_css_frame *out_frame) 1120{ 1121 (void)out_frame; 1122 1123 if ((!pipe) || (!pipe->stream)) 1124 return -EINVAL; 1125 1126 if (!IS_ISP2401 && pipe->stream->reconfigure_css_rx) 1127 ia_css_isys_rx_disable(); 1128 1129 if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8) 1130 return -EINVAL; 1131 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2); 1132 1133 if (!IS_ISP2401 && pipe->stream->reconfigure_css_rx) { 1134 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, 1135 pipe->stream->config.mode); 1136 pipe->stream->reconfigure_css_rx = false; 1137 } 1138 1139 return 0; 1140} 1141 1142void sh_css_binary_args_reset(struct sh_css_binary_args *args) 1143{ 1144 unsigned int i; 1145 1146 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) 1147 args->tnr_frames[i] = NULL; 1148 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++) 1149 args->delay_frames[i] = NULL; 1150 args->in_frame = NULL; 1151 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) 1152 args->out_frame[i] = NULL; 1153 args->out_vf_frame = NULL; 1154 args->copy_vf = false; 1155 args->copy_output = true; 1156 args->vf_downscale_log2 = 0; 1157} 1158 1159static void start_pipe( 1160 struct ia_css_pipe *me, 1161 enum sh_css_pipe_config_override copy_ovrd, 1162 enum ia_css_input_mode input_mode) 1163{ 1164 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d", 1165 me, copy_ovrd, input_mode); 1166 1167 assert(me); /* all callers are in this file and call with non null argument */ 1168 1169 sh_css_sp_init_pipeline(&me->pipeline, 1170 me->mode, 1171 (uint8_t)ia_css_pipe_get_pipe_num(me), 1172 me->config.default_capture_config.enable_xnr != 0, 1173 me->stream->config.pixels_per_clock == 2, 1174 me->stream->config.continuous, 1175 false, 1176 me->required_bds_factor, 1177 copy_ovrd, 1178 input_mode, 1179 &me->stream->config.metadata_config, 1180 &me->stream->info.metadata_info 1181 , (input_mode == IA_CSS_INPUT_MODE_MEMORY) ? 1182 (enum mipi_port_id)0 : 1183 me->stream->config.source.port.port); 1184 1185 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) { 1186 struct ia_css_pipeline_stage *stage; 1187 1188 stage = me->pipeline.stages; 1189 if (stage) { 1190 me->pipeline.current_stage = stage; 1191 start_binary(me, stage->binary); 1192 } 1193 } 1194 IA_CSS_LEAVE_PRIVATE("void"); 1195} 1196 1197void 1198sh_css_invalidate_shading_tables(struct ia_css_stream *stream) 1199{ 1200 int i; 1201 1202 assert(stream); 1203 1204 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1205 "sh_css_invalidate_shading_tables() enter:\n"); 1206 1207 for (i = 0; i < stream->num_pipes; i++) { 1208 assert(stream->pipes[i]); 1209 sh_css_pipe_free_shading_table(stream->pipes[i]); 1210 } 1211 1212 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1213 "sh_css_invalidate_shading_tables() leave: return_void\n"); 1214} 1215 1216static void 1217enable_interrupts(enum ia_css_irq_type irq_type) 1218{ 1219 enum mipi_port_id port; 1220 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE; 1221 1222 IA_CSS_ENTER_PRIVATE(""); 1223 /* Enable IRQ on the SP which signals that SP goes to idle 1224 * (aka ready state) */ 1225 cnd_sp_irq_enable(SP0_ID, true); 1226 /* Set the IRQ device 0 to either level or pulse */ 1227 irq_enable_pulse(IRQ0_ID, enable_pulse); 1228 1229 cnd_virq_enable_channel(virq_sp, true); 1230 1231 /* Enable SW interrupt 0, this is used to signal ISYS events */ 1232 cnd_virq_enable_channel( 1233 (enum virq_id)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET), 1234 true); 1235 /* Enable SW interrupt 1, this is used to signal PSYS events */ 1236 cnd_virq_enable_channel( 1237 (enum virq_id)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET), 1238 true); 1239 1240 if (!IS_ISP2401) { 1241 for (port = 0; port < N_MIPI_PORT_ID; port++) 1242 ia_css_isys_rx_enable_all_interrupts(port); 1243 } 1244 1245 IA_CSS_LEAVE_PRIVATE(""); 1246} 1247 1248static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw, 1249 const char *program, 1250 ia_css_spctrl_cfg *spctrl_cfg) 1251{ 1252 if ((!fw) || (!spctrl_cfg)) 1253 return false; 1254 spctrl_cfg->sp_entry = 0; 1255 spctrl_cfg->program_name = (char *)(program); 1256 1257 spctrl_cfg->ddr_data_offset = fw->blob.data_source; 1258 spctrl_cfg->dmem_data_addr = fw->blob.data_target; 1259 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target; 1260 spctrl_cfg->data_size = fw->blob.data_size; 1261 spctrl_cfg->bss_size = fw->blob.bss_size; 1262 1263 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data; 1264 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state; 1265 1266 spctrl_cfg->code_size = fw->blob.size; 1267 spctrl_cfg->code = fw->blob.code; 1268 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */ 1269 1270 return true; 1271} 1272 1273void 1274ia_css_unload_firmware(void) 1275{ 1276 if (sh_css_num_binaries) { 1277 /* we have already loaded before so get rid of the old stuff */ 1278 ia_css_binary_uninit(); 1279 sh_css_unload_firmware(); 1280 } 1281} 1282 1283static void 1284ia_css_reset_defaults(struct sh_css *css) 1285{ 1286 struct sh_css default_css; 1287 1288 /* Reset everything to zero */ 1289 memset(&default_css, 0, sizeof(default_css)); 1290 1291 /* Initialize the non zero values */ 1292 default_css.check_system_idle = true; 1293 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES; 1294 1295 /* 1296 * All should be 0: but memset does it already. 1297 * default_css.num_mipi_frames[N_CSI_PORTS] = 0; 1298 */ 1299 1300 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE; 1301 1302 /* Set the defaults to the output */ 1303 *css = default_css; 1304} 1305 1306int 1307ia_css_load_firmware(struct device *dev, const struct ia_css_env *env, 1308 const struct ia_css_fw *fw) 1309{ 1310 int err; 1311 1312 if (!env) 1313 return -EINVAL; 1314 if (!fw) 1315 return -EINVAL; 1316 1317 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n"); 1318 1319 /* make sure we initialize my_css */ 1320 if (my_css.flush != env->cpu_mem_env.flush) { 1321 ia_css_reset_defaults(&my_css); 1322 my_css.flush = env->cpu_mem_env.flush; 1323 } 1324 1325 err = sh_css_load_firmware(dev, fw->data, fw->bytes); 1326 if (!err) 1327 err = ia_css_binary_init_infos(); 1328 1329 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave\n"); 1330 return err; 1331} 1332 1333int 1334ia_css_init(struct device *dev, const struct ia_css_env *env, 1335 u32 mmu_l1_base, enum ia_css_irq_type irq_type) 1336{ 1337 int err; 1338 ia_css_spctrl_cfg spctrl_cfg; 1339 void (*flush_func)(struct ia_css_acc_fw *fw); 1340 hrt_data select, enable; 1341 1342 if (!env) 1343 return -EINVAL; 1344 1345 sh_css_printf = env->print_env.debug_print; 1346 1347 IA_CSS_ENTER("void"); 1348 1349 flush_func = env->cpu_mem_env.flush; 1350 1351 pipe_global_init(); 1352 ia_css_pipeline_init(); 1353 ia_css_queue_map_init(); 1354 1355 ia_css_device_access_init(&env->hw_access_env); 1356 1357 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select) & ~GPIO_FLASH_PIN_MASK; 1358 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e) | GPIO_FLASH_PIN_MASK; 1359 sh_css_mmu_set_page_table_base_index(mmu_l1_base); 1360 1361 my_css_save.mmu_base = mmu_l1_base; 1362 1363 ia_css_reset_defaults(&my_css); 1364 1365 my_css_save.driver_env = *env; 1366 my_css.flush = flush_func; 1367 1368 err = ia_css_rmgr_init(); 1369 if (err) { 1370 IA_CSS_LEAVE_ERR(err); 1371 return err; 1372 } 1373 1374 IA_CSS_LOG("init: %d", my_css_save_initialized); 1375 1376 if (!my_css_save_initialized) { 1377 my_css_save_initialized = true; 1378 my_css_save.mode = sh_css_mode_working; 1379 memset(my_css_save.stream_seeds, 0, 1380 sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS); 1381 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode); 1382 } 1383 1384 mipi_init(); 1385 1386 /* 1387 * In case this has been programmed already, update internal 1388 * data structure ... 1389 * DEPRECATED 1390 */ 1391 if (!IS_ISP2401) 1392 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID); 1393 1394 my_css.irq_type = irq_type; 1395 1396 my_css_save.irq_type = irq_type; 1397 1398 enable_interrupts(my_css.irq_type); 1399 1400 /* configure GPIO to output mode */ 1401 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select); 1402 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable); 1403 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0); 1404 1405 err = ia_css_refcount_init(REFCOUNT_SIZE); 1406 if (err) { 1407 IA_CSS_LEAVE_ERR(err); 1408 return err; 1409 } 1410 err = sh_css_params_init(); 1411 if (err) { 1412 IA_CSS_LEAVE_ERR(err); 1413 return err; 1414 } 1415 1416 if (!sh_css_setup_spctrl_config(&sh_css_sp_fw, SP_PROG_NAME, &spctrl_cfg)) 1417 return -EINVAL; 1418 1419 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg); 1420 if (err) { 1421 IA_CSS_LEAVE_ERR(err); 1422 return err; 1423 } 1424 1425 if (!sh_css_hrt_system_is_idle()) { 1426 IA_CSS_LEAVE_ERR(-EBUSY); 1427 return -EBUSY; 1428 } 1429 /* 1430 * can be called here, queuing works, but: 1431 * - when sp is started later, it will wipe queued items 1432 * so for now we leave it for later and make sure 1433 * updates are not called to frequently. 1434 * sh_css_init_buffer_queues(); 1435 */ 1436 1437 if (IS_ISP2401) 1438 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1); 1439 1440 if (!IS_ISP2401) 1441 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, 1442 ISP2400_DMA_MAX_BURST_LENGTH); 1443 else 1444 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, 1445 ISP2401_DMA_MAX_BURST_LENGTH); 1446 1447 if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR) 1448 err = -EINVAL; 1449 1450 sh_css_params_map_and_store_default_gdc_lut(); 1451 1452 IA_CSS_LEAVE_ERR(err); 1453 return err; 1454} 1455 1456int 1457ia_css_enable_isys_event_queue(bool enable) 1458{ 1459 if (sh_css_sp_is_running()) 1460 return -EBUSY; 1461 sh_css_sp_enable_isys_event_queue(enable); 1462 return 0; 1463} 1464 1465/* 1466 * Mapping sp threads. Currently, this is done when a stream is created and 1467 * pipelines are ready to be converted to sp pipelines. Be careful if you are 1468 * doing it from stream_create since we could run out of sp threads due to 1469 * allocation on inactive pipelines. 1470 */ 1471static int 1472map_sp_threads(struct ia_css_stream *stream, bool map) 1473{ 1474 struct ia_css_pipe *main_pipe = NULL; 1475 struct ia_css_pipe *copy_pipe = NULL; 1476 struct ia_css_pipe *capture_pipe = NULL; 1477 int err = 0; 1478 enum ia_css_pipe_id pipe_id; 1479 1480 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s", 1481 stream, map ? "true" : "false"); 1482 1483 if (!stream) { 1484 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 1485 return -EINVAL; 1486 } 1487 1488 main_pipe = stream->last_pipe; 1489 pipe_id = main_pipe->mode; 1490 1491 ia_css_pipeline_map(main_pipe->pipe_num, map); 1492 1493 switch (pipe_id) { 1494 case IA_CSS_PIPE_ID_PREVIEW: 1495 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 1496 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; 1497 break; 1498 1499 case IA_CSS_PIPE_ID_VIDEO: 1500 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 1501 capture_pipe = main_pipe->pipe_settings.video.capture_pipe; 1502 break; 1503 1504 case IA_CSS_PIPE_ID_CAPTURE: 1505 default: 1506 break; 1507 } 1508 1509 if (capture_pipe) 1510 ia_css_pipeline_map(capture_pipe->pipe_num, map); 1511 1512 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */ 1513 if (copy_pipe) 1514 ia_css_pipeline_map(copy_pipe->pipe_num, map); 1515 1516 /* DH regular multi pipe - not continuous mode: map the next pipes too */ 1517 if (!stream->config.continuous) { 1518 int i; 1519 1520 for (i = 1; i < stream->num_pipes; i++) 1521 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map); 1522 } 1523 1524 IA_CSS_LEAVE_ERR_PRIVATE(err); 1525 return err; 1526} 1527 1528/* 1529 * creates a host pipeline skeleton for all pipes in a stream. Called during 1530 * stream_create. 1531 */ 1532static int 1533create_host_pipeline_structure(struct ia_css_stream *stream) 1534{ 1535 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL; 1536 enum ia_css_pipe_id pipe_id; 1537 struct ia_css_pipe *main_pipe = NULL; 1538 int err = 0; 1539 unsigned int copy_pipe_delay = 0, 1540 capture_pipe_delay = 0; 1541 1542 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 1543 1544 if (!stream) { 1545 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 1546 return -EINVAL; 1547 } 1548 1549 main_pipe = stream->last_pipe; 1550 if (!main_pipe) { 1551 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 1552 return -EINVAL; 1553 } 1554 1555 pipe_id = main_pipe->mode; 1556 1557 switch (pipe_id) { 1558 case IA_CSS_PIPE_ID_PREVIEW: 1559 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 1560 copy_pipe_delay = main_pipe->dvs_frame_delay; 1561 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; 1562 capture_pipe_delay = IA_CSS_FRAME_DELAY_0; 1563 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, 1564 main_pipe->pipe_num, main_pipe->dvs_frame_delay); 1565 break; 1566 1567 case IA_CSS_PIPE_ID_VIDEO: 1568 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 1569 copy_pipe_delay = main_pipe->dvs_frame_delay; 1570 capture_pipe = main_pipe->pipe_settings.video.capture_pipe; 1571 capture_pipe_delay = IA_CSS_FRAME_DELAY_0; 1572 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, 1573 main_pipe->pipe_num, main_pipe->dvs_frame_delay); 1574 break; 1575 1576 case IA_CSS_PIPE_ID_CAPTURE: 1577 capture_pipe = main_pipe; 1578 capture_pipe_delay = main_pipe->dvs_frame_delay; 1579 break; 1580 1581 case IA_CSS_PIPE_ID_YUVPP: 1582 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, 1583 main_pipe->pipe_num, main_pipe->dvs_frame_delay); 1584 break; 1585 1586 default: 1587 err = -EINVAL; 1588 } 1589 1590 if (!(err) && copy_pipe) 1591 err = ia_css_pipeline_create(©_pipe->pipeline, 1592 copy_pipe->mode, 1593 copy_pipe->pipe_num, 1594 copy_pipe_delay); 1595 1596 if (!(err) && capture_pipe) 1597 err = ia_css_pipeline_create(&capture_pipe->pipeline, 1598 capture_pipe->mode, 1599 capture_pipe->pipe_num, 1600 capture_pipe_delay); 1601 1602 /* DH regular multi pipe - not continuous mode: create the next pipelines too */ 1603 if (!stream->config.continuous) { 1604 int i; 1605 1606 for (i = 1; i < stream->num_pipes && 0 == err; i++) { 1607 main_pipe = stream->pipes[i]; 1608 err = ia_css_pipeline_create(&main_pipe->pipeline, 1609 main_pipe->mode, 1610 main_pipe->pipe_num, 1611 main_pipe->dvs_frame_delay); 1612 } 1613 } 1614 1615 IA_CSS_LEAVE_ERR_PRIVATE(err); 1616 return err; 1617} 1618 1619/* 1620 * creates a host pipeline for all pipes in a stream. Called during 1621 * stream_start. 1622 */ 1623static int 1624create_host_pipeline(struct ia_css_stream *stream) 1625{ 1626 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL; 1627 enum ia_css_pipe_id pipe_id; 1628 struct ia_css_pipe *main_pipe = NULL; 1629 int err = 0; 1630 unsigned int max_input_width = 0; 1631 1632 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 1633 if (!stream) { 1634 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 1635 return -EINVAL; 1636 } 1637 1638 main_pipe = stream->last_pipe; 1639 pipe_id = main_pipe->mode; 1640 1641 /* 1642 * No continuous frame allocation for capture pipe. It uses the 1643 * "main" pipe's frames. 1644 */ 1645 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) || 1646 (pipe_id == IA_CSS_PIPE_ID_VIDEO)) { 1647 /* 1648 * About 1649 * pipe_id == IA_CSS_PIPE_ID_PREVIEW && 1650 * stream->config.mode != IA_CSS_INPUT_MODE_MEMORY: 1651 * 1652 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is 1653 * too strong. E.g. in SkyCam (with memory based input frames) 1654 * there is no continuous mode and thus no need for allocated 1655 * continuous frames. 1656 * This is not only for SkyCam but for all preview cases that 1657 * use DDR based input frames. For this reason the 1658 * stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed 1659 * added. 1660 */ 1661 if (stream->config.continuous || 1662 (pipe_id == IA_CSS_PIPE_ID_PREVIEW && 1663 stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) { 1664 err = alloc_continuous_frames(main_pipe, true); 1665 if (err) 1666 goto ERR; 1667 } 1668 } 1669 1670 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */ 1671 if (!IS_ISP2401 || main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY) { 1672 err = allocate_mipi_frames(main_pipe, &stream->info); 1673 if (err) 1674 goto ERR; 1675 } 1676 1677 switch (pipe_id) { 1678 case IA_CSS_PIPE_ID_PREVIEW: 1679 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; 1680 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; 1681 max_input_width = 1682 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width; 1683 1684 err = create_host_preview_pipeline(main_pipe); 1685 if (err) 1686 goto ERR; 1687 1688 break; 1689 1690 case IA_CSS_PIPE_ID_VIDEO: 1691 copy_pipe = main_pipe->pipe_settings.video.copy_pipe; 1692 capture_pipe = main_pipe->pipe_settings.video.capture_pipe; 1693 max_input_width = 1694 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width; 1695 1696 err = create_host_video_pipeline(main_pipe); 1697 if (err) 1698 goto ERR; 1699 1700 break; 1701 1702 case IA_CSS_PIPE_ID_CAPTURE: 1703 capture_pipe = main_pipe; 1704 1705 break; 1706 1707 case IA_CSS_PIPE_ID_YUVPP: 1708 err = create_host_yuvpp_pipeline(main_pipe); 1709 if (err) 1710 goto ERR; 1711 1712 break; 1713 1714 default: 1715 err = -EINVAL; 1716 } 1717 if (err) 1718 goto ERR; 1719 1720 if (copy_pipe) { 1721 err = create_host_copy_pipeline(copy_pipe, max_input_width, 1722 main_pipe->continuous_frames[0]); 1723 if (err) 1724 goto ERR; 1725 } 1726 1727 if (capture_pipe) { 1728 err = create_host_capture_pipeline(capture_pipe); 1729 if (err) 1730 goto ERR; 1731 } 1732 1733 /* DH regular multi pipe - not continuous mode: create the next pipelines too */ 1734 if (!stream->config.continuous) { 1735 int i; 1736 1737 for (i = 1; i < stream->num_pipes && 0 == err; i++) { 1738 switch (stream->pipes[i]->mode) { 1739 case IA_CSS_PIPE_ID_PREVIEW: 1740 err = create_host_preview_pipeline(stream->pipes[i]); 1741 break; 1742 case IA_CSS_PIPE_ID_VIDEO: 1743 err = create_host_video_pipeline(stream->pipes[i]); 1744 break; 1745 case IA_CSS_PIPE_ID_CAPTURE: 1746 err = create_host_capture_pipeline(stream->pipes[i]); 1747 break; 1748 case IA_CSS_PIPE_ID_YUVPP: 1749 err = create_host_yuvpp_pipeline(stream->pipes[i]); 1750 break; 1751 default: 1752 err = -EINVAL; 1753 } 1754 if (err) 1755 goto ERR; 1756 } 1757 } 1758 1759ERR: 1760 IA_CSS_LEAVE_ERR_PRIVATE(err); 1761 return err; 1762} 1763 1764static const struct ia_css_pipe default_pipe = IA_CSS_DEFAULT_PIPE; 1765static const struct ia_css_preview_settings preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS; 1766static const struct ia_css_capture_settings capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS; 1767static const struct ia_css_video_settings video = IA_CSS_DEFAULT_VIDEO_SETTINGS; 1768static const struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS; 1769 1770static int 1771init_pipe_defaults(enum ia_css_pipe_mode mode, 1772 struct ia_css_pipe *pipe, 1773 bool copy_pipe) 1774{ 1775 if (!pipe) { 1776 IA_CSS_ERROR("NULL pipe parameter"); 1777 return -EINVAL; 1778 } 1779 1780 /* Initialize pipe to pre-defined defaults */ 1781 memcpy(pipe, &default_pipe, sizeof(default_pipe)); 1782 1783 /* TODO: JB should not be needed, but temporary backward reference */ 1784 switch (mode) { 1785 case IA_CSS_PIPE_MODE_PREVIEW: 1786 pipe->mode = IA_CSS_PIPE_ID_PREVIEW; 1787 memcpy(&pipe->pipe_settings.preview, &preview, sizeof(preview)); 1788 break; 1789 case IA_CSS_PIPE_MODE_CAPTURE: 1790 if (copy_pipe) 1791 pipe->mode = IA_CSS_PIPE_ID_COPY; 1792 else 1793 pipe->mode = IA_CSS_PIPE_ID_CAPTURE; 1794 1795 memcpy(&pipe->pipe_settings.capture, &capture, sizeof(capture)); 1796 break; 1797 case IA_CSS_PIPE_MODE_VIDEO: 1798 pipe->mode = IA_CSS_PIPE_ID_VIDEO; 1799 memcpy(&pipe->pipe_settings.video, &video, sizeof(video)); 1800 break; 1801 case IA_CSS_PIPE_MODE_COPY: 1802 pipe->mode = IA_CSS_PIPE_ID_CAPTURE; 1803 break; 1804 case IA_CSS_PIPE_MODE_YUVPP: 1805 pipe->mode = IA_CSS_PIPE_ID_YUVPP; 1806 memcpy(&pipe->pipe_settings.yuvpp, &yuvpp, sizeof(yuvpp)); 1807 break; 1808 default: 1809 return -EINVAL; 1810 } 1811 1812 return 0; 1813} 1814 1815static void 1816pipe_global_init(void) 1817{ 1818 u8 i; 1819 1820 my_css.pipe_counter = 0; 1821 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) 1822 my_css.all_pipes[i] = NULL; 1823} 1824 1825static int 1826pipe_generate_pipe_num(const struct ia_css_pipe *pipe, 1827 unsigned int *pipe_number) 1828{ 1829 const u8 INVALID_PIPE_NUM = (uint8_t)~(0); 1830 u8 pipe_num = INVALID_PIPE_NUM; 1831 u8 i; 1832 1833 if (!pipe) { 1834 IA_CSS_ERROR("NULL pipe parameter"); 1835 return -EINVAL; 1836 } 1837 1838 /* Assign a new pipe_num .... search for empty place */ 1839 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { 1840 if (!my_css.all_pipes[i]) { 1841 /* position is reserved */ 1842 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe; 1843 pipe_num = i; 1844 break; 1845 } 1846 } 1847 if (pipe_num == INVALID_PIPE_NUM) { 1848 /* Max number of pipes already allocated */ 1849 IA_CSS_ERROR("Max number of pipes already created"); 1850 return -ENOSPC; 1851 } 1852 1853 my_css.pipe_counter++; 1854 1855 IA_CSS_LOG("pipe_num (%d)", pipe_num); 1856 1857 *pipe_number = pipe_num; 1858 return 0; 1859} 1860 1861static void 1862pipe_release_pipe_num(unsigned int pipe_num) 1863{ 1864 my_css.all_pipes[pipe_num] = NULL; 1865 my_css.pipe_counter--; 1866 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1867 "pipe_release_pipe_num (%d)\n", pipe_num); 1868} 1869 1870static int 1871create_pipe(enum ia_css_pipe_mode mode, 1872 struct ia_css_pipe **pipe, 1873 bool copy_pipe) 1874{ 1875 int err = 0; 1876 struct ia_css_pipe *me; 1877 1878 if (!pipe) { 1879 IA_CSS_ERROR("NULL pipe parameter"); 1880 return -EINVAL; 1881 } 1882 1883 me = kmalloc(sizeof(*me), GFP_KERNEL); 1884 if (!me) 1885 return -ENOMEM; 1886 1887 err = init_pipe_defaults(mode, me, copy_pipe); 1888 if (err) { 1889 kfree(me); 1890 return err; 1891 } 1892 1893 err = pipe_generate_pipe_num(me, &me->pipe_num); 1894 if (err) { 1895 kfree(me); 1896 return err; 1897 } 1898 1899 *pipe = me; 1900 return 0; 1901} 1902 1903struct ia_css_pipe * 1904find_pipe_by_num(uint32_t pipe_num) 1905{ 1906 unsigned int i; 1907 1908 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { 1909 if (my_css.all_pipes[i] && 1910 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) { 1911 return my_css.all_pipes[i]; 1912 } 1913 } 1914 return NULL; 1915} 1916 1917int 1918ia_css_pipe_destroy(struct ia_css_pipe *pipe) 1919{ 1920 int err = 0; 1921 1922 IA_CSS_ENTER("pipe = %p", pipe); 1923 1924 if (!pipe) { 1925 IA_CSS_LEAVE_ERR(-EINVAL); 1926 return -EINVAL; 1927 } 1928 1929 if (pipe->stream) { 1930 IA_CSS_LOG("ia_css_stream_destroy not called!"); 1931 IA_CSS_LEAVE_ERR(-EINVAL); 1932 return -EINVAL; 1933 } 1934 1935 switch (pipe->config.mode) { 1936 case IA_CSS_PIPE_MODE_PREVIEW: 1937 /* 1938 * need to take into account that this function is also called 1939 * on the internal copy pipe 1940 */ 1941 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) { 1942 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES, 1943 pipe->continuous_frames); 1944 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES, 1945 pipe->cont_md_buffers); 1946 if (pipe->pipe_settings.preview.copy_pipe) { 1947 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe); 1948 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1949 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n", 1950 err); 1951 } 1952 } 1953 break; 1954 case IA_CSS_PIPE_MODE_VIDEO: 1955 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) { 1956 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES, 1957 pipe->continuous_frames); 1958 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES, 1959 pipe->cont_md_buffers); 1960 if (pipe->pipe_settings.video.copy_pipe) { 1961 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe); 1962 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 1963 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n", 1964 err); 1965 } 1966 } 1967 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, 1968 pipe->pipe_settings.video.tnr_frames); 1969 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, 1970 pipe->pipe_settings.video.delay_frames); 1971 break; 1972 case IA_CSS_PIPE_MODE_CAPTURE: 1973 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, 1974 pipe->pipe_settings.capture.delay_frames); 1975 break; 1976 case IA_CSS_PIPE_MODE_COPY: 1977 break; 1978 case IA_CSS_PIPE_MODE_YUVPP: 1979 break; 1980 } 1981 1982 if (pipe->scaler_pp_lut != mmgr_NULL) { 1983 hmm_free(pipe->scaler_pp_lut); 1984 pipe->scaler_pp_lut = mmgr_NULL; 1985 } 1986 1987 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL; 1988 sh_css_pipe_free_shading_table(pipe); 1989 1990 ia_css_pipeline_destroy(&pipe->pipeline); 1991 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe)); 1992 1993 kfree(pipe); 1994 IA_CSS_LEAVE("err = %d", err); 1995 return err; 1996} 1997 1998void 1999ia_css_uninit(void) 2000{ 2001 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n"); 2002 2003 sh_css_params_free_default_gdc_lut(); 2004 2005 /* cleanup generic data */ 2006 sh_css_params_uninit(); 2007 ia_css_refcount_uninit(); 2008 2009 ia_css_rmgr_uninit(); 2010 2011 if (!IS_ISP2401) { 2012 /* needed for reprogramming the inputformatter after power cycle of css */ 2013 ifmtr_set_if_blocking_mode_reset = true; 2014 } 2015 2016 ia_css_spctrl_unload_fw(SP0_ID); 2017 sh_css_sp_set_sp_running(false); 2018 /* check and free any remaining mipi frames */ 2019 free_mipi_frames(NULL); 2020 2021 sh_css_sp_reset_global_vars(); 2022 2023 ia_css_isys_uninit(); 2024 2025 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n"); 2026} 2027 2028int ia_css_irq_translate( 2029 unsigned int *irq_infos) 2030{ 2031 enum virq_id irq; 2032 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs; 2033 unsigned int infos = 0; 2034 2035 /* irq_infos can be NULL, but that would make the function useless */ 2036 /* assert(irq_infos != NULL); */ 2037 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2038 "ia_css_irq_translate() enter: irq_infos=%p\n", irq_infos); 2039 2040 while (status == hrt_isp_css_irq_status_more_irqs) { 2041 status = virq_get_channel_id(&irq); 2042 if (status == hrt_isp_css_irq_status_error) 2043 return -EINVAL; 2044 2045 2046 switch (irq) { 2047 case virq_sp: 2048 /* 2049 * When SP goes to idle, info is available in the 2050 * event queue. 2051 */ 2052 infos |= IA_CSS_IRQ_INFO_EVENTS_READY; 2053 break; 2054 case virq_isp: 2055 break; 2056 case virq_isys_sof: 2057 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF; 2058 break; 2059 case virq_isys_eof: 2060 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF; 2061 break; 2062 case virq_isys_csi: 2063 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR; 2064 break; 2065 case virq_ifmt0_id: 2066 if (!IS_ISP2401) 2067 infos |= IA_CSS_IRQ_INFO_IF_ERROR; 2068 break; 2069 case virq_dma: 2070 infos |= IA_CSS_IRQ_INFO_DMA_ERROR; 2071 break; 2072 case virq_sw_pin_0: 2073 infos |= sh_css_get_sw_interrupt_value(0); 2074 break; 2075 case virq_sw_pin_1: 2076 infos |= sh_css_get_sw_interrupt_value(1); 2077 /* pqiao TODO: also assumption here */ 2078 break; 2079 default: 2080 break; 2081 } 2082 } 2083 2084 if (irq_infos) 2085 *irq_infos = infos; 2086 2087 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2088 "ia_css_irq_translate() leave: irq_infos=%u\n", 2089 infos); 2090 2091 return 0; 2092} 2093 2094int ia_css_irq_enable( 2095 enum ia_css_irq_info info, 2096 bool enable) 2097{ 2098 enum virq_id irq = N_virq_id; 2099 2100 IA_CSS_ENTER("info=%d, enable=%d", info, enable); 2101 2102 switch (info) { 2103 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF: 2104 if (IS_ISP2401) 2105 /* Just ignore those unused IRQs without printing errors */ 2106 return 0; 2107 2108 irq = virq_isys_sof; 2109 break; 2110 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF: 2111 if (IS_ISP2401) 2112 /* Just ignore those unused IRQs without printing errors */ 2113 return 0; 2114 2115 irq = virq_isys_eof; 2116 break; 2117 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR: 2118 if (IS_ISP2401) 2119 /* Just ignore those unused IRQs without printing errors */ 2120 return 0; 2121 2122 irq = virq_isys_csi; 2123 break; 2124 case IA_CSS_IRQ_INFO_IF_ERROR: 2125 if (IS_ISP2401) 2126 /* Just ignore those unused IRQs without printing errors */ 2127 return 0; 2128 2129 irq = virq_ifmt0_id; 2130 break; 2131 case IA_CSS_IRQ_INFO_DMA_ERROR: 2132 irq = virq_dma; 2133 break; 2134 case IA_CSS_IRQ_INFO_SW_0: 2135 irq = virq_sw_pin_0; 2136 break; 2137 case IA_CSS_IRQ_INFO_SW_1: 2138 irq = virq_sw_pin_1; 2139 break; 2140 default: 2141 IA_CSS_LEAVE_ERR(-EINVAL); 2142 return -EINVAL; 2143 } 2144 2145 cnd_virq_enable_channel(irq, enable); 2146 2147 IA_CSS_LEAVE_ERR(0); 2148 return 0; 2149} 2150 2151 2152static unsigned int 2153sh_css_get_sw_interrupt_value(unsigned int irq) 2154{ 2155 unsigned int irq_value; 2156 2157 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2158 "sh_css_get_sw_interrupt_value() enter: irq=%d\n", irq); 2159 irq_value = sh_css_sp_get_sw_interrupt_value(irq); 2160 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 2161 "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n", irq_value); 2162 return irq_value; 2163} 2164 2165/* 2166 * configure and load the copy binary, the next binary is used to 2167 * determine whether the copy binary needs to do left padding. 2168 */ 2169static int load_copy_binary( 2170 struct ia_css_pipe *pipe, 2171 struct ia_css_binary *copy_binary, 2172 struct ia_css_binary *next_binary) 2173{ 2174 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info; 2175 unsigned int left_padding; 2176 int err; 2177 struct ia_css_binary_descr copy_descr; 2178 2179 /* next_binary can be NULL */ 2180 assert(pipe); 2181 assert(copy_binary); 2182 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 2183 "load_copy_binary() enter:\n"); 2184 2185 if (next_binary) { 2186 copy_out_info = next_binary->in_frame_info; 2187 left_padding = next_binary->left_padding; 2188 } else { 2189 copy_out_info = pipe->output_info[0]; 2190 copy_vf_info = pipe->vf_output_info[0]; 2191 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); 2192 left_padding = 0; 2193 } 2194 2195 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr, 2196 ©_in_info, ©_out_info, 2197 (next_binary) ? NULL : NULL/*TODO: ©_vf_info*/); 2198 err = ia_css_binary_find(©_descr, copy_binary); 2199 if (err) 2200 return err; 2201 copy_binary->left_padding = left_padding; 2202 return 0; 2203} 2204 2205static int 2206alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time) 2207{ 2208 int err = 0; 2209 struct ia_css_frame_info ref_info; 2210 enum ia_css_pipe_id pipe_id; 2211 bool continuous; 2212 unsigned int i, idx; 2213 unsigned int num_frames; 2214 2215 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time); 2216 2217 if ((!pipe) || (!pipe->stream)) { 2218 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 2219 return -EINVAL; 2220 } 2221 2222 pipe_id = pipe->mode; 2223 continuous = pipe->stream->config.continuous; 2224 2225 if (continuous) { 2226 if (init_time) { 2227 num_frames = pipe->stream->config.init_num_cont_raw_buf; 2228 pipe->stream->continuous_pipe = pipe; 2229 } else { 2230 num_frames = pipe->stream->config.target_num_cont_raw_buf; 2231 } 2232 } else { 2233 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES; 2234 } 2235 2236 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) { 2237 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info; 2238 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) { 2239 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info; 2240 } else { 2241 /* should not happen */ 2242 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 2243 return -EINVAL; 2244 } 2245 2246 if (IS_ISP2401) { 2247 /* For CSI2+, the continuous frame will hold the full input frame */ 2248 ref_info.res.width = pipe->stream->config.input_config.input_res.width; 2249 ref_info.res.height = pipe->stream->config.input_config.input_res.height; 2250 2251 /* Ensure padded width is aligned for 2401 */ 2252 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS); 2253 } 2254 2255 if (pipe->stream->config.pack_raw_pixels) { 2256 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 2257 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n"); 2258 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED; 2259 } else 2260 { 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 2312int 2313ia_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 2320static int 2321load_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 2490static void 2491ia_css_binary_unload(struct ia_css_binary *binary) 2492{ 2493 ia_css_binary_destroy_isp_parameters(binary); 2494} 2495 2496static int 2497unload_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 2513static 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 2529static 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 2580static 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 2635static 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 2693static 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 2749static 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 2771static int 2772init_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 2791static unsigned int 2792get_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 2802static unsigned int 2803get_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 */ 2817static 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 2871void 2872ia_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 2935static int 2936init_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 2975static int 2976init_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 */ 2996static 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 3174ERR: 3175 IA_CSS_LEAVE_ERR_PRIVATE(err); 3176 return err; 3177} 3178 3179/* Create stages for preview */ 3180static int 3181create_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 3308ERR: 3309 IA_CSS_LEAVE_ERR_PRIVATE(err); 3310 return err; 3311} 3312 3313static 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 3333static int 3334preview_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 3416int 3417ia_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 */ 3624int 3625ia_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 */ 3831static 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 3851int 3852ia_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 4010int 4011ia_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 4048static int 4049sh_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 */ 4210void 4211sh_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 4219bool 4220sh_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 */ 4237int 4238ia_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 4249int 4250ia_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 */ 4263int 4264ia_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 4275unsigned int 4276sh_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 4286static 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 4322static int 4323sh_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 4358static int 4359sh_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 4399err: 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 */ 4409static int 4410ia_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 4444static 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 = kcalloc(cas_scaler_descr.num_stage, 4534 sizeof(struct ia_css_binary), 4535 GFP_KERNEL); 4536 if (!mycs->yuv_scaler_binary) { 4537 mycs->num_yuv_scaler = 0; 4538 err = -ENOMEM; 4539 return err; 4540 } 4541 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage, 4542 sizeof(bool), GFP_KERNEL); 4543 if (!mycs->is_output_stage) { 4544 err = -ENOMEM; 4545 return err; 4546 } 4547 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 4548 struct ia_css_binary_descr yuv_scaler_descr; 4549 4550 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 4551 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 4552 &yuv_scaler_descr, &cas_scaler_descr.in_info[i], 4553 &cas_scaler_descr.out_info[i], 4554 &cas_scaler_descr.internal_out_info[i], 4555 &cas_scaler_descr.vf_info[i]); 4556 err = ia_css_binary_find(&yuv_scaler_descr, 4557 &mycs->yuv_scaler_binary[i]); 4558 if (err) { 4559 kfree(mycs->is_output_stage); 4560 mycs->is_output_stage = NULL; 4561 return err; 4562 } 4563 } 4564 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 4565 } 4566 4567 { 4568 struct ia_css_binary_descr video_descr; 4569 enum ia_css_frame_format vf_info_format; 4570 4571 err = ia_css_pipe_get_video_binarydesc(pipe, 4572 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info, 4573 video_vf_info, 4574 pipe->stream->config.left_padding); 4575 if (err) 4576 return err; 4577 4578 /* 4579 * In the case where video_vf_info is not NULL, this allows 4580 * us to find a potential video library with desired vf format. 4581 * If success, no vf_pp binary is needed. 4582 * If failed, we will look up video binary with YUV_LINE vf format 4583 */ 4584 err = ia_css_binary_find(&video_descr, 4585 &mycs->video_binary); 4586 4587 if (err) { 4588 /* This will do another video binary lookup later for YUV_LINE format*/ 4589 if (video_vf_info) 4590 need_vf_pp = true; 4591 else 4592 return err; 4593 } else if (video_vf_info) { 4594 /* 4595 * The first video binary lookup is successful, but we 4596 * may still need vf_pp binary based on additional check 4597 */ 4598 num_output_pins = mycs->video_binary.info->num_output_pins; 4599 vf_ds_log2 = mycs->video_binary.vf_downscale_log2; 4600 4601 /* 4602 * If the binary has dual output pins, we need vf_pp 4603 * if the resolution is different. 4604 */ 4605 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output); 4606 4607 /* 4608 * If the binary has single output pin, we need vf_pp 4609 * if additional scaling is needed for vf 4610 */ 4611 need_vf_pp |= ((num_output_pins == 1) && 4612 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) || 4613 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height))); 4614 } 4615 4616 if (need_vf_pp) { 4617 /* save the current vf_info format for restoration later */ 4618 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 4619 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n"); 4620 4621 vf_info_format = video_vf_info->format; 4622 4623 if (!pipe->config.enable_vfpp_bci) 4624 ia_css_frame_info_set_format(video_vf_info, 4625 IA_CSS_FRAME_FORMAT_YUV_LINE); 4626 4627 ia_css_binary_destroy_isp_parameters(&mycs->video_binary); 4628 4629 err = ia_css_binary_find(&video_descr, 4630 &mycs->video_binary); 4631 4632 /* restore original vf_info format */ 4633 ia_css_frame_info_set_format(video_vf_info, 4634 vf_info_format); 4635 if (err) 4636 return err; 4637 } 4638 } 4639 4640 /* 4641 * If a video binary does not use a ref_frame, we set the frame delay 4642 * to 0. This is the case for the 1-stage low-power video binary. 4643 */ 4644 if (!mycs->video_binary.info->sp.enable.ref_frame) 4645 pipe->dvs_frame_delay = 0; 4646 4647 /* 4648 * The delay latency determines the number of invalid frames after 4649 * a stream is started. 4650 */ 4651 pipe->num_invalid_frames = pipe->dvs_frame_delay; 4652 pipe->info.num_invalid_frames = pipe->num_invalid_frames; 4653 4654 /* 4655 * Viewfinder frames also decrement num_invalid_frames. If the pipe 4656 * outputs a viewfinder output, then we need double the number of 4657 * invalid frames 4658 */ 4659 if (video_vf_info) 4660 pipe->num_invalid_frames *= 2; 4661 4662 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 4663 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n", 4664 pipe->num_invalid_frames, pipe->dvs_frame_delay); 4665 4666 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */ 4667 if (!IS_ISP2401) { 4668 /* Copy */ 4669 if (!online && !continuous) { 4670 /* 4671 * TODO: what exactly needs doing, prepend the copy binary to 4672 * video base this only on !online? 4673 */ 4674 err = load_copy_binary(pipe, 4675 &mycs->copy_binary, 4676 &mycs->video_binary); 4677 if (err) 4678 return err; 4679 } 4680 } 4681 4682 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) { 4683 struct ia_css_binary_descr vf_pp_descr; 4684 4685 if (mycs->video_binary.vf_frame_info.format 4686 == IA_CSS_FRAME_FORMAT_YUV_LINE) { 4687 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr, 4688 &mycs->video_binary.vf_frame_info, 4689 pipe_vf_out_info); 4690 } else { 4691 /* 4692 * output from main binary is not yuv line. currently 4693 * this is possible only when bci is enabled on vfpp 4694 * output 4695 */ 4696 assert(pipe->config.enable_vfpp_bci); 4697 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr, 4698 &mycs->video_binary.vf_frame_info, 4699 pipe_vf_out_info, NULL, NULL); 4700 } 4701 4702 err = ia_css_binary_find(&vf_pp_descr, 4703 &mycs->vf_pp_binary); 4704 if (err) 4705 return err; 4706 } 4707 4708 err = allocate_delay_frames(pipe); 4709 4710 if (err) 4711 return err; 4712 4713 if (mycs->video_binary.info->sp.enable.block_output) { 4714 tnr_info = mycs->video_binary.out_frame_info[0]; 4715 4716 /* Make tnr reference buffers output block height align */ 4717 tnr_info.res.height = CEIL_MUL(tnr_info.res.height, 4718 mycs->video_binary.info->sp.block.output_block_height); 4719 } else { 4720 tnr_info = mycs->video_binary.internal_frame_info; 4721 } 4722 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE; 4723 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH; 4724 4725 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) { 4726 if (mycs->tnr_frames[i]) { 4727 ia_css_frame_free(mycs->tnr_frames[i]); 4728 mycs->tnr_frames[i] = NULL; 4729 } 4730 err = ia_css_frame_allocate_from_info( 4731 &mycs->tnr_frames[i], 4732 &tnr_info); 4733 if (err) 4734 return err; 4735 } 4736 IA_CSS_LEAVE_PRIVATE(""); 4737 return 0; 4738} 4739 4740static int 4741unload_video_binaries(struct ia_css_pipe *pipe) 4742{ 4743 unsigned int i; 4744 4745 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 4746 4747 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { 4748 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 4749 return -EINVAL; 4750 } 4751 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary); 4752 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary); 4753 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary); 4754 4755 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++) 4756 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]); 4757 4758 kfree(pipe->pipe_settings.video.is_output_stage); 4759 pipe->pipe_settings.video.is_output_stage = NULL; 4760 kfree(pipe->pipe_settings.video.yuv_scaler_binary); 4761 pipe->pipe_settings.video.yuv_scaler_binary = NULL; 4762 4763 IA_CSS_LEAVE_ERR_PRIVATE(0); 4764 return 0; 4765} 4766 4767static int video_start(struct ia_css_pipe *pipe) 4768{ 4769 int err = 0; 4770 struct ia_css_pipe *copy_pipe, *capture_pipe; 4771 enum sh_css_pipe_config_override copy_ovrd; 4772 enum ia_css_input_mode video_pipe_input_mode; 4773 unsigned int thread_id; 4774 4775 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 4776 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { 4777 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 4778 return -EINVAL; 4779 } 4780 4781 video_pipe_input_mode = pipe->stream->config.mode; 4782 4783 copy_pipe = pipe->pipe_settings.video.copy_pipe; 4784 capture_pipe = pipe->pipe_settings.video.capture_pipe; 4785 4786 sh_css_metrics_start_frame(); 4787 4788 /* multi stream video needs mipi buffers */ 4789 4790 err = send_mipi_frames(pipe); 4791 if (err) 4792 return err; 4793 4794 send_raw_frames(pipe); 4795 4796 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 4797 copy_ovrd = 1 << thread_id; 4798 4799 if (pipe->stream->cont_capt) { 4800 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), 4801 &thread_id); 4802 copy_ovrd |= 1 << thread_id; 4803 } 4804 4805 /* Construct and load the copy pipe */ 4806 if (pipe->stream->config.continuous) { 4807 sh_css_sp_init_pipeline(©_pipe->pipeline, 4808 IA_CSS_PIPE_ID_COPY, 4809 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe), 4810 false, 4811 pipe->stream->config.pixels_per_clock == 2, false, 4812 false, pipe->required_bds_factor, 4813 copy_ovrd, 4814 pipe->stream->config.mode, 4815 &pipe->stream->config.metadata_config, 4816 &pipe->stream->info.metadata_info, 4817 pipe->stream->config.source.port.port); 4818 4819 /* 4820 * make the video pipe start with mem mode input, copy handles 4821 * the actual mode 4822 */ 4823 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; 4824 } 4825 4826 /* Construct and load the capture pipe */ 4827 if (pipe->stream->cont_capt) { 4828 sh_css_sp_init_pipeline(&capture_pipe->pipeline, 4829 IA_CSS_PIPE_ID_CAPTURE, 4830 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe), 4831 capture_pipe->config.default_capture_config.enable_xnr != 0, 4832 capture_pipe->stream->config.pixels_per_clock == 2, 4833 true, /* continuous */ 4834 false, /* offline */ 4835 capture_pipe->required_bds_factor, 4836 0, 4837 IA_CSS_INPUT_MODE_MEMORY, 4838 &pipe->stream->config.metadata_config, 4839 &pipe->stream->info.metadata_info, 4840 (enum mipi_port_id)0); 4841 } 4842 4843 start_pipe(pipe, copy_ovrd, video_pipe_input_mode); 4844 4845 IA_CSS_LEAVE_ERR_PRIVATE(err); 4846 return err; 4847} 4848 4849static 4850int sh_css_pipe_get_viewfinder_frame_info( 4851 struct ia_css_pipe *pipe, 4852 struct ia_css_frame_info *info, 4853 unsigned int idx) 4854{ 4855 assert(pipe); 4856 assert(info); 4857 4858 /* We could print the pointer as input arg, and the values as output */ 4859 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 4860 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n"); 4861 4862 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE && 4863 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || 4864 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)) 4865 return -EINVAL; 4866 /* offline video does not generate viewfinder output */ 4867 *info = pipe->vf_output_info[idx]; 4868 4869 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 4870 "sh_css_pipe_get_viewfinder_frame_info() leave: \ 4871 info.res.width=%d, info.res.height=%d, \ 4872 info.padded_width=%d, info.format=%d, \ 4873 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n", 4874 info->res.width, info->res.height, 4875 info->padded_width, info->format, 4876 info->raw_bit_depth, info->raw_bayer_order); 4877 4878 return 0; 4879} 4880 4881static int 4882sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width, 4883 unsigned int height, unsigned int min_width, 4884 enum ia_css_frame_format format, 4885 unsigned int idx) 4886{ 4887 int err = 0; 4888 4889 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n", 4890 pipe, width, height, min_width, format, idx); 4891 4892 if (!pipe) { 4893 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 4894 return -EINVAL; 4895 } 4896 4897 err = ia_css_util_check_res(width, height); 4898 if (err) { 4899 IA_CSS_LEAVE_ERR_PRIVATE(err); 4900 return err; 4901 } 4902 if (pipe->vf_output_info[idx].res.width != width || 4903 pipe->vf_output_info[idx].res.height != height || 4904 pipe->vf_output_info[idx].format != format) 4905 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height, 4906 format, min_width); 4907 4908 IA_CSS_LEAVE_ERR_PRIVATE(0); 4909 return 0; 4910} 4911 4912static int load_copy_binaries(struct ia_css_pipe *pipe) 4913{ 4914 int err = 0; 4915 4916 assert(pipe); 4917 IA_CSS_ENTER_PRIVATE(""); 4918 4919 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 4920 pipe->mode == IA_CSS_PIPE_ID_COPY); 4921 if (pipe->pipe_settings.capture.copy_binary.info) 4922 return 0; 4923 4924 err = ia_css_frame_check_info(&pipe->output_info[0]); 4925 if (err) 4926 goto ERR; 4927 4928 err = verify_copy_out_frame_format(pipe); 4929 if (err) 4930 goto ERR; 4931 4932 err = load_copy_binary(pipe, 4933 &pipe->pipe_settings.capture.copy_binary, 4934 NULL); 4935 4936ERR: 4937 IA_CSS_LEAVE_ERR_PRIVATE(err); 4938 return err; 4939} 4940 4941static bool need_capture_pp( 4942 const struct ia_css_pipe *pipe) 4943{ 4944 const struct ia_css_frame_info *out_info = &pipe->output_info[0]; 4945 4946 IA_CSS_ENTER_LEAVE_PRIVATE(""); 4947 assert(pipe); 4948 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 4949 4950 /* determine whether we need to use the capture_pp binary. 4951 * This is needed for: 4952 * 1. XNR or 4953 * 2. Digital Zoom or 4954 * 3. YUV downscaling 4955 */ 4956 if (pipe->out_yuv_ds_input_info.res.width && 4957 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) || 4958 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height))) 4959 return true; 4960 4961 if (pipe->config.default_capture_config.enable_xnr != 0) 4962 return true; 4963 4964 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) || 4965 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) || 4966 pipe->config.enable_dz) 4967 return true; 4968 4969 return false; 4970} 4971 4972static bool need_capt_ldc( 4973 const struct ia_css_pipe *pipe) 4974{ 4975 IA_CSS_ENTER_LEAVE_PRIVATE(""); 4976 assert(pipe); 4977 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 4978 return (pipe->extra_config.enable_dvs_6axis) ? true : false; 4979} 4980 4981static int set_num_primary_stages(unsigned int *num, 4982 enum ia_css_pipe_version version) 4983{ 4984 int err = 0; 4985 4986 if (!num) 4987 return -EINVAL; 4988 4989 switch (version) { 4990 case IA_CSS_PIPE_VERSION_2_6_1: 4991 *num = NUM_PRIMARY_HQ_STAGES; 4992 break; 4993 case IA_CSS_PIPE_VERSION_2_2: 4994 case IA_CSS_PIPE_VERSION_1: 4995 *num = NUM_PRIMARY_STAGES; 4996 break; 4997 default: 4998 err = -EINVAL; 4999 break; 5000 } 5001 5002 return err; 5003} 5004 5005static int load_primary_binaries( 5006 struct ia_css_pipe *pipe) 5007{ 5008 bool online = false; 5009 bool need_pp = false; 5010 bool need_isp_copy_binary = false; 5011 bool need_ldc = false; 5012 bool sensor = false; 5013 bool memory, continuous; 5014 struct ia_css_frame_info prim_in_info, 5015 prim_out_info, 5016 capt_pp_out_info, vf_info, 5017 *vf_pp_in_info, *pipe_out_info, 5018 *pipe_vf_out_info, *capt_pp_in_info, 5019 capt_ldc_out_info; 5020 int err = 0; 5021 struct ia_css_capture_settings *mycs; 5022 unsigned int i; 5023 bool need_extra_yuv_scaler = false; 5024 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES]; 5025 5026 IA_CSS_ENTER_PRIVATE(""); 5027 assert(pipe); 5028 assert(pipe->stream); 5029 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 5030 pipe->mode == IA_CSS_PIPE_ID_COPY); 5031 5032 online = pipe->stream->config.online; 5033 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); 5034 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 5035 continuous = pipe->stream->config.continuous; 5036 5037 mycs = &pipe->pipe_settings.capture; 5038 pipe_out_info = &pipe->output_info[0]; 5039 pipe_vf_out_info = &pipe->vf_output_info[0]; 5040 5041 if (mycs->primary_binary[0].info) 5042 return 0; 5043 5044 err = set_num_primary_stages(&mycs->num_primary_stage, 5045 pipe->config.isp_pipe_version); 5046 if (err) { 5047 IA_CSS_LEAVE_ERR_PRIVATE(err); 5048 return err; 5049 } 5050 5051 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 5052 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info); 5053 if (err) { 5054 IA_CSS_LEAVE_ERR_PRIVATE(err); 5055 return err; 5056 } 5057 } else { 5058 err = ia_css_frame_check_info(pipe_out_info); 5059 if (err) { 5060 IA_CSS_LEAVE_ERR_PRIVATE(err); 5061 return err; 5062 } 5063 } 5064 need_pp = need_capture_pp(pipe); 5065 5066 /* 5067 * we use the vf output info to get the primary/capture_pp binary 5068 * configured for vf_veceven. It will select the closest downscaling 5069 * factor. 5070 */ 5071 vf_info = *pipe_vf_out_info; 5072 5073 /* 5074 * WARNING: The #if def flag has been added below as a 5075 * temporary solution to solve the problem of enabling the 5076 * view finder in a single binary in a capture flow. The 5077 * vf-pp stage has been removed for Skycam in the solution 5078 * provided. The vf-pp stage should be re-introduced when 5079 * required. This should not be considered as a clean solution. 5080 * Proper investigation should be done to come up with the clean 5081 * solution. 5082 */ 5083 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); 5084 5085 /* 5086 * TODO: All this yuv_scaler and capturepp calculation logic 5087 * can be shared later. Capture_pp is also a yuv_scale binary 5088 * with extra XNR funcionality. Therefore, it can be made as the 5089 * first step of the cascade. 5090 */ 5091 capt_pp_out_info = pipe->out_yuv_ds_input_info; 5092 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420; 5093 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP; 5094 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP; 5095 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0); 5096 5097 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res, 5098 pipe_out_info->res); 5099 5100 if (need_extra_yuv_scaler) { 5101 struct ia_css_cas_binary_descr cas_scaler_descr = { }; 5102 5103 err = ia_css_pipe_create_cas_scaler_desc_single_output( 5104 &capt_pp_out_info, 5105 pipe_out_info, 5106 NULL, 5107 &cas_scaler_descr); 5108 if (err) { 5109 IA_CSS_LEAVE_ERR_PRIVATE(err); 5110 return err; 5111 } 5112 mycs->num_yuv_scaler = cas_scaler_descr.num_stage; 5113 mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage, 5114 sizeof(struct ia_css_binary), 5115 GFP_KERNEL); 5116 if (!mycs->yuv_scaler_binary) { 5117 err = -ENOMEM; 5118 IA_CSS_LEAVE_ERR_PRIVATE(err); 5119 return err; 5120 } 5121 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage, 5122 sizeof(bool), GFP_KERNEL); 5123 if (!mycs->is_output_stage) { 5124 err = -ENOMEM; 5125 IA_CSS_LEAVE_ERR_PRIVATE(err); 5126 return err; 5127 } 5128 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 5129 struct ia_css_binary_descr yuv_scaler_descr; 5130 5131 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 5132 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 5133 &yuv_scaler_descr, &cas_scaler_descr.in_info[i], 5134 &cas_scaler_descr.out_info[i], 5135 &cas_scaler_descr.internal_out_info[i], 5136 &cas_scaler_descr.vf_info[i]); 5137 err = ia_css_binary_find(&yuv_scaler_descr, 5138 &mycs->yuv_scaler_binary[i]); 5139 if (err) { 5140 IA_CSS_LEAVE_ERR_PRIVATE(err); 5141 return err; 5142 } 5143 } 5144 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 5145 5146 } else { 5147 capt_pp_out_info = pipe->output_info[0]; 5148 } 5149 5150 /* TODO Do we disable ldc for skycam */ 5151 need_ldc = need_capt_ldc(pipe); 5152 5153 /* we build up the pipeline starting at the end */ 5154 /* Capture post-processing */ 5155 if (need_pp) { 5156 struct ia_css_binary_descr capture_pp_descr; 5157 5158 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info; 5159 5160 ia_css_pipe_get_capturepp_binarydesc(pipe, 5161 &capture_pp_descr, 5162 capt_pp_in_info, 5163 &capt_pp_out_info, 5164 &vf_info); 5165 5166 err = ia_css_binary_find(&capture_pp_descr, 5167 &mycs->capture_pp_binary); 5168 if (err) { 5169 IA_CSS_LEAVE_ERR_PRIVATE(err); 5170 return err; 5171 } 5172 5173 if (need_ldc) { 5174 struct ia_css_binary_descr capt_ldc_descr; 5175 5176 ia_css_pipe_get_ldc_binarydesc(pipe, 5177 &capt_ldc_descr, 5178 &prim_out_info, 5179 &capt_ldc_out_info); 5180 5181 err = ia_css_binary_find(&capt_ldc_descr, 5182 &mycs->capture_ldc_binary); 5183 if (err) { 5184 IA_CSS_LEAVE_ERR_PRIVATE(err); 5185 return err; 5186 } 5187 } 5188 } else { 5189 prim_out_info = *pipe_out_info; 5190 } 5191 5192 /* Primary */ 5193 for (i = 0; i < mycs->num_primary_stage; i++) { 5194 struct ia_css_frame_info *local_vf_info = NULL; 5195 5196 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && 5197 (i == mycs->num_primary_stage - 1)) 5198 local_vf_info = &vf_info; 5199 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], 5200 &prim_in_info, &prim_out_info, 5201 local_vf_info, i); 5202 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]); 5203 if (err) { 5204 IA_CSS_LEAVE_ERR_PRIVATE(err); 5205 return err; 5206 } 5207 } 5208 5209 /* Viewfinder post-processing */ 5210 if (need_pp) 5211 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info; 5212 else 5213 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info; 5214 5215 /* 5216 * WARNING: The #if def flag has been added below as a 5217 * temporary solution to solve the problem of enabling the 5218 * view finder in a single binary in a capture flow. The 5219 * vf-pp stage has been removed for Skycam in the solution 5220 * provided. The vf-pp stage should be re-introduced when 5221 * required. Thisshould not be considered as a clean solution. 5222 * Proper * investigation should be done to come up with the clean 5223 * solution. 5224 */ 5225 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 5226 struct ia_css_binary_descr vf_pp_descr; 5227 5228 ia_css_pipe_get_vfpp_binarydesc(pipe, 5229 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); 5230 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary); 5231 if (err) { 5232 IA_CSS_LEAVE_ERR_PRIVATE(err); 5233 return err; 5234 } 5235 } 5236 err = allocate_delay_frames(pipe); 5237 5238 if (err) 5239 return err; 5240 5241 if (IS_ISP2401) 5242 /* 5243 * When the input system is 2401, only the Direct Sensor Mode 5244 * Offline Capture uses the ISP copy binary. 5245 */ 5246 need_isp_copy_binary = !online && sensor; 5247 else 5248 need_isp_copy_binary = !online && !continuous && !memory; 5249 5250 /* ISP Copy */ 5251 if (need_isp_copy_binary) { 5252 err = load_copy_binary(pipe, 5253 &mycs->copy_binary, 5254 &mycs->primary_binary[0]); 5255 if (err) { 5256 IA_CSS_LEAVE_ERR_PRIVATE(err); 5257 return err; 5258 } 5259 } 5260 5261 return 0; 5262} 5263 5264static int 5265allocate_delay_frames(struct ia_css_pipe *pipe) 5266{ 5267 unsigned int num_delay_frames = 0, i = 0; 5268 unsigned int dvs_frame_delay = 0; 5269 struct ia_css_frame_info ref_info; 5270 int err = 0; 5271 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO; 5272 struct ia_css_frame **delay_frames = NULL; 5273 5274 IA_CSS_ENTER_PRIVATE(""); 5275 5276 if (!pipe) { 5277 IA_CSS_ERROR("Invalid args - pipe %p", pipe); 5278 return -EINVAL; 5279 } 5280 5281 mode = pipe->mode; 5282 dvs_frame_delay = pipe->dvs_frame_delay; 5283 5284 if (dvs_frame_delay > 0) 5285 num_delay_frames = dvs_frame_delay + 1; 5286 5287 switch (mode) { 5288 case IA_CSS_PIPE_ID_CAPTURE: { 5289 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture; 5290 (void)mycs_capture; 5291 return err; 5292 } 5293 break; 5294 case IA_CSS_PIPE_ID_VIDEO: { 5295 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video; 5296 5297 ref_info = mycs_video->video_binary.internal_frame_info; 5298 5299 /* 5300 * The ref frame expects 5301 * 1. Y plane 5302 * 2. UV plane with line interleaving, like below 5303 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) 5304 * 5305 * This format is not YUV420(which has Y, U and V planes). 5306 * Its closer to NV12, except that the UV plane has UV 5307 * interleaving, like UVUVUVUVUVUVUVUVU... 5308 * 5309 * TODO: make this ref_frame format as a separate frame format 5310 */ 5311 ref_info.format = IA_CSS_FRAME_FORMAT_NV12; 5312 delay_frames = mycs_video->delay_frames; 5313 } 5314 break; 5315 case IA_CSS_PIPE_ID_PREVIEW: { 5316 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview; 5317 5318 ref_info = mycs_preview->preview_binary.internal_frame_info; 5319 5320 /* 5321 * The ref frame expects 5322 * 1. Y plane 5323 * 2. UV plane with line interleaving, like below 5324 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) 5325 * 5326 * This format is not YUV420(which has Y, U and V planes). 5327 * Its closer to NV12, except that the UV plane has UV 5328 * interleaving, like UVUVUVUVUVUVUVUVU... 5329 * 5330 * TODO: make this ref_frame format as a separate frame format 5331 */ 5332 ref_info.format = IA_CSS_FRAME_FORMAT_NV12; 5333 delay_frames = mycs_preview->delay_frames; 5334 } 5335 break; 5336 default: 5337 return -EINVAL; 5338 } 5339 5340 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH; 5341 5342 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES); 5343 for (i = 0; i < num_delay_frames; i++) { 5344 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info); 5345 if (err) 5346 return err; 5347 } 5348 IA_CSS_LEAVE_PRIVATE(""); 5349 return 0; 5350} 5351 5352static int load_advanced_binaries(struct ia_css_pipe *pipe) 5353{ 5354 struct ia_css_frame_info pre_in_info, gdc_in_info, 5355 post_in_info, post_out_info, 5356 vf_info, *vf_pp_in_info, *pipe_out_info, 5357 *pipe_vf_out_info; 5358 bool need_pp; 5359 bool need_isp_copy = true; 5360 int err = 0; 5361 5362 IA_CSS_ENTER_PRIVATE(""); 5363 5364 assert(pipe); 5365 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 5366 pipe->mode == IA_CSS_PIPE_ID_COPY); 5367 if (pipe->pipe_settings.capture.pre_isp_binary.info) 5368 return 0; 5369 pipe_out_info = &pipe->output_info[0]; 5370 pipe_vf_out_info = &pipe->vf_output_info[0]; 5371 5372 vf_info = *pipe_vf_out_info; 5373 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info); 5374 if (err) 5375 return err; 5376 need_pp = need_capture_pp(pipe); 5377 5378 ia_css_frame_info_set_format(&vf_info, 5379 IA_CSS_FRAME_FORMAT_YUV_LINE); 5380 5381 /* we build up the pipeline starting at the end */ 5382 /* Capture post-processing */ 5383 if (need_pp) { 5384 struct ia_css_binary_descr capture_pp_descr; 5385 5386 ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr, 5387 &post_out_info, 5388 pipe_out_info, &vf_info); 5389 err = ia_css_binary_find(&capture_pp_descr, 5390 &pipe->pipe_settings.capture.capture_pp_binary); 5391 if (err) 5392 return err; 5393 } else { 5394 post_out_info = *pipe_out_info; 5395 } 5396 5397 /* Post-gdc */ 5398 { 5399 struct ia_css_binary_descr post_gdc_descr; 5400 5401 ia_css_pipe_get_post_gdc_binarydesc(pipe, &post_gdc_descr, 5402 &post_in_info, 5403 &post_out_info, &vf_info); 5404 err = ia_css_binary_find(&post_gdc_descr, 5405 &pipe->pipe_settings.capture.post_isp_binary); 5406 if (err) 5407 return err; 5408 } 5409 5410 /* Gdc */ 5411 { 5412 struct ia_css_binary_descr gdc_descr; 5413 5414 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info, 5415 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); 5416 err = ia_css_binary_find(&gdc_descr, 5417 &pipe->pipe_settings.capture.anr_gdc_binary); 5418 if (err) 5419 return err; 5420 } 5421 pipe->pipe_settings.capture.anr_gdc_binary.left_padding = 5422 pipe->pipe_settings.capture.post_isp_binary.left_padding; 5423 5424 /* Pre-gdc */ 5425 { 5426 struct ia_css_binary_descr pre_gdc_descr; 5427 5428 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info, 5429 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); 5430 err = ia_css_binary_find(&pre_gdc_descr, 5431 &pipe->pipe_settings.capture.pre_isp_binary); 5432 if (err) 5433 return err; 5434 } 5435 pipe->pipe_settings.capture.pre_isp_binary.left_padding = 5436 pipe->pipe_settings.capture.anr_gdc_binary.left_padding; 5437 5438 /* Viewfinder post-processing */ 5439 if (need_pp) { 5440 vf_pp_in_info = 5441 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info; 5442 } else { 5443 vf_pp_in_info = 5444 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info; 5445 } 5446 5447 { 5448 struct ia_css_binary_descr vf_pp_descr; 5449 5450 ia_css_pipe_get_vfpp_binarydesc(pipe, 5451 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); 5452 err = ia_css_binary_find(&vf_pp_descr, 5453 &pipe->pipe_settings.capture.vf_pp_binary); 5454 if (err) 5455 return err; 5456 } 5457 5458 /* Copy */ 5459 if (IS_ISP2401) 5460 /* For CSI2+, only the direct sensor mode/online requires ISP copy */ 5461 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 5462 5463 if (need_isp_copy) 5464 load_copy_binary(pipe, 5465 &pipe->pipe_settings.capture.copy_binary, 5466 &pipe->pipe_settings.capture.pre_isp_binary); 5467 5468 return err; 5469} 5470 5471static int load_bayer_isp_binaries(struct ia_css_pipe *pipe) 5472{ 5473 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info; 5474 int err = 0; 5475 struct ia_css_binary_descr pre_de_descr; 5476 5477 IA_CSS_ENTER_PRIVATE(""); 5478 assert(pipe); 5479 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 5480 pipe->mode == IA_CSS_PIPE_ID_COPY); 5481 pipe_out_info = &pipe->output_info[0]; 5482 5483 if (pipe->pipe_settings.capture.pre_isp_binary.info) 5484 return 0; 5485 5486 err = ia_css_frame_check_info(pipe_out_info); 5487 if (err) 5488 return err; 5489 5490 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr, 5491 &pre_isp_in_info, 5492 pipe_out_info); 5493 5494 err = ia_css_binary_find(&pre_de_descr, 5495 &pipe->pipe_settings.capture.pre_isp_binary); 5496 5497 return err; 5498} 5499 5500static int load_low_light_binaries(struct ia_css_pipe *pipe) 5501{ 5502 struct ia_css_frame_info pre_in_info, anr_in_info, 5503 post_in_info, post_out_info, 5504 vf_info, *pipe_vf_out_info, *pipe_out_info, 5505 *vf_pp_in_info; 5506 bool need_pp; 5507 bool need_isp_copy = true; 5508 int err = 0; 5509 5510 IA_CSS_ENTER_PRIVATE(""); 5511 assert(pipe); 5512 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 5513 pipe->mode == IA_CSS_PIPE_ID_COPY); 5514 5515 if (pipe->pipe_settings.capture.pre_isp_binary.info) 5516 return 0; 5517 pipe_vf_out_info = &pipe->vf_output_info[0]; 5518 pipe_out_info = &pipe->output_info[0]; 5519 5520 vf_info = *pipe_vf_out_info; 5521 err = ia_css_util_check_vf_out_info(pipe_out_info, 5522 &vf_info); 5523 if (err) 5524 return err; 5525 need_pp = need_capture_pp(pipe); 5526 5527 ia_css_frame_info_set_format(&vf_info, 5528 IA_CSS_FRAME_FORMAT_YUV_LINE); 5529 5530 /* we build up the pipeline starting at the end */ 5531 /* Capture post-processing */ 5532 if (need_pp) { 5533 struct ia_css_binary_descr capture_pp_descr; 5534 5535 ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr, 5536 &post_out_info, 5537 pipe_out_info, &vf_info); 5538 err = ia_css_binary_find(&capture_pp_descr, 5539 &pipe->pipe_settings.capture.capture_pp_binary); 5540 if (err) 5541 return err; 5542 } else { 5543 post_out_info = *pipe_out_info; 5544 } 5545 5546 /* Post-anr */ 5547 { 5548 struct ia_css_binary_descr post_anr_descr; 5549 5550 ia_css_pipe_get_post_anr_binarydesc(pipe, 5551 &post_anr_descr, &post_in_info, &post_out_info, &vf_info); 5552 err = ia_css_binary_find(&post_anr_descr, 5553 &pipe->pipe_settings.capture.post_isp_binary); 5554 if (err) 5555 return err; 5556 } 5557 5558 /* Anr */ 5559 { 5560 struct ia_css_binary_descr anr_descr; 5561 5562 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info, 5563 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); 5564 err = ia_css_binary_find(&anr_descr, 5565 &pipe->pipe_settings.capture.anr_gdc_binary); 5566 if (err) 5567 return err; 5568 } 5569 pipe->pipe_settings.capture.anr_gdc_binary.left_padding = 5570 pipe->pipe_settings.capture.post_isp_binary.left_padding; 5571 5572 /* Pre-anr */ 5573 { 5574 struct ia_css_binary_descr pre_anr_descr; 5575 5576 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info, 5577 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); 5578 err = ia_css_binary_find(&pre_anr_descr, 5579 &pipe->pipe_settings.capture.pre_isp_binary); 5580 if (err) 5581 return err; 5582 } 5583 pipe->pipe_settings.capture.pre_isp_binary.left_padding = 5584 pipe->pipe_settings.capture.anr_gdc_binary.left_padding; 5585 5586 /* Viewfinder post-processing */ 5587 if (need_pp) { 5588 vf_pp_in_info = 5589 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info; 5590 } else { 5591 vf_pp_in_info = 5592 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info; 5593 } 5594 5595 { 5596 struct ia_css_binary_descr vf_pp_descr; 5597 5598 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr, 5599 vf_pp_in_info, pipe_vf_out_info); 5600 err = ia_css_binary_find(&vf_pp_descr, 5601 &pipe->pipe_settings.capture.vf_pp_binary); 5602 if (err) 5603 return err; 5604 } 5605 5606 /* Copy */ 5607 if (IS_ISP2401) 5608 /* For CSI2+, only the direct sensor mode/online requires ISP copy */ 5609 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 5610 5611 if (need_isp_copy) 5612 err = load_copy_binary(pipe, 5613 &pipe->pipe_settings.capture.copy_binary, 5614 &pipe->pipe_settings.capture.pre_isp_binary); 5615 5616 return err; 5617} 5618 5619static bool copy_on_sp(struct ia_css_pipe *pipe) 5620{ 5621 bool rval; 5622 5623 assert(pipe); 5624 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n"); 5625 5626 rval = true; 5627 5628 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE); 5629 5630 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW); 5631 5632 rval &= ((pipe->stream->config.input_config.format == 5633 ATOMISP_INPUT_FORMAT_BINARY_8) || 5634 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)); 5635 5636 return rval; 5637} 5638 5639static int load_capture_binaries(struct ia_css_pipe *pipe) 5640{ 5641 int err = 0; 5642 bool must_be_raw; 5643 5644 IA_CSS_ENTER_PRIVATE(""); 5645 assert(pipe); 5646 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 5647 pipe->mode == IA_CSS_PIPE_ID_COPY); 5648 5649 if (pipe->pipe_settings.capture.primary_binary[0].info) { 5650 IA_CSS_LEAVE_ERR_PRIVATE(0); 5651 return 0; 5652 } 5653 5654 /* in primary, advanced,low light or bayer, 5655 the input format must be raw */ 5656 must_be_raw = 5657 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED || 5658 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER || 5659 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT; 5660 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false); 5661 if (err) { 5662 IA_CSS_LEAVE_ERR_PRIVATE(err); 5663 return err; 5664 } 5665 if (copy_on_sp(pipe) && 5666 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { 5667 ia_css_frame_info_init( 5668 &pipe->output_info[0], 5669 JPEG_BYTES, 5670 1, 5671 IA_CSS_FRAME_FORMAT_BINARY_8, 5672 0); 5673 IA_CSS_LEAVE_ERR_PRIVATE(0); 5674 return 0; 5675 } 5676 5677 switch (pipe->config.default_capture_config.mode) { 5678 case IA_CSS_CAPTURE_MODE_RAW: 5679 err = load_copy_binaries(pipe); 5680 if (!err && IS_ISP2401) 5681 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; 5682 5683 break; 5684 case IA_CSS_CAPTURE_MODE_BAYER: 5685 err = load_bayer_isp_binaries(pipe); 5686 break; 5687 case IA_CSS_CAPTURE_MODE_PRIMARY: 5688 err = load_primary_binaries(pipe); 5689 break; 5690 case IA_CSS_CAPTURE_MODE_ADVANCED: 5691 err = load_advanced_binaries(pipe); 5692 break; 5693 case IA_CSS_CAPTURE_MODE_LOW_LIGHT: 5694 err = load_low_light_binaries(pipe); 5695 break; 5696 } 5697 if (err) { 5698 IA_CSS_LEAVE_ERR_PRIVATE(err); 5699 return err; 5700 } 5701 5702 IA_CSS_LEAVE_ERR_PRIVATE(err); 5703 return err; 5704} 5705 5706static int 5707unload_capture_binaries(struct ia_css_pipe *pipe) 5708{ 5709 unsigned int i; 5710 5711 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 5712 5713 if (!pipe || (pipe->mode != IA_CSS_PIPE_ID_CAPTURE && 5714 pipe->mode != IA_CSS_PIPE_ID_COPY)) { 5715 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 5716 return -EINVAL; 5717 } 5718 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary); 5719 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++) 5720 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]); 5721 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary); 5722 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary); 5723 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary); 5724 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary); 5725 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary); 5726 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary); 5727 5728 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++) 5729 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]); 5730 5731 kfree(pipe->pipe_settings.capture.is_output_stage); 5732 pipe->pipe_settings.capture.is_output_stage = NULL; 5733 kfree(pipe->pipe_settings.capture.yuv_scaler_binary); 5734 pipe->pipe_settings.capture.yuv_scaler_binary = NULL; 5735 5736 IA_CSS_LEAVE_ERR_PRIVATE(0); 5737 return 0; 5738} 5739 5740static bool 5741need_downscaling(const struct ia_css_resolution in_res, 5742 const struct ia_css_resolution out_res) 5743{ 5744 if (in_res.width > out_res.width || in_res.height > out_res.height) 5745 return true; 5746 5747 return false; 5748} 5749 5750static bool 5751need_yuv_scaler_stage(const struct ia_css_pipe *pipe) 5752{ 5753 unsigned int i; 5754 struct ia_css_resolution in_res, out_res; 5755 5756 bool need_format_conversion = false; 5757 5758 IA_CSS_ENTER_PRIVATE(""); 5759 assert(pipe); 5760 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP); 5761 5762 /* TODO: make generic function */ 5763 need_format_conversion = 5764 ((pipe->stream->config.input_config.format == 5765 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) && 5766 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8)); 5767 5768 in_res = pipe->config.input_effective_res; 5769 5770 if (pipe->config.enable_dz) 5771 return true; 5772 5773 if ((pipe->output_info[0].res.width != 0) && need_format_conversion) 5774 return true; 5775 5776 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 5777 out_res = pipe->output_info[i].res; 5778 5779 /* A non-zero width means it is a valid output port */ 5780 if ((out_res.width != 0) && need_downscaling(in_res, out_res)) 5781 return true; 5782 } 5783 5784 return false; 5785} 5786 5787/* 5788 * TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc 5789 * which has some hard-coded knowledge which prevents reuse of the function. 5790 * Later, merge this with ia_css_pipe_create_cas_scaler_desc 5791 */ 5792static int ia_css_pipe_create_cas_scaler_desc_single_output( 5793 struct ia_css_frame_info *in_info, 5794 struct ia_css_frame_info *out_info, 5795 struct ia_css_frame_info *vf_info, 5796 struct ia_css_cas_binary_descr *descr) 5797{ 5798 unsigned int i; 5799 unsigned int hor_ds_factor = 0, ver_ds_factor = 0; 5800 int err = 0; 5801 struct ia_css_frame_info tmp_in_info; 5802 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP; 5803 5804 assert(in_info); 5805 assert(out_info); 5806 5807 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5808 "ia_css_pipe_create_cas_scaler_desc() enter:\n"); 5809 5810 /* We assume that this function is used only for single output port case. */ 5811 descr->num_output_stage = 1; 5812 5813 hor_ds_factor = CEIL_DIV(in_info->res.width, out_info->res.width); 5814 ver_ds_factor = CEIL_DIV(in_info->res.height, out_info->res.height); 5815 /* use the same horizontal and vertical downscaling factor for simplicity */ 5816 assert(hor_ds_factor == ver_ds_factor); 5817 5818 i = 1; 5819 while (i < hor_ds_factor) { 5820 descr->num_stage++; 5821 i *= max_scale_factor_per_stage; 5822 } 5823 5824 descr->in_info = kmalloc(descr->num_stage * 5825 sizeof(struct ia_css_frame_info), 5826 GFP_KERNEL); 5827 if (!descr->in_info) { 5828 err = -ENOMEM; 5829 goto ERR; 5830 } 5831 descr->internal_out_info = kmalloc(descr->num_stage * 5832 sizeof(struct ia_css_frame_info), 5833 GFP_KERNEL); 5834 if (!descr->internal_out_info) { 5835 err = -ENOMEM; 5836 goto ERR; 5837 } 5838 descr->out_info = kmalloc(descr->num_stage * 5839 sizeof(struct ia_css_frame_info), 5840 GFP_KERNEL); 5841 if (!descr->out_info) { 5842 err = -ENOMEM; 5843 goto ERR; 5844 } 5845 descr->vf_info = kmalloc(descr->num_stage * 5846 sizeof(struct ia_css_frame_info), 5847 GFP_KERNEL); 5848 if (!descr->vf_info) { 5849 err = -ENOMEM; 5850 goto ERR; 5851 } 5852 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), 5853 GFP_KERNEL); 5854 if (!descr->is_output_stage) { 5855 err = -ENOMEM; 5856 goto ERR; 5857 } 5858 5859 tmp_in_info = *in_info; 5860 for (i = 0; i < descr->num_stage; i++) { 5861 descr->in_info[i] = tmp_in_info; 5862 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= out_info->res.width) { 5863 descr->is_output_stage[i] = true; 5864 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) { 5865 descr->internal_out_info[i].res.width = out_info->res.width; 5866 descr->internal_out_info[i].res.height = out_info->res.height; 5867 descr->internal_out_info[i].padded_width = out_info->padded_width; 5868 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 5869 } else { 5870 assert(i == (descr->num_stage - 1)); 5871 descr->internal_out_info[i].res.width = 0; 5872 descr->internal_out_info[i].res.height = 0; 5873 } 5874 descr->out_info[i].res.width = out_info->res.width; 5875 descr->out_info[i].res.height = out_info->res.height; 5876 descr->out_info[i].padded_width = out_info->padded_width; 5877 descr->out_info[i].format = out_info->format; 5878 if (vf_info) { 5879 descr->vf_info[i].res.width = vf_info->res.width; 5880 descr->vf_info[i].res.height = vf_info->res.height; 5881 descr->vf_info[i].padded_width = vf_info->padded_width; 5882 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE); 5883 } else { 5884 descr->vf_info[i].res.width = 0; 5885 descr->vf_info[i].res.height = 0; 5886 descr->vf_info[i].padded_width = 0; 5887 } 5888 } else { 5889 descr->is_output_stage[i] = false; 5890 descr->internal_out_info[i].res.width = tmp_in_info.res.width / 5891 max_scale_factor_per_stage; 5892 descr->internal_out_info[i].res.height = tmp_in_info.res.height / 5893 max_scale_factor_per_stage; 5894 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; 5895 ia_css_frame_info_init(&descr->internal_out_info[i], 5896 tmp_in_info.res.width / max_scale_factor_per_stage, 5897 tmp_in_info.res.height / max_scale_factor_per_stage, 5898 IA_CSS_FRAME_FORMAT_YUV420, 0); 5899 descr->out_info[i].res.width = 0; 5900 descr->out_info[i].res.height = 0; 5901 descr->vf_info[i].res.width = 0; 5902 descr->vf_info[i].res.height = 0; 5903 } 5904 tmp_in_info = descr->internal_out_info[i]; 5905 } 5906ERR: 5907 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5908 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n", 5909 err); 5910 return err; 5911} 5912 5913/* FIXME: merge most of this and single output version */ 5914static int 5915ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe *pipe, 5916 struct ia_css_cas_binary_descr *descr) 5917{ 5918 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; 5919 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 5920 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 5921 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; 5922 unsigned int i, j; 5923 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE], 5924 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE], 5925 scale_factor = 0; 5926 unsigned int num_stages = 0; 5927 int err = 0; 5928 5929 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP; 5930 5931 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 5932 "ia_css_pipe_create_cas_scaler_desc() enter:\n"); 5933 5934 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 5935 out_info[i] = NULL; 5936 vf_out_info[i] = NULL; 5937 hor_scale_factor[i] = 0; 5938 ver_scale_factor[i] = 0; 5939 } 5940 5941 in_info.res = pipe->config.input_effective_res; 5942 in_info.padded_width = in_info.res.width; 5943 descr->num_output_stage = 0; 5944 /* Find out how much scaling we need for each output */ 5945 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 5946 if (pipe->output_info[i].res.width != 0) { 5947 out_info[i] = &pipe->output_info[i]; 5948 if (pipe->vf_output_info[i].res.width != 0) 5949 vf_out_info[i] = &pipe->vf_output_info[i]; 5950 descr->num_output_stage += 1; 5951 } 5952 5953 if (out_info[i]) { 5954 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width); 5955 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height); 5956 /* use the same horizontal and vertical scaling factor for simplicity */ 5957 assert(hor_scale_factor[i] == ver_scale_factor[i]); 5958 scale_factor = 1; 5959 do { 5960 num_stages++; 5961 scale_factor *= max_scale_factor_per_stage; 5962 } while (scale_factor < hor_scale_factor[i]); 5963 5964 in_info.res = out_info[i]->res; 5965 } 5966 } 5967 5968 if (need_yuv_scaler_stage(pipe) && (num_stages == 0)) 5969 num_stages = 1; 5970 5971 descr->num_stage = num_stages; 5972 5973 descr->in_info = kmalloc_array(descr->num_stage, 5974 sizeof(struct ia_css_frame_info), 5975 GFP_KERNEL); 5976 if (!descr->in_info) { 5977 err = -ENOMEM; 5978 goto ERR; 5979 } 5980 descr->internal_out_info = kmalloc(descr->num_stage * 5981 sizeof(struct ia_css_frame_info), 5982 GFP_KERNEL); 5983 if (!descr->internal_out_info) { 5984 err = -ENOMEM; 5985 goto ERR; 5986 } 5987 descr->out_info = kmalloc(descr->num_stage * 5988 sizeof(struct ia_css_frame_info), 5989 GFP_KERNEL); 5990 if (!descr->out_info) { 5991 err = -ENOMEM; 5992 goto ERR; 5993 } 5994 descr->vf_info = kmalloc(descr->num_stage * 5995 sizeof(struct ia_css_frame_info), 5996 GFP_KERNEL); 5997 if (!descr->vf_info) { 5998 err = -ENOMEM; 5999 goto ERR; 6000 } 6001 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), 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 } 6070ERR: 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 6077static 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 6096static int 6097load_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 = kcalloc(cas_scaler_descr.num_stage, 6147 sizeof(struct ia_css_binary), 6148 GFP_KERNEL); 6149 if (!mycs->yuv_scaler_binary) { 6150 err = -ENOMEM; 6151 goto ERR; 6152 } 6153 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage, 6154 sizeof(bool), GFP_KERNEL); 6155 if (!mycs->is_output_stage) { 6156 err = -ENOMEM; 6157 goto ERR; 6158 } 6159 for (i = 0; i < cas_scaler_descr.num_stage; i++) { 6160 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; 6161 ia_css_pipe_get_yuvscaler_binarydesc(pipe, 6162 &yuv_scaler_descr, 6163 &cas_scaler_descr.in_info[i], 6164 &cas_scaler_descr.out_info[i], 6165 &cas_scaler_descr.internal_out_info[i], 6166 &cas_scaler_descr.vf_info[i]); 6167 err = ia_css_binary_find(&yuv_scaler_descr, 6168 &mycs->yuv_scaler_binary[i]); 6169 if (err) 6170 goto ERR; 6171 } 6172 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 6173 } else { 6174 mycs->num_output = 1; 6175 } 6176 6177 if (need_scaler) 6178 next_binary = &mycs->yuv_scaler_binary[0]; 6179 else 6180 next_binary = NULL; 6181 6182 /* 6183 * NOTES 6184 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when 6185 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"? 6186 * 6187 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_ 6188 * binary". However, the "yuv_scale_binary" does NOT support the input-frame 6189 * format as "IA_CSS_STREAM _FORMAT_YUV422_8". 6190 * 6191 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv 6192 * _scale_binary". It would translate the input-frame to the frame formats that 6193 * are supported by the "yuv_scale_binary". 6194 * 6195 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_ 6196 * pp_defs.h" for the list of input-frame formats that are supported by the 6197 * "yuv_scale_binary". 6198 */ 6199 if (IS_ISP2401) 6200 need_isp_copy_binary = 6201 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); 6202 else 6203 need_isp_copy_binary = true; 6204 6205 if (need_isp_copy_binary) { 6206 err = load_copy_binary(pipe, 6207 &mycs->copy_binary, 6208 next_binary); 6209 6210 if (err) 6211 goto ERR; 6212 6213 /* 6214 * NOTES 6215 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified? 6216 * 6217 * In some use cases, the first stage in the "yuvpp" pipe is the 6218 * "isp_copy_binary". The "isp_copy_binary" is designed to process 6219 * the input from either the system DDR or from the IPU internal VMEM. 6220 * So it provides the flag "online" to specify where its input is from, 6221 * i.e.: 6222 * 6223 * (1) "online <= true", the input is from the IPU internal VMEM. 6224 * (2) "online <= false", the input is from the system DDR. 6225 * 6226 * In other use cases, the first stage in the "yuvpp" pipe is the 6227 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the 6228 * input ONLY from the system DDR. So it does not provide the flag "online" 6229 * to specify where its input is from. 6230 */ 6231 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; 6232 } 6233 6234 /* Viewfinder post-processing */ 6235 if (need_scaler) { 6236 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) { 6237 if (mycs->is_output_stage[i]) { 6238 assert(j < 2); 6239 vf_pp_in_info[j] = 6240 &mycs->yuv_scaler_binary[i].vf_frame_info; 6241 j++; 6242 } 6243 } 6244 mycs->num_vf_pp = j; 6245 } else { 6246 vf_pp_in_info[0] = 6247 &mycs->copy_binary.vf_frame_info; 6248 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) 6249 vf_pp_in_info[i] = NULL; 6250 6251 mycs->num_vf_pp = 1; 6252 } 6253 mycs->vf_pp_binary = kcalloc(mycs->num_vf_pp, 6254 sizeof(struct ia_css_binary), 6255 GFP_KERNEL); 6256 if (!mycs->vf_pp_binary) { 6257 err = -ENOMEM; 6258 goto ERR; 6259 } 6260 6261 { 6262 struct ia_css_binary_descr vf_pp_descr; 6263 6264 for (i = 0; i < mycs->num_vf_pp; i++) { 6265 if (pipe->vf_output_info[i].res.width != 0) { 6266 ia_css_pipe_get_vfpp_binarydesc(pipe, 6267 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]); 6268 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]); 6269 if (err) 6270 goto ERR; 6271 } 6272 } 6273 } 6274 6275ERR: 6276 if (need_scaler) 6277 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); 6278 6279 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n", 6280 err); 6281 return err; 6282} 6283 6284static int 6285unload_yuvpp_binaries(struct ia_css_pipe *pipe) 6286{ 6287 unsigned int i; 6288 6289 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 6290 6291 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { 6292 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 6293 return -EINVAL; 6294 } 6295 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary); 6296 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++) 6297 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]); 6298 6299 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++) 6300 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]); 6301 6302 kfree(pipe->pipe_settings.yuvpp.is_output_stage); 6303 pipe->pipe_settings.yuvpp.is_output_stage = NULL; 6304 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary); 6305 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL; 6306 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary); 6307 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL; 6308 6309 IA_CSS_LEAVE_ERR_PRIVATE(0); 6310 return 0; 6311} 6312 6313static int yuvpp_start(struct ia_css_pipe *pipe) 6314{ 6315 int err = 0; 6316 enum sh_css_pipe_config_override copy_ovrd; 6317 enum ia_css_input_mode yuvpp_pipe_input_mode; 6318 unsigned int thread_id; 6319 6320 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 6321 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { 6322 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 6323 return -EINVAL; 6324 } 6325 6326 yuvpp_pipe_input_mode = pipe->stream->config.mode; 6327 6328 sh_css_metrics_start_frame(); 6329 6330 /* multi stream video needs mipi buffers */ 6331 6332 err = send_mipi_frames(pipe); 6333 if (err) { 6334 IA_CSS_LEAVE_ERR_PRIVATE(err); 6335 return err; 6336 } 6337 6338 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 6339 copy_ovrd = 1 << thread_id; 6340 6341 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode); 6342 6343 IA_CSS_LEAVE_ERR_PRIVATE(err); 6344 return err; 6345} 6346 6347static int 6348sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) 6349{ 6350 int err = 0; 6351 6352 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 6353 6354 if (!pipe) { 6355 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 6356 return -EINVAL; 6357 } 6358 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ 6359 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) { 6360 IA_CSS_LEAVE_ERR_PRIVATE(0); 6361 return 0; 6362 } 6363 6364 switch (pipe->mode) { 6365 case IA_CSS_PIPE_ID_PREVIEW: 6366 err = unload_preview_binaries(pipe); 6367 break; 6368 case IA_CSS_PIPE_ID_VIDEO: 6369 err = unload_video_binaries(pipe); 6370 break; 6371 case IA_CSS_PIPE_ID_CAPTURE: 6372 err = unload_capture_binaries(pipe); 6373 break; 6374 case IA_CSS_PIPE_ID_YUVPP: 6375 err = unload_yuvpp_binaries(pipe); 6376 break; 6377 default: 6378 break; 6379 } 6380 IA_CSS_LEAVE_ERR_PRIVATE(err); 6381 return err; 6382} 6383 6384static int 6385sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) 6386{ 6387 int err = 0; 6388 6389 assert(pipe); 6390 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n"); 6391 6392 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ 6393 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 6394 return err; 6395 6396 switch (pipe->mode) { 6397 case IA_CSS_PIPE_ID_PREVIEW: 6398 err = load_preview_binaries(pipe); 6399 break; 6400 case IA_CSS_PIPE_ID_VIDEO: 6401 err = load_video_binaries(pipe); 6402 break; 6403 case IA_CSS_PIPE_ID_CAPTURE: 6404 err = load_capture_binaries(pipe); 6405 break; 6406 case IA_CSS_PIPE_ID_YUVPP: 6407 err = load_yuvpp_binaries(pipe); 6408 break; 6409 default: 6410 err = -EINVAL; 6411 break; 6412 } 6413 if (err) { 6414 if (sh_css_pipe_unload_binaries(pipe)) { 6415 /* 6416 * currently css does not support multiple error 6417 * returns in a single function, using -EINVAL in 6418 * this case 6419 */ 6420 err = -EINVAL; 6421 } 6422 } 6423 return err; 6424} 6425 6426static int 6427create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) 6428{ 6429 struct ia_css_pipeline *me; 6430 int err = 0; 6431 struct ia_css_pipeline_stage *vf_pp_stage = NULL, 6432 *copy_stage = NULL, 6433 *yuv_scaler_stage = NULL; 6434 struct ia_css_binary *copy_binary, 6435 *vf_pp_binary, 6436 *yuv_scaler_binary; 6437 bool need_scaler = false; 6438 unsigned int num_stage, num_output_stage; 6439 unsigned int i, j; 6440 6441 struct ia_css_frame *in_frame = NULL; 6442 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 6443 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 6444 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; 6445 struct ia_css_pipeline_stage_desc stage_desc; 6446 bool need_in_frameinfo_memory = false; 6447 bool sensor = false; 6448 bool buffered_sensor = false; 6449 bool online = false; 6450 bool continuous = false; 6451 6452 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 6453 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { 6454 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 6455 return -EINVAL; 6456 } 6457 me = &pipe->pipeline; 6458 ia_css_pipeline_clean(me); 6459 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 6460 out_frame[i] = NULL; 6461 vf_frame[i] = NULL; 6462 } 6463 ia_css_pipe_util_create_output_frames(bin_out_frame); 6464 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler; 6465 num_output_stage = pipe->pipe_settings.yuvpp.num_output; 6466 6467 if (IS_ISP2401) { 6468 /* 6469 * When the input system is 2401, always enable 'in_frameinfo_memory' 6470 * except for the following: 6471 * - Direct Sensor Mode Online Capture 6472 * - Direct Sensor Mode Continuous Capture 6473 * - Buffered Sensor Mode Continuous Capture 6474 */ 6475 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; 6476 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; 6477 online = pipe->stream->config.online; 6478 continuous = pipe->stream->config.continuous; 6479 need_in_frameinfo_memory = 6480 !((sensor && (online || continuous)) || (buffered_sensor && continuous)); 6481 } else { 6482 /* Construct in_frame info (only in case we have dynamic input */ 6483 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 6484 } 6485 /* 6486 * the input frame can come from: 6487 * 6488 * a) memory: connect yuvscaler to me->in_frame 6489 * b) sensor, via copy binary: connect yuvscaler to copy binary later 6490 * on 6491 */ 6492 if (need_in_frameinfo_memory) { 6493 /* TODO: improve for different input formats. */ 6494 6495 /* 6496 * "pipe->stream->config.input_config.format" represents the sensor output 6497 * frame format, e.g. YUV422 8-bit. 6498 * 6499 * "in_frame_format" represents the imaging pipe's input frame format, e.g. 6500 * Bayer-Quad RAW. 6501 */ 6502 int in_frame_format; 6503 6504 if (pipe->stream->config.input_config.format == 6505 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) { 6506 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8; 6507 } else if (pipe->stream->config.input_config.format == 6508 ATOMISP_INPUT_FORMAT_YUV422_8) { 6509 /* 6510 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8", 6511 * the "isp_copy_var" binary is selected as the first stage in the yuvpp 6512 * pipe. 6513 * 6514 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from 6515 * the frame buffer (at DDR) to the frame-line buffer (at VMEM). 6516 * 6517 * By now, the "isp_copy_var" binary does NOT provide a separated 6518 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores 6519 * the YUV422-8 pixels in the frame-line buffer which is designed to 6520 * store the Bayer-Quad RAW pixels. 6521 * 6522 * To direct the "isp_copy_var" binary reading from the RAW frame-line 6523 * buffer, its input frame format must be specified as "IA_CSS_FRAME_ 6524 * FORMAT_RAW". 6525 */ 6526 in_frame_format = IA_CSS_FRAME_FORMAT_RAW; 6527 } else { 6528 in_frame_format = IA_CSS_FRAME_FORMAT_NV12; 6529 } 6530 6531 err = init_in_frameinfo_memory_defaults(pipe, 6532 &me->in_frame, 6533 in_frame_format); 6534 6535 if (err) { 6536 IA_CSS_LEAVE_ERR_PRIVATE(err); 6537 return err; 6538 } 6539 6540 in_frame = &me->in_frame; 6541 } else { 6542 in_frame = NULL; 6543 } 6544 6545 for (i = 0; i < num_output_stage; i++) { 6546 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE); 6547 if (pipe->output_info[i].res.width != 0) { 6548 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i); 6549 if (err) { 6550 IA_CSS_LEAVE_ERR_PRIVATE(err); 6551 return err; 6552 } 6553 out_frame[i] = &me->out_frame[i]; 6554 } 6555 6556 /* Construct vf_frame info (only in case we have VF) */ 6557 if (pipe->vf_output_info[i].res.width != 0) { 6558 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i); 6559 if (err) { 6560 IA_CSS_LEAVE_ERR_PRIVATE(err); 6561 return err; 6562 } 6563 vf_frame[i] = &me->vf_frame[i]; 6564 } 6565 } 6566 6567 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary; 6568 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary; 6569 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary; 6570 need_scaler = need_yuv_scaler_stage(pipe); 6571 6572 if (pipe->pipe_settings.yuvpp.copy_binary.info) { 6573 struct ia_css_frame *in_frame_local = NULL; 6574 6575 if (IS_ISP2401 && !online) { 6576 /* After isp copy is enabled in_frame needs to be passed. */ 6577 in_frame_local = in_frame; 6578 } 6579 6580 if (need_scaler) { 6581 ia_css_pipe_util_set_output_frames(bin_out_frame, 6582 0, NULL); 6583 ia_css_pipe_get_generic_stage_desc(&stage_desc, 6584 copy_binary, 6585 bin_out_frame, 6586 in_frame_local, 6587 NULL); 6588 } else { 6589 ia_css_pipe_util_set_output_frames(bin_out_frame, 6590 0, out_frame[0]); 6591 ia_css_pipe_get_generic_stage_desc(&stage_desc, 6592 copy_binary, 6593 bin_out_frame, 6594 in_frame_local, 6595 NULL); 6596 } 6597 6598 err = ia_css_pipeline_create_and_add_stage(me, 6599 &stage_desc, 6600 ©_stage); 6601 6602 if (err) { 6603 IA_CSS_LEAVE_ERR_PRIVATE(err); 6604 return err; 6605 } 6606 6607 if (copy_stage) { 6608 /* if we use yuv scaler binary, vf output should be from there */ 6609 copy_stage->args.copy_vf = !need_scaler; 6610 /* for yuvpp pipe, it should always be enabled */ 6611 copy_stage->args.copy_output = true; 6612 /* connect output of copy binary to input of yuv scaler */ 6613 in_frame = copy_stage->args.out_frame[0]; 6614 } 6615 } 6616 6617 if (need_scaler) { 6618 struct ia_css_frame *tmp_out_frame = NULL; 6619 struct ia_css_frame *tmp_vf_frame = NULL; 6620 struct ia_css_frame *tmp_in_frame = in_frame; 6621 6622 for (i = 0, j = 0; i < num_stage; i++) { 6623 assert(j < num_output_stage); 6624 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { 6625 tmp_out_frame = out_frame[j]; 6626 tmp_vf_frame = vf_frame[j]; 6627 } else { 6628 tmp_out_frame = NULL; 6629 tmp_vf_frame = NULL; 6630 } 6631 6632 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, 6633 tmp_out_frame, 6634 NULL, 6635 &yuv_scaler_binary[i], 6636 &yuv_scaler_stage); 6637 6638 if (err) { 6639 IA_CSS_LEAVE_ERR_PRIVATE(err); 6640 return err; 6641 } 6642 /* we use output port 1 as internal output port */ 6643 tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; 6644 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { 6645 if (tmp_vf_frame && (tmp_vf_frame->frame_info.res.width != 0)) { 6646 in_frame = yuv_scaler_stage->args.out_vf_frame; 6647 err = add_vf_pp_stage(pipe, in_frame, 6648 tmp_vf_frame, 6649 &vf_pp_binary[j], 6650 &vf_pp_stage); 6651 6652 if (err) { 6653 IA_CSS_LEAVE_ERR_PRIVATE(err); 6654 return err; 6655 } 6656 } 6657 j++; 6658 } 6659 } 6660 } else if (copy_stage) { 6661 if (vf_frame[0] && vf_frame[0]->frame_info.res.width != 0) { 6662 in_frame = copy_stage->args.out_vf_frame; 6663 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], 6664 &vf_pp_binary[0], &vf_pp_stage); 6665 } 6666 if (err) { 6667 IA_CSS_LEAVE_ERR_PRIVATE(err); 6668 return err; 6669 } 6670 } 6671 6672 ia_css_pipeline_finalize_stages(&pipe->pipeline, 6673 pipe->stream->config.continuous); 6674 6675 IA_CSS_LEAVE_ERR_PRIVATE(0); 6676 6677 return 0; 6678} 6679 6680static int 6681create_host_copy_pipeline(struct ia_css_pipe *pipe, 6682 unsigned int max_input_width, 6683 struct ia_css_frame *out_frame) 6684{ 6685 struct ia_css_pipeline *me; 6686 int err = 0; 6687 struct ia_css_pipeline_stage_desc stage_desc; 6688 6689 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6690 "create_host_copy_pipeline() enter:\n"); 6691 6692 /* pipeline already created as part of create_host_pipeline_structure */ 6693 me = &pipe->pipeline; 6694 ia_css_pipeline_clean(me); 6695 6696 /* Construct out_frame info */ 6697 if (copy_on_sp(pipe) && 6698 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { 6699 ia_css_frame_info_init(&out_frame->frame_info, JPEG_BYTES, 1, 6700 IA_CSS_FRAME_FORMAT_BINARY_8, 0); 6701 } else if (out_frame->frame_info.format == IA_CSS_FRAME_FORMAT_RAW) { 6702 out_frame->frame_info.raw_bit_depth = 6703 ia_css_pipe_util_pipe_input_format_bpp(pipe); 6704 } 6705 6706 me->num_stages = 1; 6707 me->pipe_id = IA_CSS_PIPE_ID_COPY; 6708 pipe->mode = IA_CSS_PIPE_ID_COPY; 6709 6710 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, 6711 IA_CSS_PIPELINE_RAW_COPY, 6712 max_input_width); 6713 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, NULL); 6714 6715 ia_css_pipeline_finalize_stages(&pipe->pipeline, 6716 pipe->stream->config.continuous); 6717 6718 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6719 "create_host_copy_pipeline() leave:\n"); 6720 6721 return err; 6722} 6723 6724static int 6725create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) 6726{ 6727 struct ia_css_pipeline *me = &pipe->pipeline; 6728 int err = 0; 6729 struct ia_css_pipeline_stage_desc stage_desc; 6730 struct ia_css_frame *out_frame = &me->out_frame[0]; 6731 struct ia_css_pipeline_stage *out_stage = NULL; 6732 unsigned int thread_id; 6733 enum sh_css_queue_id queue_id; 6734 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS; 6735 6736 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6737 "create_host_isyscopy_capture_pipeline() enter:\n"); 6738 ia_css_pipeline_clean(me); 6739 6740 /* Construct out_frame info */ 6741 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->frame_info, 0); 6742 if (err) 6743 return err; 6744 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 6745 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id); 6746 out_frame->dynamic_queue_id = queue_id; 6747 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; 6748 6749 me->num_stages = 1; 6750 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE; 6751 pipe->mode = IA_CSS_PIPE_ID_CAPTURE; 6752 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, 6753 IA_CSS_PIPELINE_ISYS_COPY, 6754 max_input_width); 6755 err = ia_css_pipeline_create_and_add_stage(me, 6756 &stage_desc, &out_stage); 6757 if (err) 6758 return err; 6759 6760 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous); 6761 6762 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 6763 "create_host_isyscopy_capture_pipeline() leave:\n"); 6764 6765 return err; 6766} 6767 6768static int 6769create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) 6770{ 6771 struct ia_css_pipeline *me; 6772 int err = 0; 6773 enum ia_css_capture_mode mode; 6774 struct ia_css_pipeline_stage *current_stage = NULL; 6775 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL; 6776 struct ia_css_binary *copy_binary, 6777 *primary_binary[MAX_NUM_PRIMARY_STAGES], 6778 *vf_pp_binary, 6779 *pre_isp_binary, 6780 *anr_gdc_binary, 6781 *post_isp_binary, 6782 *yuv_scaler_binary, 6783 *capture_pp_binary, 6784 *capture_ldc_binary; 6785 bool need_pp = false; 6786 bool raw; 6787 6788 struct ia_css_frame *in_frame; 6789 struct ia_css_frame *out_frame; 6790 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; 6791 struct ia_css_frame *vf_frame; 6792 struct ia_css_pipeline_stage_desc stage_desc; 6793 bool need_in_frameinfo_memory = false; 6794 bool sensor = false; 6795 bool buffered_sensor = false; 6796 bool online = false; 6797 bool continuous = false; 6798 unsigned int i, num_yuv_scaler, num_primary_stage; 6799 bool need_yuv_pp = false; 6800 bool *is_output_stage = NULL; 6801 bool need_ldc = false; 6802 6803 IA_CSS_ENTER_PRIVATE(""); 6804 assert(pipe); 6805 assert(pipe->stream); 6806 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || 6807 pipe->mode == IA_CSS_PIPE_ID_COPY); 6808 6809 me = &pipe->pipeline; 6810 mode = pipe->config.default_capture_config.mode; 6811 raw = (mode == IA_CSS_CAPTURE_MODE_RAW); 6812 ia_css_pipeline_clean(me); 6813 ia_css_pipe_util_create_output_frames(out_frames); 6814 6815 if (IS_ISP2401) { 6816 /* 6817 * When the input system is 2401, always enable 'in_frameinfo_memory' 6818 * except for the following: 6819 * - Direct Sensor Mode Online Capture 6820 * - Direct Sensor Mode Online Capture 6821 * - Direct Sensor Mode Continuous Capture 6822 * - Buffered Sensor Mode Continuous Capture 6823 */ 6824 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); 6825 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 6826 online = pipe->stream->config.online; 6827 continuous = pipe->stream->config.continuous; 6828 need_in_frameinfo_memory = 6829 !((sensor && (online || continuous)) || (buffered_sensor && 6830 (online || continuous))); 6831 } else { 6832 /* Construct in_frame info (only in case we have dynamic input */ 6833 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 6834 } 6835 6836 if (need_in_frameinfo_memory) { 6837 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, 6838 IA_CSS_FRAME_FORMAT_RAW); 6839 if (err) { 6840 IA_CSS_LEAVE_ERR_PRIVATE(err); 6841 return err; 6842 } 6843 6844 in_frame = &me->in_frame; 6845 } else { 6846 in_frame = NULL; 6847 } 6848 6849 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); 6850 if (err) { 6851 IA_CSS_LEAVE_ERR_PRIVATE(err); 6852 return err; 6853 } 6854 out_frame = &me->out_frame[0]; 6855 6856 /* Construct vf_frame info (only in case we have VF) */ 6857 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { 6858 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) { 6859 /* These modes don't support viewfinder output */ 6860 vf_frame = NULL; 6861 } else { 6862 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0); 6863 vf_frame = &me->vf_frame[0]; 6864 } 6865 } else { 6866 vf_frame = NULL; 6867 } 6868 6869 copy_binary = &pipe->pipe_settings.capture.copy_binary; 6870 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage; 6871 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) { 6872 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 6873 return -EINVAL; 6874 } 6875 6876 for (i = 0; i < num_primary_stage; i++) 6877 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i]; 6878 6879 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary; 6880 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary; 6881 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary; 6882 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary; 6883 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary; 6884 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary; 6885 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler; 6886 is_output_stage = pipe->pipe_settings.capture.is_output_stage; 6887 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary; 6888 6889 need_pp = (need_capture_pp(pipe) || pipe->output_stage) && 6890 mode != IA_CSS_CAPTURE_MODE_RAW && 6891 mode != IA_CSS_CAPTURE_MODE_BAYER; 6892 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info); 6893 need_ldc = (capture_ldc_binary && capture_ldc_binary->info); 6894 6895 if (pipe->pipe_settings.capture.copy_binary.info) { 6896 if (raw) { 6897 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 6898 if (IS_ISP2401) { 6899 if (!continuous) { 6900 ia_css_pipe_get_generic_stage_desc(&stage_desc, 6901 copy_binary, 6902 out_frames, 6903 in_frame, 6904 NULL); 6905 } else { 6906 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 6907 ia_css_pipe_get_generic_stage_desc(&stage_desc, 6908 copy_binary, 6909 out_frames, 6910 in_frame, 6911 NULL); 6912 } 6913 } else { 6914 ia_css_pipe_get_generic_stage_desc(&stage_desc, 6915 copy_binary, 6916 out_frames, 6917 NULL, NULL); 6918 } 6919 } else { 6920 ia_css_pipe_util_set_output_frames(out_frames, 0, 6921 in_frame); 6922 ia_css_pipe_get_generic_stage_desc(&stage_desc, 6923 copy_binary, 6924 out_frames, 6925 NULL, NULL); 6926 } 6927 6928 err = ia_css_pipeline_create_and_add_stage(me, 6929 &stage_desc, 6930 ¤t_stage); 6931 if (err) { 6932 IA_CSS_LEAVE_ERR_PRIVATE(err); 6933 return err; 6934 } 6935 } else if (pipe->stream->config.continuous) { 6936 in_frame = pipe->stream->last_pipe->continuous_frames[0]; 6937 } 6938 6939 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 6940 struct ia_css_frame *local_in_frame = NULL; 6941 struct ia_css_frame *local_out_frame = NULL; 6942 6943 for (i = 0; i < num_primary_stage; i++) { 6944 if (i == 0) 6945 local_in_frame = in_frame; 6946 else 6947 local_in_frame = NULL; 6948 if (!need_pp && (i == num_primary_stage - 1) && (!IS_ISP2401 || !need_ldc)) 6949 local_out_frame = out_frame; 6950 else 6951 local_out_frame = NULL; 6952 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame); 6953 /* 6954 * WARNING: The #if def flag has been added below as a 6955 * temporary solution to solve the problem of enabling the 6956 * view finder in a single binary in a capture flow. The 6957 * vf-pp stage has been removed from Skycam in the solution 6958 * provided. The vf-pp stage should be re-introduced when 6959 * required. This * should not be considered as a clean solution. 6960 * Proper investigation should be done to come up with the clean 6961 * solution. 6962 */ 6963 ia_css_pipe_get_generic_stage_desc(&stage_desc, 6964 primary_binary[i], 6965 out_frames, 6966 local_in_frame, 6967 NULL); 6968 err = ia_css_pipeline_create_and_add_stage(me, 6969 &stage_desc, 6970 ¤t_stage); 6971 if (err) { 6972 IA_CSS_LEAVE_ERR_PRIVATE(err); 6973 return err; 6974 } 6975 } 6976 /* If we use copy iso primary, the input must be yuv iso raw */ 6977 current_stage->args.copy_vf = 6978 primary_binary[0]->info->sp.pipeline.mode == 6979 IA_CSS_BINARY_MODE_COPY; 6980 current_stage->args.copy_output = current_stage->args.copy_vf; 6981 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED || 6982 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { 6983 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 6984 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, 6985 out_frames, in_frame, NULL); 6986 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, 6987 NULL); 6988 if (err) { 6989 IA_CSS_LEAVE_ERR_PRIVATE(err); 6990 return err; 6991 } 6992 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 6993 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary, 6994 out_frames, NULL, NULL); 6995 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, 6996 NULL); 6997 if (err) { 6998 IA_CSS_LEAVE_ERR_PRIVATE(err); 6999 return err; 7000 } 7001 7002 if (need_pp) { 7003 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 7004 ia_css_pipe_get_generic_stage_desc(&stage_desc, 7005 post_isp_binary, 7006 out_frames, 7007 NULL, NULL); 7008 } else { 7009 ia_css_pipe_util_set_output_frames(out_frames, 0, 7010 out_frame); 7011 ia_css_pipe_get_generic_stage_desc(&stage_desc, 7012 post_isp_binary, 7013 out_frames, 7014 NULL, NULL); 7015 } 7016 7017 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, 7018 ¤t_stage); 7019 if (err) { 7020 IA_CSS_LEAVE_ERR_PRIVATE(err); 7021 return err; 7022 } 7023 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) { 7024 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); 7025 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, 7026 out_frames, in_frame, NULL); 7027 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, 7028 NULL); 7029 if (err) { 7030 IA_CSS_LEAVE_ERR_PRIVATE(err); 7031 return err; 7032 } 7033 } 7034 7035 if (need_pp && current_stage) { 7036 struct ia_css_frame *local_in_frame = NULL; 7037 7038 local_in_frame = current_stage->args.out_frame[0]; 7039 7040 if (need_ldc) { 7041 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); 7042 ia_css_pipe_get_generic_stage_desc(&stage_desc, 7043 capture_ldc_binary, 7044 out_frames, 7045 local_in_frame, 7046 NULL); 7047 err = ia_css_pipeline_create_and_add_stage(me, 7048 &stage_desc, 7049 ¤t_stage); 7050 local_in_frame = current_stage->args.out_frame[0]; 7051 } 7052 err = add_capture_pp_stage(pipe, me, local_in_frame, 7053 need_yuv_pp ? NULL : out_frame, 7054 capture_pp_binary, 7055 ¤t_stage); 7056 if (err) { 7057 IA_CSS_LEAVE_ERR_PRIVATE(err); 7058 return err; 7059 } 7060 } 7061 7062 if (need_yuv_pp && current_stage) { 7063 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0]; 7064 struct ia_css_frame *tmp_out_frame = NULL; 7065 7066 for (i = 0; i < num_yuv_scaler; i++) { 7067 if (is_output_stage[i]) 7068 tmp_out_frame = out_frame; 7069 else 7070 tmp_out_frame = NULL; 7071 7072 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, 7073 tmp_out_frame, NULL, 7074 &yuv_scaler_binary[i], 7075 &yuv_scaler_stage); 7076 if (err) { 7077 IA_CSS_LEAVE_ERR_PRIVATE(err); 7078 return err; 7079 } 7080 /* we use output port 1 as internal output port */ 7081 tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; 7082 } 7083 } 7084 7085 /* 7086 * WARNING: The #if def flag has been added below as a 7087 * temporary solution to solve the problem of enabling the 7088 * view finder in a single binary in a capture flow. The vf-pp 7089 * stage has been removed from Skycam in the solution provided. 7090 * The vf-pp stage should be re-introduced when required. This 7091 * should not be considered as a clean solution. Proper 7092 * investigation should be done to come up with the clean solution. 7093 */ 7094 if (mode != IA_CSS_CAPTURE_MODE_RAW && 7095 mode != IA_CSS_CAPTURE_MODE_BAYER && 7096 current_stage && vf_frame) { 7097 in_frame = current_stage->args.out_vf_frame; 7098 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary, 7099 ¤t_stage); 7100 if (err) { 7101 IA_CSS_LEAVE_ERR_PRIVATE(err); 7102 return err; 7103 } 7104 } 7105 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); 7106 7107 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7108 "create_host_regular_capture_pipeline() leave:\n"); 7109 7110 return 0; 7111} 7112 7113static int 7114create_host_capture_pipeline(struct ia_css_pipe *pipe) 7115{ 7116 int err = 0; 7117 7118 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7119 7120 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) 7121 err = create_host_isyscopy_capture_pipeline(pipe); 7122 else 7123 err = create_host_regular_capture_pipeline(pipe); 7124 if (err) { 7125 IA_CSS_LEAVE_ERR_PRIVATE(err); 7126 return err; 7127 } 7128 7129 IA_CSS_LEAVE_ERR_PRIVATE(err); 7130 7131 return err; 7132} 7133 7134static int capture_start(struct ia_css_pipe *pipe) 7135{ 7136 struct ia_css_pipeline *me; 7137 unsigned int thread_id; 7138 7139 int err = 0; 7140 enum sh_css_pipe_config_override copy_ovrd; 7141 7142 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); 7143 if (!pipe) { 7144 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 7145 return -EINVAL; 7146 } 7147 7148 me = &pipe->pipeline; 7149 7150 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || 7151 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) && 7152 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { 7153 if (copy_on_sp(pipe)) { 7154 err = start_copy_on_sp(pipe, &me->out_frame[0]); 7155 IA_CSS_LEAVE_ERR_PRIVATE(err); 7156 return err; 7157 } 7158 } 7159 /* old isys: need to send_mipi_frames() in all pipe modes */ 7160 if (!IS_ISP2401 || pipe->config.mode != IA_CSS_PIPE_MODE_COPY) { 7161 err = send_mipi_frames(pipe); 7162 if (err) { 7163 IA_CSS_LEAVE_ERR_PRIVATE(err); 7164 return err; 7165 } 7166 } 7167 7168 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); 7169 copy_ovrd = 1 << thread_id; 7170 7171 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode); 7172 7173 /* 7174 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured, 7175 * which is currently done in start_binary(); but COPY pipe contains no binary, 7176 * and does not call start_binary(); so we need to configure the rx here. 7177 */ 7178 if (!IS_ISP2401 && 7179 pipe->config.mode == IA_CSS_PIPE_MODE_COPY && 7180 pipe->stream->reconfigure_css_rx) { 7181 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, 7182 pipe->stream->config.mode); 7183 pipe->stream->reconfigure_css_rx = false; 7184 } 7185 7186 IA_CSS_LEAVE_ERR_PRIVATE(err); 7187 return err; 7188} 7189 7190static int 7191sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, 7192 struct ia_css_frame_info *info, 7193 unsigned int idx) 7194{ 7195 assert(pipe); 7196 assert(info); 7197 7198 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7199 "sh_css_pipe_get_output_frame_info() enter:\n"); 7200 7201 *info = pipe->output_info[idx]; 7202 if (copy_on_sp(pipe) && 7203 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { 7204 ia_css_frame_info_init( 7205 info, 7206 JPEG_BYTES, 7207 1, 7208 IA_CSS_FRAME_FORMAT_BINARY_8, 7209 0); 7210 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW || 7211 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) { 7212 info->raw_bit_depth = 7213 ia_css_pipe_util_pipe_input_format_bpp(pipe); 7214 } 7215 7216 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7217 "sh_css_pipe_get_output_frame_info() leave:\n"); 7218 return 0; 7219} 7220 7221void 7222ia_css_stream_send_input_frame(const struct ia_css_stream *stream, 7223 const unsigned short *data, 7224 unsigned int width, 7225 unsigned int height) 7226{ 7227 assert(stream); 7228 7229 ia_css_inputfifo_send_input_frame( 7230 data, width, height, 7231 stream->config.channel_id, 7232 stream->config.input_config.format, 7233 stream->config.pixels_per_clock == 2); 7234} 7235 7236void 7237ia_css_stream_start_input_frame(const struct ia_css_stream *stream) 7238{ 7239 assert(stream); 7240 7241 ia_css_inputfifo_start_frame( 7242 stream->config.channel_id, 7243 stream->config.input_config.format, 7244 stream->config.pixels_per_clock == 2); 7245} 7246 7247void 7248ia_css_stream_send_input_line(const struct ia_css_stream *stream, 7249 const unsigned short *data, 7250 unsigned int width, 7251 const unsigned short *data2, 7252 unsigned int width2) 7253{ 7254 assert(stream); 7255 7256 ia_css_inputfifo_send_line(stream->config.channel_id, 7257 data, width, data2, width2); 7258} 7259 7260void 7261ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream, 7262 enum atomisp_input_format format, 7263 const unsigned short *data, 7264 unsigned int width) 7265{ 7266 assert(stream); 7267 if (!data || width == 0) 7268 return; 7269 ia_css_inputfifo_send_embedded_line(stream->config.channel_id, 7270 format, data, width); 7271} 7272 7273void 7274ia_css_stream_end_input_frame(const struct ia_css_stream *stream) 7275{ 7276 assert(stream); 7277 7278 ia_css_inputfifo_end_frame(stream->config.channel_id); 7279} 7280 7281bool 7282ia_css_pipeline_uses_params(struct ia_css_pipeline *me) 7283{ 7284 struct ia_css_pipeline_stage *stage; 7285 7286 assert(me); 7287 7288 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7289 "ia_css_pipeline_uses_params() enter: me=%p\n", me); 7290 7291 for (stage = me->stages; stage; stage = stage->next) 7292 if (stage->binary_info && stage->binary_info->enable.params) { 7293 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7294 "ia_css_pipeline_uses_params() leave: return_bool=true\n"); 7295 return true; 7296 } 7297 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7298 "ia_css_pipeline_uses_params() leave: return_bool=false\n"); 7299 return false; 7300} 7301 7302/* 7303 * @brief Tag a specific frame in continuous capture. 7304 * Refer to "sh_css_internal.h" for details. 7305 */ 7306int ia_css_stream_capture_frame(struct ia_css_stream *stream, 7307 unsigned int exp_id) 7308{ 7309 struct sh_css_tag_descr tag_descr; 7310 u32 encoded_tag_descr; 7311 int err; 7312 7313 assert(stream); 7314 IA_CSS_ENTER("exp_id=%d", exp_id); 7315 7316 /* Only continuous streams have a tagger */ 7317 if (exp_id == 0 || !stream->config.continuous) { 7318 IA_CSS_LEAVE_ERR(-EINVAL); 7319 return -EINVAL; 7320 } 7321 7322 if (!sh_css_sp_is_running()) { 7323 /* SP is not running. The queues are not valid */ 7324 IA_CSS_LEAVE_ERR(-EBUSY); 7325 return -EBUSY; 7326 } 7327 7328 /* Create the tag descriptor from the parameters */ 7329 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr); 7330 /* Encode the tag descriptor into a 32-bit value */ 7331 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); 7332 /* 7333 * Enqueue the encoded tag to the host2sp queue. 7334 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 7335 * on both host and the SP side. 7336 * It is mainly because it is enough to have only one tag_cmd queue 7337 */ 7338 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr); 7339 7340 IA_CSS_LEAVE_ERR(err); 7341 return err; 7342} 7343 7344/* 7345 * @brief Configure the continuous capture. 7346 * Refer to "sh_css_internal.h" for details. 7347 */ 7348int ia_css_stream_capture(struct ia_css_stream *stream, int num_captures, 7349 unsigned int skip, int offset) 7350{ 7351 struct sh_css_tag_descr tag_descr; 7352 unsigned int encoded_tag_descr; 7353 int return_err; 7354 7355 if (!stream) 7356 return -EINVAL; 7357 7358 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7359 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n", 7360 num_captures, skip, offset); 7361 7362 /* Check if the tag descriptor is valid */ 7363 if (num_captures < SH_CSS_MINIMUM_TAG_ID) { 7364 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7365 "ia_css_stream_capture() leave: return_err=%d\n", 7366 -EINVAL); 7367 return -EINVAL; 7368 } 7369 7370 /* Create the tag descriptor from the parameters */ 7371 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr); 7372 7373 /* Encode the tag descriptor into a 32-bit value */ 7374 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); 7375 7376 if (!sh_css_sp_is_running()) { 7377 /* SP is not running. The queues are not valid */ 7378 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7379 "ia_css_stream_capture() leaving:queues unavailable\n"); 7380 return -EBUSY; 7381 } 7382 7383 /* 7384 * Enqueue the encoded tag to the host2sp queue. 7385 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 7386 * on both host and the SP side. 7387 * It is mainly because it is enough to have only one tag_cmd queue 7388 */ 7389 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr); 7390 7391 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7392 "ia_css_stream_capture() leave: return_err=%d\n", 7393 return_err); 7394 7395 return return_err; 7396} 7397 7398static void 7399sh_css_init_host_sp_control_vars(void) 7400{ 7401 const struct ia_css_fw_info *fw; 7402 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started; 7403 7404 unsigned int HIVE_ADDR_host_sp_queues_initialized; 7405 unsigned int HIVE_ADDR_sp_sleep_mode; 7406 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; 7407 unsigned int HIVE_ADDR_sp_stop_copy_preview; 7408 unsigned int HIVE_ADDR_host_sp_com; 7409 unsigned int o = offsetof(struct host_sp_communication, host2sp_command) 7410 / sizeof(int); 7411 7412 unsigned int i; 7413 7414 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7415 "sh_css_init_host_sp_control_vars() enter: void\n"); 7416 7417 fw = &sh_css_sp_fw; 7418 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started; 7419 7420 HIVE_ADDR_host_sp_queues_initialized = 7421 fw->info.sp.host_sp_queues_initialized; 7422 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode; 7423 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb; 7424 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview; 7425 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; 7426 7427 sp_dmem_store_uint32(SP0_ID, 7428 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started), 7429 (uint32_t)(0)); 7430 7431 sp_dmem_store_uint32(SP0_ID, 7432 (unsigned int)sp_address_of(host_sp_queues_initialized), 7433 (uint32_t)(0)); 7434 sp_dmem_store_uint32(SP0_ID, 7435 (unsigned int)sp_address_of(sp_sleep_mode), 7436 (uint32_t)(0)); 7437 sp_dmem_store_uint32(SP0_ID, 7438 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb), 7439 (uint32_t)(false)); 7440 sp_dmem_store_uint32(SP0_ID, 7441 (unsigned int)sp_address_of(sp_stop_copy_preview), 7442 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0)); 7443 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready); 7444 7445 for (i = 0; i < N_CSI_PORTS; i++) { 7446 sh_css_update_host2sp_num_mipi_frames 7447 (my_css.num_mipi_frames[i]); 7448 } 7449 7450 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 7451 "sh_css_init_host_sp_control_vars() leave: return_void\n"); 7452} 7453 7454/* 7455 * create the internal structures and fill in the configuration data 7456 */ 7457 7458static const struct 7459ia_css_pipe_config ia_css_pipe_default_config = DEFAULT_PIPE_CONFIG; 7460 7461void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config) 7462{ 7463 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n"); 7464 memcpy(pipe_config, &ia_css_pipe_default_config, sizeof(*pipe_config)); 7465} 7466 7467void 7468ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config) 7469{ 7470 if (!extra_config) { 7471 IA_CSS_ERROR("NULL input parameter"); 7472 return; 7473 } 7474 7475 extra_config->enable_raw_binning = false; 7476 extra_config->enable_yuv_ds = false; 7477 extra_config->enable_high_speed = false; 7478 extra_config->enable_dvs_6axis = false; 7479 extra_config->enable_reduced_pipe = false; 7480 extra_config->disable_vf_pp = false; 7481 extra_config->enable_fractional_ds = false; 7482} 7483 7484void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config) 7485{ 7486 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n"); 7487 assert(stream_config); 7488 memset(stream_config, 0, sizeof(*stream_config)); 7489 stream_config->online = true; 7490 stream_config->left_padding = -1; 7491 stream_config->pixels_per_clock = 1; 7492 /* 7493 * temporary default value for backwards compatibility. 7494 * This field used to be hardcoded within CSS but this has now 7495 * been moved to the stream_config struct. 7496 */ 7497 stream_config->source.port.rxcount = 0x04040404; 7498} 7499 7500int ia_css_pipe_create(const struct ia_css_pipe_config *config, 7501 struct ia_css_pipe **pipe) 7502{ 7503 int err = 0; 7504 7505 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe); 7506 7507 if (!config || !pipe) { 7508 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 7509 return -EINVAL; 7510 } 7511 7512 err = ia_css_pipe_create_extra(config, NULL, pipe); 7513 7514 if (err == 0) 7515 IA_CSS_LOG("pipe created successfully = %p", *pipe); 7516 7517 IA_CSS_LEAVE_ERR_PRIVATE(err); 7518 7519 return err; 7520} 7521 7522int 7523ia_css_pipe_create_extra(const struct ia_css_pipe_config *config, 7524 const struct ia_css_pipe_extra_config *extra_config, 7525 struct ia_css_pipe **pipe) 7526{ 7527 int err = -EINVAL; 7528 struct ia_css_pipe *internal_pipe = NULL; 7529 unsigned int i; 7530 7531 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe); 7532 7533 /* do not allow to create more than the maximum limit */ 7534 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) { 7535 IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC); 7536 return -EINVAL; 7537 } 7538 7539 if ((!pipe) || (!config)) { 7540 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); 7541 return -EINVAL; 7542 } 7543 7544 ia_css_debug_dump_pipe_config(config); 7545 ia_css_debug_dump_pipe_extra_config(extra_config); 7546 7547 err = create_pipe(config->mode, &internal_pipe, false); 7548 if (err) { 7549 IA_CSS_LEAVE_ERR_PRIVATE(err); 7550 return err; 7551 } 7552 7553 /* now we have a pipe structure to fill */ 7554 internal_pipe->config = *config; 7555 if (extra_config) 7556 internal_pipe->extra_config = *extra_config; 7557 else 7558 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config); 7559 7560 /* 7561 * Use config value when dvs_frame_delay setting equal to 2, 7562 * otherwise always 1 by default 7563 */ 7564 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2) 7565 internal_pipe->dvs_frame_delay = 2; 7566 else 7567 internal_pipe->dvs_frame_delay = 1; 7568 7569 /* 7570 * we still keep enable_raw_binning for backward compatibility, 7571 * for any new fractional bayer downscaling, we should use 7572 * bayer_ds_out_res. if both are specified, bayer_ds_out_res will 7573 * take precedence.if none is specified, we set bayer_ds_out_res 7574 * equal to IF output resolution(IF may do cropping on sensor output) 7575 * or use default decimation factor 1. 7576 */ 7577 7578 /* YUV downscaling */ 7579 if ((internal_pipe->config.vf_pp_in_res.width || 7580 internal_pipe->config.capt_pp_in_res.width)) { 7581 enum ia_css_frame_format format; 7582 7583 if (internal_pipe->config.vf_pp_in_res.width) { 7584 format = IA_CSS_FRAME_FORMAT_YUV_LINE; 7585 ia_css_frame_info_init( 7586 &internal_pipe->vf_yuv_ds_input_info, 7587 internal_pipe->config.vf_pp_in_res.width, 7588 internal_pipe->config.vf_pp_in_res.height, 7589 format, 0); 7590 } 7591 if (internal_pipe->config.capt_pp_in_res.width) { 7592 format = IA_CSS_FRAME_FORMAT_YUV420; 7593 ia_css_frame_info_init( 7594 &internal_pipe->out_yuv_ds_input_info, 7595 internal_pipe->config.capt_pp_in_res.width, 7596 internal_pipe->config.capt_pp_in_res.height, 7597 format, 0); 7598 } 7599 } 7600 if (internal_pipe->config.vf_pp_in_res.width && 7601 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) { 7602 ia_css_frame_info_init( 7603 &internal_pipe->vf_yuv_ds_input_info, 7604 internal_pipe->config.vf_pp_in_res.width, 7605 internal_pipe->config.vf_pp_in_res.height, 7606 IA_CSS_FRAME_FORMAT_YUV_LINE, 0); 7607 } 7608 /* handle bayer downscaling output info */ 7609 if (internal_pipe->config.bayer_ds_out_res.width) { 7610 ia_css_frame_info_init( 7611 &internal_pipe->bds_output_info, 7612 internal_pipe->config.bayer_ds_out_res.width, 7613 internal_pipe->config.bayer_ds_out_res.height, 7614 IA_CSS_FRAME_FORMAT_RAW, 0); 7615 } 7616 7617 /* handle output info, assume always needed */ 7618 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { 7619 if (internal_pipe->config.output_info[i].res.width) { 7620 err = sh_css_pipe_configure_output( 7621 internal_pipe, 7622 internal_pipe->config.output_info[i].res.width, 7623 internal_pipe->config.output_info[i].res.height, 7624 internal_pipe->config.output_info[i].padded_width, 7625 internal_pipe->config.output_info[i].format, 7626 i); 7627 if (err) { 7628 IA_CSS_LEAVE_ERR_PRIVATE(err); 7629 kvfree(internal_pipe); 7630 internal_pipe = NULL; 7631 return err; 7632 } 7633 } 7634 7635 /* handle vf output info, when configured */ 7636 internal_pipe->enable_viewfinder[i] = 7637 (internal_pipe->config.vf_output_info[i].res.width != 0); 7638 if (internal_pipe->config.vf_output_info[i].res.width) { 7639 err = sh_css_pipe_configure_viewfinder( 7640 internal_pipe, 7641 internal_pipe->config.vf_output_info[i].res.width, 7642 internal_pipe->config.vf_output_info[i].res.height, 7643 internal_pipe->config.vf_output_info[i].padded_width, 7644 internal_pipe->config.vf_output_info[i].format, 7645 i); 7646 if (err) { 7647 IA_CSS_LEAVE_ERR_PRIVATE(err); 7648 kvfree(internal_pipe); 7649 internal_pipe = NULL; 7650 return err; 7651 } 7652 } 7653 } 7654 /* set all info to zeroes first */ 7655 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info)); 7656 7657 /* all went well, return the pipe */ 7658 *pipe = internal_pipe; 7659 IA_CSS_LEAVE_ERR_PRIVATE(0); 7660 return 0; 7661} 7662 7663int 7664ia_css_pipe_get_info(const struct ia_css_pipe *pipe, 7665 struct ia_css_pipe_info *pipe_info) 7666{ 7667 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7668 "ia_css_pipe_get_info()\n"); 7669 if (!pipe_info) { 7670 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 7671 "ia_css_pipe_get_info: pipe_info cannot be NULL\n"); 7672 return -EINVAL; 7673 } 7674 if (!pipe || !pipe->stream) { 7675 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 7676 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n"); 7677 return -EINVAL; 7678 } 7679 /* we succeeded return the info */ 7680 *pipe_info = pipe->info; 7681 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n"); 7682 return 0; 7683} 7684 7685bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info) 7686{ 7687 unsigned int i; 7688 7689 if (pipe_info) { 7690 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) { 7691 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable) 7692 return true; 7693 } 7694 } 7695 7696 return false; 7697} 7698 7699int 7700ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe, 7701 int pin_index, 7702 enum ia_css_frame_format new_format) 7703{ 7704 int err = 0; 7705 7706 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format); 7707 7708 if (!pipe) { 7709 IA_CSS_ERROR("pipe is not set"); 7710 err = -EINVAL; 7711 IA_CSS_LEAVE_ERR_PRIVATE(err); 7712 return err; 7713 } 7714 if (0 != pin_index && 1 != pin_index) { 7715 IA_CSS_ERROR("pin index is not valid"); 7716 err = -EINVAL; 7717 IA_CSS_LEAVE_ERR_PRIVATE(err); 7718 return err; 7719 } 7720 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) { 7721 IA_CSS_ERROR("new format is not valid"); 7722 err = -EINVAL; 7723 IA_CSS_LEAVE_ERR_PRIVATE(err); 7724 return err; 7725 } else { 7726 err = ia_css_pipe_check_format(pipe, new_format); 7727 if (!err) { 7728 if (pin_index == 0) 7729 pipe->output_info[0].format = new_format; 7730 else 7731 pipe->vf_output_info[0].format = new_format; 7732 } 7733 } 7734 IA_CSS_LEAVE_ERR_PRIVATE(err); 7735 return err; 7736} 7737 7738/* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */ 7739static int 7740ia_css_stream_configure_rx(struct ia_css_stream *stream) 7741{ 7742 struct ia_css_input_port *config; 7743 7744 assert(stream); 7745 7746 config = &stream->config.source.port; 7747 /* AM: this code is not reliable, especially for 2400 */ 7748 if (config->num_lanes == 1) 7749 stream->csi_rx_config.mode = MONO_1L_1L_0L; 7750 else if (config->num_lanes == 2) 7751 stream->csi_rx_config.mode = MONO_2L_1L_0L; 7752 else if (config->num_lanes == 3) 7753 stream->csi_rx_config.mode = MONO_3L_1L_0L; 7754 else if (config->num_lanes == 4) 7755 stream->csi_rx_config.mode = MONO_4L_1L_0L; 7756 else if (config->num_lanes != 0) 7757 return -EINVAL; 7758 7759 if (config->port > MIPI_PORT2_ID) 7760 return -EINVAL; 7761 stream->csi_rx_config.port = 7762 ia_css_isys_port_to_mipi_port(config->port); 7763 stream->csi_rx_config.timeout = config->timeout; 7764 stream->csi_rx_config.initcount = 0; 7765 stream->csi_rx_config.synccount = 0x28282828; 7766 stream->csi_rx_config.rxcount = config->rxcount; 7767 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE) 7768 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE; 7769 else 7770 /* 7771 * not implemented yet, requires extension of the rx_cfg_t 7772 * struct 7773 */ 7774 return -EINVAL; 7775 7776 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2); 7777 stream->reconfigure_css_rx = true; 7778 return 0; 7779} 7780 7781static struct ia_css_pipe * 7782find_pipe(struct ia_css_pipe *pipes[], unsigned int num_pipes, 7783 enum ia_css_pipe_mode mode, bool copy_pipe) 7784{ 7785 unsigned int i; 7786 7787 assert(pipes); 7788 for (i = 0; i < num_pipes; i++) { 7789 assert(pipes[i]); 7790 if (pipes[i]->config.mode != mode) 7791 continue; 7792 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY) 7793 continue; 7794 return pipes[i]; 7795 } 7796 return NULL; 7797} 7798 7799static int 7800metadata_info_init(const struct ia_css_metadata_config *mdc, 7801 struct ia_css_metadata_info *md) 7802{ 7803 /* Either both width and height should be set or neither */ 7804 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0)) 7805 return -EINVAL; 7806 7807 md->resolution = mdc->resolution; 7808 /* 7809 * We round up the stride to a multiple of the width 7810 * of the port going to DDR, this is a HW requirements (DMA). 7811 */ 7812 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES); 7813 md->size = mdc->resolution.height * md->stride; 7814 return 0; 7815} 7816 7817int 7818ia_css_stream_create(const struct ia_css_stream_config *stream_config, 7819 int num_pipes, 7820 struct ia_css_pipe *pipes[], 7821 struct ia_css_stream **stream) 7822{ 7823 struct ia_css_pipe *curr_pipe; 7824 struct ia_css_stream *curr_stream = NULL; 7825 bool spcopyonly; 7826 bool sensor_binning_changed; 7827 int i, j; 7828 int err = -EINVAL; 7829 struct ia_css_metadata_info md_info; 7830 struct ia_css_resolution effective_res; 7831 7832 IA_CSS_ENTER("num_pipes=%d", num_pipes); 7833 ia_css_debug_dump_stream_config(stream_config, num_pipes); 7834 7835 /* some checks */ 7836 if (num_pipes == 0 || 7837 !stream || 7838 !pipes) { 7839 err = -EINVAL; 7840 IA_CSS_LEAVE_ERR(err); 7841 return err; 7842 } 7843 7844 if (!IS_ISP2401) { 7845 /* We don't support metadata for JPEG stream, since they both use str2mem */ 7846 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && 7847 stream_config->metadata_config.resolution.height > 0) { 7848 err = -EINVAL; 7849 IA_CSS_LEAVE_ERR(err); 7850 return err; 7851 } 7852 } else { 7853 if (stream_config->online && stream_config->pack_raw_pixels) { 7854 IA_CSS_LOG("online and pack raw is invalid on input system 2401"); 7855 err = -EINVAL; 7856 IA_CSS_LEAVE_ERR(err); 7857 return err; 7858 } 7859 } 7860 7861 ia_css_debug_pipe_graph_dump_stream_config(stream_config); 7862 7863 /* check if mipi size specified */ 7864 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 7865 if (!IS_ISP2401 || !stream_config->online) 7866 { 7867 unsigned int port = (unsigned int)stream_config->source.port.port; 7868 7869 if (port >= N_MIPI_PORT_ID) { 7870 err = -EINVAL; 7871 IA_CSS_LEAVE_ERR(err); 7872 return err; 7873 } 7874 7875 if (my_css.size_mem_words != 0) { 7876 my_css.mipi_frame_size[port] = my_css.size_mem_words; 7877 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) { 7878 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words; 7879 } else { 7880 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7881 "ia_css_stream_create() exit: error, need to set mipi frame size.\n"); 7882 assert(stream_config->mipi_buffer_config.size_mem_words != 0); 7883 err = -EINVAL; 7884 IA_CSS_LEAVE_ERR(err); 7885 return err; 7886 } 7887 7888 if (my_css.size_mem_words != 0) { 7889 my_css.num_mipi_frames[port] = 7890 2; /* Temp change: Default for backwards compatibility. */ 7891 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) { 7892 my_css.num_mipi_frames[port] = 7893 stream_config->mipi_buffer_config.nof_mipi_buffers; 7894 } else { 7895 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 7896 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n"); 7897 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0); 7898 err = -EINVAL; 7899 IA_CSS_LEAVE_ERR(err); 7900 return err; 7901 } 7902 } 7903 7904 /* Currently we only supported metadata up to a certain size. */ 7905 err = metadata_info_init(&stream_config->metadata_config, &md_info); 7906 if (err) { 7907 IA_CSS_LEAVE_ERR(err); 7908 return err; 7909 } 7910 7911 /* allocate the stream instance */ 7912 curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL); 7913 if (!curr_stream) { 7914 err = -ENOMEM; 7915 IA_CSS_LEAVE_ERR(err); 7916 return err; 7917 } 7918 /* default all to 0 */ 7919 curr_stream->info.metadata_info = md_info; 7920 7921 /* allocate pipes */ 7922 curr_stream->num_pipes = num_pipes; 7923 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL); 7924 if (!curr_stream->pipes) { 7925 curr_stream->num_pipes = 0; 7926 kfree(curr_stream); 7927 curr_stream = NULL; 7928 err = -ENOMEM; 7929 IA_CSS_LEAVE_ERR(err); 7930 return err; 7931 } 7932 /* store pipes */ 7933 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY); 7934 for (i = 0; i < num_pipes; i++) 7935 curr_stream->pipes[i] = pipes[i]; 7936 curr_stream->last_pipe = curr_stream->pipes[0]; 7937 /* take over stream config */ 7938 curr_stream->config = *stream_config; 7939 7940 if (IS_ISP2401) { 7941 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR && 7942 stream_config->online) 7943 curr_stream->config.online = false; 7944 7945 if (curr_stream->config.online) { 7946 curr_stream->config.source.port.num_lanes = 7947 stream_config->source.port.num_lanes; 7948 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; 7949 } 7950 } 7951 /* in case driver doesn't configure init number of raw buffers, configure it here */ 7952 if (curr_stream->config.target_num_cont_raw_buf == 0) 7953 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES; 7954 if (curr_stream->config.init_num_cont_raw_buf == 0) 7955 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf; 7956 7957 /* Enable locking & unlocking of buffers in RAW buffer pool */ 7958 if (curr_stream->config.ia_css_enable_raw_buffer_locking) 7959 sh_css_sp_configure_enable_raw_pool_locking( 7960 curr_stream->config.lock_all); 7961 7962 /* copy mode specific stuff */ 7963 switch (curr_stream->config.mode) { 7964 case IA_CSS_INPUT_MODE_SENSOR: 7965 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: 7966 if (!IS_ISP2401) 7967 ia_css_stream_configure_rx(curr_stream); 7968 break; 7969 case IA_CSS_INPUT_MODE_PRBS: 7970 if (!IS_ISP2401) { 7971 IA_CSS_LOG("mode prbs"); 7972 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed); 7973 } 7974 break; 7975 case IA_CSS_INPUT_MODE_MEMORY: 7976 IA_CSS_LOG("mode memory"); 7977 curr_stream->reconfigure_css_rx = false; 7978 break; 7979 default: 7980 IA_CSS_LOG("mode sensor/default"); 7981 } 7982 7983 for (i = 0; i < num_pipes; i++) { 7984 struct ia_css_resolution effective_res; 7985 7986 curr_pipe = pipes[i]; 7987 /* set current stream */ 7988 curr_pipe->stream = curr_stream; 7989 /* take over effective info */ 7990 7991 effective_res = curr_pipe->config.input_effective_res; 7992 if (effective_res.height == 0 || effective_res.width == 0) { 7993 effective_res = curr_pipe->stream->config.input_config.effective_res; 7994 7995 curr_pipe->config.input_effective_res = effective_res; 7996 } 7997 IA_CSS_LOG("effective_res=%dx%d", 7998 effective_res.width, 7999 effective_res.height); 8000 } 8001 8002 err = ia_css_stream_isp_parameters_init(curr_stream); 8003 if (err) 8004 goto ERR; 8005 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs); 8006 8007 /* sensor binning */ 8008 if (!spcopyonly) { 8009 sensor_binning_changed = 8010 sh_css_params_set_binning_factor(curr_stream, 8011 curr_stream->config.sensor_binning_factor); 8012 } else { 8013 sensor_binning_changed = false; 8014 } 8015 8016 IA_CSS_LOG("sensor_binning=%d, changed=%d", 8017 curr_stream->config.sensor_binning_factor, sensor_binning_changed); 8018 /* loop over pipes */ 8019 IA_CSS_LOG("num_pipes=%d", num_pipes); 8020 curr_stream->cont_capt = false; 8021 /* Temporary hack: we give the preview pipe a reference to the capture 8022 * pipe in continuous capture mode. */ 8023 if (curr_stream->config.continuous) { 8024 /* Search for the preview pipe and create the copy pipe */ 8025 struct ia_css_pipe *preview_pipe; 8026 struct ia_css_pipe *video_pipe; 8027 struct ia_css_pipe *capture_pipe = NULL; 8028 struct ia_css_pipe *copy_pipe = NULL; 8029 8030 if (num_pipes >= 2) { 8031 curr_stream->cont_capt = true; 8032 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder; 8033 curr_stream->stop_copy_preview = my_css.stop_copy_preview; 8034 } 8035 8036 /* Create copy pipe here, since it may not be exposed to the driver */ 8037 preview_pipe = find_pipe(pipes, num_pipes, 8038 IA_CSS_PIPE_MODE_PREVIEW, false); 8039 video_pipe = find_pipe(pipes, num_pipes, 8040 IA_CSS_PIPE_MODE_VIDEO, false); 8041 8042 if (curr_stream->cont_capt) { 8043 capture_pipe = find_pipe(pipes, num_pipes, 8044 IA_CSS_PIPE_MODE_CAPTURE, 8045 false); 8046 if (!capture_pipe) { 8047 err = -EINVAL; 8048 goto ERR; 8049 } 8050 } 8051 /* We do not support preview and video pipe at the same time */ 8052 if (preview_pipe && video_pipe) { 8053 err = -EINVAL; 8054 goto ERR; 8055 } 8056 8057 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) { 8058 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); 8059 if (err) 8060 goto ERR; 8061 ia_css_pipe_config_defaults(©_pipe->config); 8062 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe; 8063 copy_pipe->stream = curr_stream; 8064 } 8065 if (preview_pipe && curr_stream->cont_capt) 8066 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe; 8067 8068 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) { 8069 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); 8070 if (err) 8071 goto ERR; 8072 ia_css_pipe_config_defaults(©_pipe->config); 8073 video_pipe->pipe_settings.video.copy_pipe = copy_pipe; 8074 copy_pipe->stream = curr_stream; 8075 } 8076 if (video_pipe && curr_stream->cont_capt) 8077 video_pipe->pipe_settings.video.capture_pipe = capture_pipe; 8078 } 8079 for (i = 0; i < num_pipes; i++) { 8080 curr_pipe = pipes[i]; 8081 /* set current stream */ 8082 curr_pipe->stream = curr_stream; 8083 8084 /* take over effective info */ 8085 8086 effective_res = curr_pipe->config.input_effective_res; 8087 err = ia_css_util_check_res( 8088 effective_res.width, 8089 effective_res.height); 8090 if (err) 8091 goto ERR; 8092 8093 /* sensor binning per pipe */ 8094 if (sensor_binning_changed) 8095 sh_css_pipe_free_shading_table(curr_pipe); 8096 } 8097 8098 /* now pipes have been configured, info should be available */ 8099 for (i = 0; i < num_pipes; i++) { 8100 struct ia_css_pipe_info *pipe_info = NULL; 8101 8102 curr_pipe = pipes[i]; 8103 8104 err = sh_css_pipe_load_binaries(curr_pipe); 8105 if (err) 8106 goto ERR; 8107 8108 /* handle each pipe */ 8109 pipe_info = &curr_pipe->info; 8110 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { 8111 err = sh_css_pipe_get_output_frame_info(curr_pipe, 8112 &pipe_info->output_info[j], j); 8113 if (err) 8114 goto ERR; 8115 } 8116 8117 if (!spcopyonly) { 8118 if (!IS_ISP2401) 8119 err = sh_css_pipe_get_shading_info(curr_pipe, 8120 &pipe_info->shading_info, 8121 NULL); 8122 else 8123 err = sh_css_pipe_get_shading_info(curr_pipe, 8124 &pipe_info->shading_info, 8125 &curr_pipe->config); 8126 8127 if (err) 8128 goto ERR; 8129 err = sh_css_pipe_get_grid_info(curr_pipe, 8130 &pipe_info->grid_info); 8131 if (err) 8132 goto ERR; 8133 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { 8134 sh_css_pipe_get_viewfinder_frame_info(curr_pipe, 8135 &pipe_info->vf_output_info[j], 8136 j); 8137 if (err) 8138 goto ERR; 8139 } 8140 } 8141 8142 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe; 8143 } 8144 8145 curr_stream->started = false; 8146 8147 /* Map SP threads before doing anything. */ 8148 err = map_sp_threads(curr_stream, true); 8149 if (err) { 8150 IA_CSS_LOG("map_sp_threads: return_err=%d", err); 8151 goto ERR; 8152 } 8153 8154 for (i = 0; i < num_pipes; i++) { 8155 curr_pipe = pipes[i]; 8156 ia_css_pipe_map_queue(curr_pipe, true); 8157 } 8158 8159 /* Create host side pipeline objects without stages */ 8160 err = create_host_pipeline_structure(curr_stream); 8161 if (err) { 8162 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err); 8163 goto ERR; 8164 } 8165 8166 /* assign curr_stream */ 8167 *stream = curr_stream; 8168 8169ERR: 8170 if (!err) { 8171 /* working mode: enter into the seed list */ 8172 if (my_css_save.mode == sh_css_mode_working) { 8173 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { 8174 if (!my_css_save.stream_seeds[i].stream) { 8175 IA_CSS_LOG("entered stream into loc=%d", i); 8176 my_css_save.stream_seeds[i].orig_stream = stream; 8177 my_css_save.stream_seeds[i].stream = curr_stream; 8178 my_css_save.stream_seeds[i].num_pipes = num_pipes; 8179 my_css_save.stream_seeds[i].stream_config = *stream_config; 8180 for (j = 0; j < num_pipes; j++) { 8181 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config; 8182 my_css_save.stream_seeds[i].pipes[j] = pipes[j]; 8183 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j]; 8184 } 8185 break; 8186 } 8187 } 8188 } else { 8189 ia_css_stream_destroy(curr_stream); 8190 } 8191 } else { 8192 ia_css_stream_destroy(curr_stream); 8193 } 8194 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode); 8195 return err; 8196} 8197 8198int 8199ia_css_stream_destroy(struct ia_css_stream *stream) 8200{ 8201 int i; 8202 int err = 0; 8203 8204 IA_CSS_ENTER_PRIVATE("stream = %p", stream); 8205 if (!stream) { 8206 err = -EINVAL; 8207 IA_CSS_LEAVE_ERR_PRIVATE(err); 8208 return err; 8209 } 8210 8211 ia_css_stream_isp_parameters_uninit(stream); 8212 8213 if ((stream->last_pipe) && 8214 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) { 8215 if (IS_ISP2401) { 8216 for (i = 0; i < stream->num_pipes; i++) { 8217 struct ia_css_pipe *entry = stream->pipes[i]; 8218 unsigned int sp_thread_id; 8219 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal; 8220 8221 assert(entry); 8222 if (entry) { 8223 /* get the SP thread id */ 8224 if (!ia_css_pipeline_get_sp_thread_id( 8225 ia_css_pipe_get_pipe_num(entry), &sp_thread_id)) 8226 return -EINVAL; 8227 8228 /* get the target input terminal */ 8229 sp_pipeline_input_terminal = 8230 &sh_css_sp_group.pipe_io[sp_thread_id].input; 8231 8232 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) { 8233 ia_css_isys_stream_h isys_stream = 8234 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]; 8235 if (stream->config.isys_config[i].valid && isys_stream->valid) 8236 ia_css_isys_stream_destroy(isys_stream); 8237 } 8238 } 8239 } 8240 8241 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { 8242 for (i = 0; i < stream->num_pipes; i++) { 8243 struct ia_css_pipe *entry = stream->pipes[i]; 8244 /* 8245 * free any mipi frames that are remaining: 8246 * some test stream create-destroy cycles do 8247 * not generate output frames 8248 * and the mipi buffer is not freed in the 8249 * deque function 8250 */ 8251 if (entry) 8252 free_mipi_frames(entry); 8253 } 8254 } 8255 stream_unregister_with_csi_rx(stream); 8256 } 8257 8258 for (i = 0; i < stream->num_pipes; i++) { 8259 struct ia_css_pipe *curr_pipe = stream->pipes[i]; 8260 8261 assert(curr_pipe); 8262 ia_css_pipe_map_queue(curr_pipe, false); 8263 } 8264 8265 err = map_sp_threads(stream, false); 8266 if (err) { 8267 IA_CSS_LEAVE_ERR_PRIVATE(err); 8268 return err; 8269 } 8270 } 8271 8272 /* remove references from pipes to stream */ 8273 for (i = 0; i < stream->num_pipes; i++) { 8274 struct ia_css_pipe *entry = stream->pipes[i]; 8275 8276 assert(entry); 8277 if (entry) { 8278 /* clear reference to stream */ 8279 entry->stream = NULL; 8280 /* check internal copy pipe */ 8281 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW && 8282 entry->pipe_settings.preview.copy_pipe) { 8283 IA_CSS_LOG("clearing stream on internal preview copy pipe"); 8284 entry->pipe_settings.preview.copy_pipe->stream = NULL; 8285 } 8286 if (entry->mode == IA_CSS_PIPE_ID_VIDEO && 8287 entry->pipe_settings.video.copy_pipe) { 8288 IA_CSS_LOG("clearing stream on internal video copy pipe"); 8289 entry->pipe_settings.video.copy_pipe->stream = NULL; 8290 } 8291 err = sh_css_pipe_unload_binaries(entry); 8292 } 8293 } 8294 /* free associated memory of stream struct */ 8295 kfree(stream->pipes); 8296 stream->pipes = NULL; 8297 stream->num_pipes = 0; 8298 8299 /* working mode: take out of the seed list */ 8300 if (my_css_save.mode == sh_css_mode_working) { 8301 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { 8302 if (my_css_save.stream_seeds[i].stream == stream) { 8303 IA_CSS_LOG("took out stream %d", i); 8304 my_css_save.stream_seeds[i].stream = NULL; 8305 break; 8306 } 8307 } 8308 } 8309 8310 kfree(stream); 8311 IA_CSS_LEAVE_ERR(err); 8312 8313 return err; 8314} 8315 8316int 8317ia_css_stream_get_info(const struct ia_css_stream *stream, 8318 struct ia_css_stream_info *stream_info) 8319{ 8320 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n"); 8321 assert(stream); 8322 assert(stream_info); 8323 8324 *stream_info = stream->info; 8325 return 0; 8326} 8327 8328int 8329ia_css_stream_start(struct ia_css_stream *stream) 8330{ 8331 int err = 0; 8332 8333 IA_CSS_ENTER("stream = %p", stream); 8334 if ((!stream) || (!stream->last_pipe)) { 8335 IA_CSS_LEAVE_ERR(-EINVAL); 8336 return -EINVAL; 8337 } 8338 IA_CSS_LOG("starting %d", stream->last_pipe->mode); 8339 8340 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf); 8341 8342 /* Create host side pipeline. */ 8343 err = create_host_pipeline(stream); 8344 if (err) { 8345 IA_CSS_LEAVE_ERR(err); 8346 return err; 8347 } 8348 8349 if (IS_ISP2401 && 8350 ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) || 8351 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))) 8352 stream_register_with_csi_rx(stream); 8353 8354 /* Initialize mipi size checks */ 8355 if (!IS_ISP2401 && stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { 8356 unsigned int idx; 8357 unsigned int port = (unsigned int)(stream->config.source.port.port); 8358 8359 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) { 8360 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 8361 sh_css_get_mipi_sizes_for_check(port, idx); 8362 } 8363 } 8364 8365 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) { 8366 if (IS_ISP2401) 8367 err = sh_css_config_input_network_2401(stream); 8368 else 8369 err = sh_css_config_input_network_2400(stream); 8370 if (err) 8371 return err; 8372 } 8373 8374 err = sh_css_pipe_start(stream); 8375 IA_CSS_LEAVE_ERR(err); 8376 return err; 8377} 8378 8379int 8380ia_css_stream_stop(struct ia_css_stream *stream) 8381{ 8382 int err = 0; 8383 8384 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n"); 8385 assert(stream); 8386 assert(stream->last_pipe); 8387 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n", 8388 stream->last_pipe->mode); 8389 8390 /* De-initialize mipi size checks */ 8391 if (!IS_ISP2401 && stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { 8392 unsigned int idx; 8393 unsigned int port = (unsigned int)(stream->config.source.port.port); 8394 8395 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) 8396 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0; 8397 } 8398 8399 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline); 8400 if (err) 8401 return err; 8402 8403 /* 8404 * Ideally, unmapping should happen after pipeline_stop, but current 8405 * semantics do not allow that. 8406 */ 8407 /* err = map_sp_threads(stream, false); */ 8408 8409 return err; 8410} 8411 8412bool 8413ia_css_stream_has_stopped(struct ia_css_stream *stream) 8414{ 8415 bool stopped; 8416 8417 assert(stream); 8418 8419 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline); 8420 8421 return stopped; 8422} 8423 8424/* ISP2400 */ 8425/* 8426 * Destroy the stream and all the pipes related to it. 8427 * The stream handle is used to identify the correct entry in the css_save struct 8428 */ 8429int 8430ia_css_stream_unload(struct ia_css_stream *stream) 8431{ 8432 int i; 8433 8434 assert(stream); 8435 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n"); 8436 /* some checks */ 8437 assert(stream); 8438 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) 8439 if (my_css_save.stream_seeds[i].stream == stream) { 8440 int j; 8441 8442 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8443 "ia_css_stream_unload(): unloading %d (%p)\n", i, 8444 my_css_save.stream_seeds[i].stream); 8445 ia_css_stream_destroy(stream); 8446 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) 8447 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]); 8448 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 8449 "ia_css_stream_unload(): after unloading %d (%p)\n", i, 8450 my_css_save.stream_seeds[i].stream); 8451 break; 8452 } 8453 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n"); 8454 return 0; 8455} 8456 8457int 8458ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, 8459 enum ia_css_pipe_id *pipe_id) 8460{ 8461 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n"); 8462 if (pipe) 8463 *pipe_id = pipe->mode; 8464 else 8465 *pipe_id = IA_CSS_PIPE_ID_COPY; 8466 8467 return 0; 8468} 8469 8470enum atomisp_input_format 8471ia_css_stream_get_format(const struct ia_css_stream *stream) 8472{ 8473 return stream->config.input_config.format; 8474} 8475 8476bool 8477ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) 8478{ 8479 return (stream->config.pixels_per_clock == 2); 8480} 8481 8482struct ia_css_binary * 8483ia_css_stream_get_shading_correction_binary(const struct ia_css_stream 8484 *stream) 8485{ 8486 struct ia_css_pipe *pipe; 8487 8488 assert(stream); 8489 8490 pipe = stream->pipes[0]; 8491 8492 if (stream->num_pipes == 2) { 8493 assert(stream->pipes[1]); 8494 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO || 8495 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 8496 pipe = stream->pipes[1]; 8497 } 8498 8499 return ia_css_pipe_get_shading_correction_binary(pipe); 8500} 8501 8502struct ia_css_binary * 8503ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) 8504{ 8505 int i; 8506 struct ia_css_pipe *video_pipe = NULL; 8507 8508 /* First we find the video pipe */ 8509 for (i = 0; i < stream->num_pipes; i++) { 8510 struct ia_css_pipe *pipe = stream->pipes[i]; 8511 8512 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) { 8513 video_pipe = pipe; 8514 break; 8515 } 8516 } 8517 if (video_pipe) 8518 return &video_pipe->pipe_settings.video.video_binary; 8519 return NULL; 8520} 8521 8522struct ia_css_binary * 8523ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) 8524{ 8525 struct ia_css_pipe *pipe; 8526 struct ia_css_binary *s3a_binary = NULL; 8527 8528 assert(stream); 8529 8530 pipe = stream->pipes[0]; 8531 8532 if (stream->num_pipes == 2) { 8533 assert(stream->pipes[1]); 8534 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO || 8535 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW) 8536 pipe = stream->pipes[1]; 8537 } 8538 8539 s3a_binary = ia_css_pipe_get_s3a_binary(pipe); 8540 8541 return s3a_binary; 8542} 8543 8544int 8545ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, 8546 unsigned int output_padded_width) 8547{ 8548 struct ia_css_pipe *pipe; 8549 8550 assert(stream); 8551 8552 pipe = stream->last_pipe; 8553 8554 assert(pipe); 8555 8556 /* set the config also just in case (redundant info? why do we save config in pipe?) */ 8557 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width; 8558 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width; 8559 8560 return 0; 8561} 8562 8563static struct ia_css_binary * 8564ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) 8565{ 8566 struct ia_css_binary *binary = NULL; 8567 8568 assert(pipe); 8569 8570 switch (pipe->config.mode) { 8571 case IA_CSS_PIPE_MODE_PREVIEW: 8572 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary; 8573 break; 8574 case IA_CSS_PIPE_MODE_VIDEO: 8575 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 8576 break; 8577 case IA_CSS_PIPE_MODE_CAPTURE: 8578 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 8579 unsigned int i; 8580 8581 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 8582 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) { 8583 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i]; 8584 break; 8585 } 8586 } 8587 } else if (pipe->config.default_capture_config.mode == 8588 IA_CSS_CAPTURE_MODE_BAYER) 8589 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 8590 else if (pipe->config.default_capture_config.mode == 8591 IA_CSS_CAPTURE_MODE_ADVANCED || 8592 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { 8593 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) 8594 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 8595 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2) 8596 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary; 8597 } 8598 break; 8599 default: 8600 break; 8601 } 8602 8603 if (binary && binary->info->sp.enable.sc) 8604 return binary; 8605 8606 return NULL; 8607} 8608 8609static struct ia_css_binary * 8610ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) 8611{ 8612 struct ia_css_binary *binary = NULL; 8613 8614 assert(pipe); 8615 8616 switch (pipe->config.mode) { 8617 case IA_CSS_PIPE_MODE_PREVIEW: 8618 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary; 8619 break; 8620 case IA_CSS_PIPE_MODE_VIDEO: 8621 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 8622 break; 8623 case IA_CSS_PIPE_MODE_CAPTURE: 8624 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 8625 unsigned int i; 8626 8627 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 8628 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) { 8629 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i]; 8630 break; 8631 } 8632 } 8633 } else if (pipe->config.default_capture_config.mode == 8634 IA_CSS_CAPTURE_MODE_BAYER) { 8635 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 8636 } else if (pipe->config.default_capture_config.mode == 8637 IA_CSS_CAPTURE_MODE_ADVANCED || 8638 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { 8639 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) 8640 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; 8641 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2) 8642 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary; 8643 else 8644 assert(0); 8645 } 8646 break; 8647 default: 8648 break; 8649 } 8650 8651 if (binary && !binary->info->sp.enable.s3a) 8652 binary = NULL; 8653 8654 return binary; 8655} 8656 8657static struct ia_css_binary * 8658ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) 8659{ 8660 struct ia_css_binary *binary = NULL; 8661 8662 assert(pipe); 8663 8664 switch (pipe->config.mode) { 8665 case IA_CSS_PIPE_MODE_VIDEO: 8666 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; 8667 break; 8668 default: 8669 break; 8670 } 8671 8672 if (binary && !binary->info->sp.enable.dis) 8673 binary = NULL; 8674 8675 return binary; 8676} 8677 8678struct ia_css_pipeline * 8679ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) 8680{ 8681 assert(pipe); 8682 8683 return (struct ia_css_pipeline *)&pipe->pipeline; 8684} 8685 8686unsigned int 8687ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) 8688{ 8689 assert(pipe); 8690 8691 /* 8692 * KW was not sure this function was not returning a value 8693 * that was out of range; so added an assert, and, for the 8694 * case when asserts are not enabled, clip to the largest 8695 * value; pipe_num is unsigned so the value cannot be too small 8696 */ 8697 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX); 8698 8699 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX) 8700 return (IA_CSS_PIPELINE_NUM_MAX - 1); 8701 8702 return pipe->pipe_num; 8703} 8704 8705unsigned int 8706ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) 8707{ 8708 assert(pipe); 8709 8710 return (unsigned int)pipe->config.isp_pipe_version; 8711} 8712 8713#define SP_START_TIMEOUT_US 30000000 8714 8715int 8716ia_css_start_sp(void) 8717{ 8718 unsigned long timeout; 8719 int err = 0; 8720 8721 IA_CSS_ENTER(""); 8722 sh_css_sp_start_isp(); 8723 8724 /* waiting for the SP is completely started */ 8725 timeout = SP_START_TIMEOUT_US; 8726 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) { 8727 timeout--; 8728 udelay(1); 8729 } 8730 if (timeout == 0) { 8731 IA_CSS_ERROR("timeout during SP initialization"); 8732 return -EINVAL; 8733 } 8734 8735 /* Workaround, in order to run two streams in parallel. See TASK 4271*/ 8736 /* TODO: Fix this. */ 8737 8738 sh_css_init_host_sp_control_vars(); 8739 8740 /* buffers should be initialized only when sp is started */ 8741 /* AM: At the moment it will be done only when there is no stream active. */ 8742 8743 sh_css_setup_queues(); 8744 ia_css_bufq_dump_queue_info(); 8745 8746 IA_CSS_LEAVE_ERR(err); 8747 return err; 8748} 8749 8750/* 8751 * Time to wait SP for termincate. Only condition when this can happen 8752 * is a fatal hw failure, but we must be able to detect this and emit 8753 * a proper error trace. 8754 */ 8755#define SP_SHUTDOWN_TIMEOUT_US 200000 8756 8757int 8758ia_css_stop_sp(void) 8759{ 8760 unsigned long timeout; 8761 int err = 0; 8762 8763 IA_CSS_ENTER("void"); 8764 8765 if (!sh_css_sp_is_running()) { 8766 err = -EINVAL; 8767 IA_CSS_LEAVE("SP already stopped : return_err=%d", err); 8768 8769 /* Return an error - stop SP should not have been called by driver */ 8770 return err; 8771 } 8772 8773 /* For now, stop whole SP */ 8774 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) { 8775 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); 8776 ia_css_debug_dump_sp_sw_debug_info(); 8777 } 8778 8779 sh_css_sp_set_sp_running(false); 8780 8781 timeout = SP_SHUTDOWN_TIMEOUT_US; 8782 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) { 8783 timeout--; 8784 udelay(1); 8785 } 8786 if (ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED) 8787 IA_CSS_WARNING("SP has not terminated (SW)"); 8788 8789 if (timeout == 0) { 8790 IA_CSS_WARNING("SP is not idle"); 8791 ia_css_debug_dump_sp_sw_debug_info(); 8792 } 8793 timeout = SP_SHUTDOWN_TIMEOUT_US; 8794 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) { 8795 timeout--; 8796 udelay(1); 8797 } 8798 if (timeout == 0) { 8799 IA_CSS_WARNING("ISP is not idle"); 8800 ia_css_debug_dump_sp_sw_debug_info(); 8801 } 8802 8803 sh_css_hmm_buffer_record_uninit(); 8804 8805 /* clear pending param sets from refcount */ 8806 sh_css_param_clear_param_sets(); 8807 8808 IA_CSS_LEAVE_ERR(err); 8809 return err; 8810} 8811 8812int 8813ia_css_update_continuous_frames(struct ia_css_stream *stream) 8814{ 8815 struct ia_css_pipe *pipe; 8816 unsigned int i; 8817 8818 ia_css_debug_dtrace( 8819 IA_CSS_DEBUG_TRACE, 8820 "sh_css_update_continuous_frames() enter:\n"); 8821 8822 if (!stream) { 8823 ia_css_debug_dtrace( 8824 IA_CSS_DEBUG_TRACE, 8825 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n"); 8826 return -EINVAL; 8827 } 8828 8829 pipe = stream->continuous_pipe; 8830 8831 for (i = stream->config.init_num_cont_raw_buf; 8832 i < stream->config.target_num_cont_raw_buf; i++) 8833 sh_css_update_host2sp_offline_frame(i, 8834 pipe->continuous_frames[i], pipe->cont_md_buffers[i]); 8835 8836 sh_css_update_host2sp_cont_num_raw_frames 8837 (stream->config.target_num_cont_raw_buf, true); 8838 ia_css_debug_dtrace( 8839 IA_CSS_DEBUG_TRACE, 8840 "sh_css_update_continuous_frames() leave: return_void\n"); 8841 8842 return 0; 8843} 8844 8845void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) 8846{ 8847 unsigned int thread_id; 8848 unsigned int pipe_num; 8849 bool need_input_queue; 8850 8851 IA_CSS_ENTER(""); 8852 assert(pipe); 8853 8854 pipe_num = pipe->pipe_num; 8855 8856 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 8857 8858 if (IS_ISP2401) 8859 need_input_queue = true; 8860 else 8861 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; 8862 8863 /* map required buffer queues to resources */ 8864 /* TODO: to be improved */ 8865 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) { 8866 if (need_input_queue) 8867 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 8868 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 8869 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 8870 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 8871 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 8872 if (pipe->pipe_settings.preview.preview_binary.info && 8873 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a) 8874 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 8875 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) { 8876 unsigned int i; 8877 8878 if (need_input_queue) 8879 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 8880 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 8881 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); 8882 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 8883 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 8884 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 8885 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { 8886 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { 8887 if (pipe->pipe_settings.capture.primary_binary[i].info && 8888 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) { 8889 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 8890 break; 8891 } 8892 } 8893 } else if (pipe->config.default_capture_config.mode == 8894 IA_CSS_CAPTURE_MODE_ADVANCED || 8895 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT || 8896 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) { 8897 if (pipe->pipe_settings.capture.pre_isp_binary.info && 8898 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a) 8899 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 8900 } 8901 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) { 8902 if (need_input_queue) 8903 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 8904 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 8905 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) 8906 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); 8907 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 8908 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); 8909 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 8910 if (pipe->pipe_settings.video.video_binary.info && 8911 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a) 8912 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); 8913 if (pipe->pipe_settings.video.video_binary.info && 8914 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis 8915 )) 8916 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map); 8917 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) { 8918 if (need_input_queue) 8919 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 8920 if (!pipe->stream->config.continuous) 8921 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); 8922 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 8923 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) { 8924 unsigned int idx; 8925 8926 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) { 8927 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map); 8928 if (pipe->enable_viewfinder[idx]) 8929 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map); 8930 } 8931 if (need_input_queue) 8932 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); 8933 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); 8934 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); 8935 } 8936 IA_CSS_LEAVE(""); 8937} 8938 8939 8940int 8941ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) 8942{ 8943 int ret; 8944 8945 IA_CSS_ENTER(""); 8946 8947 /* 8948 * Only continuous streams have a tagger to which we can send the 8949 * unlock message. 8950 */ 8951 if (!stream || !stream->config.continuous) { 8952 IA_CSS_ERROR("invalid stream pointer"); 8953 return -EINVAL; 8954 } 8955 8956 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID || 8957 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) { 8958 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id); 8959 return -EINVAL; 8960 } 8961 8962 /* 8963 * Send the event. Since we verified that the exp_id is valid, 8964 * we can safely assign it to an 8-bit argument here. 8965 */ 8966 ret = ia_css_bufq_enqueue_psys_event( 8967 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0); 8968 8969 IA_CSS_LEAVE_ERR(ret); 8970 return ret; 8971} 8972 8973static void 8974sh_css_hmm_buffer_record_init(void) 8975{ 8976 int i; 8977 8978 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) 8979 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]); 8980} 8981 8982static void 8983sh_css_hmm_buffer_record_uninit(void) 8984{ 8985 int i; 8986 struct sh_css_hmm_buffer_record *buffer_record = NULL; 8987 8988 buffer_record = &hmm_buffer_record[0]; 8989 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 8990 if (buffer_record->in_use) { 8991 if (buffer_record->h_vbuf) 8992 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf); 8993 sh_css_hmm_buffer_record_reset(buffer_record); 8994 } 8995 buffer_record++; 8996 } 8997} 8998 8999static void 9000sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) 9001{ 9002 assert(buffer_record); 9003 buffer_record->in_use = false; 9004 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID; 9005 buffer_record->h_vbuf = NULL; 9006 buffer_record->kernel_ptr = 0; 9007} 9008 9009static struct sh_css_hmm_buffer_record 9010*sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf, 9011 enum ia_css_buffer_type type, 9012 hrt_address kernel_ptr) 9013{ 9014 int i; 9015 struct sh_css_hmm_buffer_record *buffer_record = NULL; 9016 struct sh_css_hmm_buffer_record *out_buffer_record = NULL; 9017 9018 assert(h_vbuf); 9019 assert((type > IA_CSS_BUFFER_TYPE_INVALID) && 9020 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE)); 9021 assert(kernel_ptr != 0); 9022 9023 buffer_record = &hmm_buffer_record[0]; 9024 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 9025 if (!buffer_record->in_use) { 9026 buffer_record->in_use = true; 9027 buffer_record->type = type; 9028 buffer_record->h_vbuf = h_vbuf; 9029 buffer_record->kernel_ptr = kernel_ptr; 9030 out_buffer_record = buffer_record; 9031 break; 9032 } 9033 buffer_record++; 9034 } 9035 9036 return out_buffer_record; 9037} 9038 9039static struct sh_css_hmm_buffer_record 9040*sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr, 9041 enum ia_css_buffer_type type) 9042{ 9043 int i; 9044 struct sh_css_hmm_buffer_record *buffer_record = NULL; 9045 bool found_record = false; 9046 9047 buffer_record = &hmm_buffer_record[0]; 9048 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { 9049 if ((buffer_record->in_use) && 9050 (buffer_record->type == type) && 9051 (buffer_record->h_vbuf) && 9052 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) { 9053 found_record = true; 9054 break; 9055 } 9056 buffer_record++; 9057 } 9058 9059 if (found_record) 9060 return buffer_record; 9061 else 9062 return NULL; 9063}
~/
Read-only file preview.