diff options
Diffstat (limited to 'drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c')
-rw-r--r-- | drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c | 11094 |
1 files changed, 0 insertions, 11094 deletions
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c deleted file mode 100644 index 4bcc835..0000000 --- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c +++ /dev/null @@ -1,11094 +0,0 @@ -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/*! \file */ -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> - -#include "ia_css.h" -#include "sh_css_hrt.h" /* only for file 2 MIPI */ -#include "ia_css_buffer.h" -#include "ia_css_binary.h" -#include "sh_css_internal.h" -#include "sh_css_mipi.h" -#include "sh_css_sp.h" /* sh_css_sp_group */ -#if !defined(HAS_NO_INPUT_SYSTEM) -#include "ia_css_isys.h" -#endif -#include "ia_css_frame.h" -#include "sh_css_defs.h" -#include "sh_css_firmware.h" -#include "sh_css_params.h" -#include "sh_css_params_internal.h" -#include "sh_css_param_shading.h" -#include "ia_css_refcount.h" -#include "ia_css_rmgr.h" -#include "ia_css_debug.h" -#include "ia_css_debug_pipe.h" -#include "ia_css_device_access.h" -#include "device_access.h" -#include "sh_css_legacy.h" -#include "ia_css_pipeline.h" -#include "ia_css_stream.h" -#include "sh_css_stream_format.h" -#include "ia_css_pipe.h" -#include "ia_css_util.h" -#include "ia_css_pipe_util.h" -#include "ia_css_pipe_binarydesc.h" -#include "ia_css_pipe_stagedesc.h" -#ifdef USE_INPUT_SYSTEM_VERSION_2 -#include "ia_css_isys.h" -#endif - -#include "memory_access.h" -#include "tag.h" -#include "assert_support.h" -#include "math_support.h" -#include "sw_event_global.h" /* Event IDs.*/ -#if !defined(HAS_NO_INPUT_FORMATTER) -#include "ia_css_ifmtr.h" -#endif -#if !defined(HAS_NO_INPUT_SYSTEM) -#include "input_system.h" -#endif -#include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */ -#include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */ -#include "gdc_device.h" /* HRT_GDC_N */ -#include "dma.h" /* dma_set_max_burst_size() */ -#include "irq.h" /* virq */ -#include "sp.h" /* cnd_sp_irq_enable() */ -#include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */ -#include "gp_device.h" /* gp_device_reg_store() */ -#define __INLINE_GPIO__ -#include "gpio.h" -#include "timed_ctrl.h" -#include "platform_support.h" /* hrt_sleep(), inline */ -#include "ia_css_inputfifo.h" -#define WITH_PC_MONITORING 0 - -#define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0 - -#if WITH_PC_MONITORING -#define MULTIPLE_SAMPLES 1 -#define NOF_SAMPLES 60 -#include "linux/kthread.h" -#include "linux/sched.h" -#include "linux/delay.h" -#include "sh_css_metrics.h" -static int thread_alive; -#endif /* WITH_PC_MONITORING */ - -#include "ia_css_spctrl.h" -#include "ia_css_version_data.h" -#include "sh_css_struct.h" -#include "ia_css_bufq.h" -#include "ia_css_timer.h" /* clock_value_t */ - -#include "isp/modes/interface/input_buf.isp.h" - -/* Name of the sp program: should not be built-in */ -#define SP_PROG_NAME "sp" -/* Size of Refcount List */ -#define REFCOUNT_SIZE 1000 - -/* for JPEG, we don't know the length of the image upfront, - * but since we support sensor upto 16MP, we take this as - * upper limit. - */ -#define JPEG_BYTES (16 * 1024 * 1024) - -#define STATS_ENABLED(stage) (stage && stage->binary && stage->binary->info && \ - (stage->binary->info->sp.enable.s3a || stage->binary->info->sp.enable.dis)) - -struct sh_css my_css; - -int (*sh_css_printf) (const char *fmt, va_list args) = NULL; - -/* modes of work: stream_create and stream_destroy will update the save/restore data - only when in working mode, not suspend/resume -*/ -enum ia_sh_css_modes { - sh_css_mode_none = 0, - sh_css_mode_working, - sh_css_mode_suspend, - sh_css_mode_resume -}; - -/* a stream seed, to save and restore the stream data. - the stream seed contains all the data required to "grow" the seed again after it was closed. -*/ -struct sh_css_stream_seed { - struct ia_css_stream **orig_stream; /* pointer to restore the original handle */ - struct ia_css_stream *stream; /* handle, used as ID too.*/ - struct ia_css_stream_config stream_config; /* stream config struct */ - int num_pipes; - struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; /* pipe handles */ - struct ia_css_pipe **orig_pipes[IA_CSS_PIPE_ID_NUM]; /* pointer to restore original handle */ - struct ia_css_pipe_config pipe_config[IA_CSS_PIPE_ID_NUM]; /* pipe config structs */ -}; - -#define MAX_ACTIVE_STREAMS 5 -/* A global struct for save/restore to hold all the data that should sustain power-down: - MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds. -*/ -struct sh_css_save { - enum ia_sh_css_modes mode; - uint32_t mmu_base; /* the last mmu_base */ - enum ia_css_irq_type irq_type; - struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS]; - struct ia_css_fw *loaded_fw; /* fw struct previously loaded */ - struct ia_css_env driver_env; /* driver-supplied env copy */ -}; - -static bool my_css_save_initialized; /* if my_css_save was initialized */ -static struct sh_css_save my_css_save; - -/* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline, - this array is temporary and will be replaced by resource manager*/ -/* Taking the biggest Size for number of Elements */ -#define MAX_HMM_BUFFER_NUM \ - (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2)) - -struct sh_css_hmm_buffer_record { - bool in_use; - enum ia_css_buffer_type type; - struct ia_css_rmgr_vbuf_handle *h_vbuf; - hrt_address kernel_ptr; -}; - -static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM]; - -#define GPIO_FLASH_PIN_MASK (1 << HIVE_GPIO_STROBE_TRIGGER_PIN) - -static bool fw_explicitly_loaded = false; - -/* - * Local prototypes - */ - -static enum ia_css_err -allocate_delay_frames(struct ia_css_pipe *pipe); - -static enum ia_css_err -sh_css_pipe_start(struct ia_css_stream *stream); - -#ifdef ISP2401 -/* - * @brief Stop all "ia_css_pipe" instances in the target - * "ia_css_stream" instance. - * - * @param[in] stream Point to the target "ia_css_stream" instance. - * - * @return - * - IA_CSS_SUCCESS, if the "stop" requests have been successfully sent out. - * - CSS error code, otherwise. - * - * - * NOTE - * This API sends the "stop" requests to the "ia_css_pipe" - * instances in the same "ia_css_stream" instance. It will - * return without waiting for all "ia_css_pipe" instatnces - * being stopped. - */ -static enum ia_css_err -sh_css_pipes_stop(struct ia_css_stream *stream); - -/* - * @brief Check if all "ia_css_pipe" instances in the target - * "ia_css_stream" instance have stopped. - * - * @param[in] stream Point to the target "ia_css_stream" instance. - * - * @return - * - true, if all "ia_css_pipe" instances in the target "ia_css_stream" - * instance have ben stopped. - * - false, otherwise. - */ -static bool -sh_css_pipes_have_stopped(struct ia_css_stream *stream); - -static enum ia_css_err -ia_css_pipe_check_format(struct ia_css_pipe *pipe, enum ia_css_frame_format format); - -static enum ia_css_err -check_pipe_resolutions(const struct ia_css_pipe *pipe); - -#endif - -static enum ia_css_err -ia_css_pipe_load_extension(struct ia_css_pipe *pipe, - struct ia_css_fw_info *firmware); - -static void -ia_css_pipe_unload_extension(struct ia_css_pipe *pipe, - struct ia_css_fw_info *firmware); -static void -ia_css_reset_defaults(struct sh_css* css); - -static void -sh_css_init_host_sp_control_vars(void); - -static enum ia_css_err set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version); - -static bool -need_capture_pp(const struct ia_css_pipe *pipe); - -static bool -need_yuv_scaler_stage(const struct ia_css_pipe *pipe); - -static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output( - struct ia_css_frame_info *cas_scaler_in_info, - struct ia_css_frame_info *cas_scaler_out_info, - struct ia_css_frame_info *cas_scaler_vf_info, - struct ia_css_cas_binary_descr *descr); - -static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr *descr); - -static bool -need_downscaling(const struct ia_css_resolution in_res, - const struct ia_css_resolution out_res); - -static bool need_capt_ldc(const struct ia_css_pipe *pipe); - -static enum ia_css_err -sh_css_pipe_load_binaries(struct ia_css_pipe *pipe); - -static -enum ia_css_err sh_css_pipe_get_viewfinder_frame_info( - struct ia_css_pipe *pipe, - struct ia_css_frame_info *info, - unsigned int idx); - -static enum ia_css_err -sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, - struct ia_css_frame_info *info, - unsigned int idx); - -static enum ia_css_err -capture_start(struct ia_css_pipe *pipe); - -static enum ia_css_err -video_start(struct ia_css_pipe *pipe); - -static enum ia_css_err -preview_start(struct ia_css_pipe *pipe); - -static enum ia_css_err -yuvpp_start(struct ia_css_pipe *pipe); - -static bool copy_on_sp(struct ia_css_pipe *pipe); - -static enum ia_css_err -init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, - struct ia_css_frame *vf_frame, unsigned int idx); - -static enum ia_css_err -init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe, - struct ia_css_frame *frame, enum ia_css_frame_format format); - -static enum ia_css_err -init_out_frameinfo_defaults(struct ia_css_pipe *pipe, - struct ia_css_frame *out_frame, unsigned int idx); - -static enum ia_css_err -sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, - const void *acc_fw); - -static enum ia_css_err -alloc_continuous_frames( - struct ia_css_pipe *pipe, bool init_time); - -static void -pipe_global_init(void); - -static enum ia_css_err -pipe_generate_pipe_num(const struct ia_css_pipe *pipe, unsigned int *pipe_number); - -static void -pipe_release_pipe_num(unsigned int pipe_num); - -static enum ia_css_err -create_host_pipeline_structure(struct ia_css_stream *stream); - -static enum ia_css_err -create_host_pipeline(struct ia_css_stream *stream); - -static enum ia_css_err -create_host_preview_pipeline(struct ia_css_pipe *pipe); - -static enum ia_css_err -create_host_video_pipeline(struct ia_css_pipe *pipe); - -static enum ia_css_err -create_host_copy_pipeline(struct ia_css_pipe *pipe, - unsigned max_input_width, - struct ia_css_frame *out_frame); - -static enum ia_css_err -create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe); - -static enum ia_css_err -create_host_capture_pipeline(struct ia_css_pipe *pipe); - -static enum ia_css_err -create_host_yuvpp_pipeline(struct ia_css_pipe *pipe); - -static enum ia_css_err -create_host_acc_pipeline(struct ia_css_pipe *pipe); - -static unsigned int -sh_css_get_sw_interrupt_value(unsigned int irq); - -static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe); - -static struct ia_css_binary * -ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe); - -static struct ia_css_binary * -ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe); - -static void -sh_css_hmm_buffer_record_init(void); - -static void -sh_css_hmm_buffer_record_uninit(void); - -static void -sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record); - -static struct sh_css_hmm_buffer_record -*sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf, - enum ia_css_buffer_type type, - hrt_address kernel_ptr); - -static struct sh_css_hmm_buffer_record -*sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr, - enum ia_css_buffer_type type); - -void -ia_css_get_acc_configs( - struct ia_css_pipe *pipe, - struct ia_css_isp_config *config); - - -#if CONFIG_ON_FRAME_ENQUEUE() -static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info *info, struct frame_data_wrapper *frame); -#endif - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 -static unsigned int get_crop_lines_for_bayer_order(const struct ia_css_stream_config *config); -static unsigned int get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config); -static void get_pipe_extra_pixel(struct ia_css_pipe *pipe, - unsigned int *extra_row, unsigned int *extra_column); -#endif - -#ifdef ISP2401 -#ifdef USE_INPUT_SYSTEM_VERSION_2401 -static enum ia_css_err -aspect_ratio_crop_init(struct ia_css_stream *curr_stream, - struct ia_css_pipe *pipes[], - bool *do_crop_status); - -static bool -aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe); - -static enum ia_css_err -aspect_ratio_crop(struct ia_css_pipe *curr_pipe, - struct ia_css_resolution *effective_res); -#endif - -#endif -static void -sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe) -{ - assert(pipe != NULL); - if (pipe == NULL) { - IA_CSS_ERROR("NULL input parameter"); - return; - } - - if (pipe->shading_table) - ia_css_shading_table_free(pipe->shading_table); - pipe->shading_table = NULL; -} - -static enum ia_css_frame_format yuv420_copy_formats[] = { - IA_CSS_FRAME_FORMAT_NV12, - IA_CSS_FRAME_FORMAT_NV21, - IA_CSS_FRAME_FORMAT_YV12, - IA_CSS_FRAME_FORMAT_YUV420, - IA_CSS_FRAME_FORMAT_YUV420_16, - IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8, - IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8 -}; - -static enum ia_css_frame_format yuv422_copy_formats[] = { - IA_CSS_FRAME_FORMAT_NV12, - IA_CSS_FRAME_FORMAT_NV16, - IA_CSS_FRAME_FORMAT_NV21, - IA_CSS_FRAME_FORMAT_NV61, - IA_CSS_FRAME_FORMAT_YV12, - IA_CSS_FRAME_FORMAT_YV16, - IA_CSS_FRAME_FORMAT_YUV420, - IA_CSS_FRAME_FORMAT_YUV420_16, - IA_CSS_FRAME_FORMAT_YUV422, - IA_CSS_FRAME_FORMAT_YUV422_16, - IA_CSS_FRAME_FORMAT_UYVY, - IA_CSS_FRAME_FORMAT_YUYV -}; - -/* Verify whether the selected output format is can be produced - * by the copy binary given the stream format. - * */ -static enum ia_css_err -verify_copy_out_frame_format(struct ia_css_pipe *pipe) -{ - enum ia_css_frame_format out_fmt = pipe->output_info[0].format; - unsigned int i, found = 0; - - assert(pipe != NULL); - assert(pipe->stream != NULL); - - switch (pipe->stream->config.input_config.format) { - case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: - case ATOMISP_INPUT_FORMAT_YUV420_8: - for (i=0; i<ARRAY_SIZE(yuv420_copy_formats) && !found; i++) - found = (out_fmt == yuv420_copy_formats[i]); - break; - case ATOMISP_INPUT_FORMAT_YUV420_10: - case ATOMISP_INPUT_FORMAT_YUV420_16: - found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16); - break; - case ATOMISP_INPUT_FORMAT_YUV422_8: - for (i=0; i<ARRAY_SIZE(yuv422_copy_formats) && !found; i++) - found = (out_fmt == yuv422_copy_formats[i]); - break; - case ATOMISP_INPUT_FORMAT_YUV422_10: - case ATOMISP_INPUT_FORMAT_YUV422_16: - found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 || - out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16); - break; - case ATOMISP_INPUT_FORMAT_RGB_444: - case ATOMISP_INPUT_FORMAT_RGB_555: - case ATOMISP_INPUT_FORMAT_RGB_565: - found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 || - out_fmt == IA_CSS_FRAME_FORMAT_RGB565); - break; - case ATOMISP_INPUT_FORMAT_RGB_666: - case ATOMISP_INPUT_FORMAT_RGB_888: - found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 || - out_fmt == IA_CSS_FRAME_FORMAT_YUV420); - break; - case ATOMISP_INPUT_FORMAT_RAW_6: - case ATOMISP_INPUT_FORMAT_RAW_7: - case ATOMISP_INPUT_FORMAT_RAW_8: - case ATOMISP_INPUT_FORMAT_RAW_10: - case ATOMISP_INPUT_FORMAT_RAW_12: - case ATOMISP_INPUT_FORMAT_RAW_14: - case ATOMISP_INPUT_FORMAT_RAW_16: - found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) || - (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED); - break; - case ATOMISP_INPUT_FORMAT_BINARY_8: - found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8); - break; - default: - break; - } - if (!found) - return IA_CSS_ERR_INVALID_ARGUMENTS; - return IA_CSS_SUCCESS; -} - -unsigned int -ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream) -{ - int bpp = 0; - - if (stream != NULL) - bpp = ia_css_util_input_format_bpp(stream->config.input_config.format, - stream->config.pixels_per_clock == 2); - - return bpp; -} - -#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) -static enum ia_css_err -sh_css_config_input_network(struct ia_css_stream *stream) -{ - unsigned int fmt_type; - struct ia_css_pipe *pipe = stream->last_pipe; - struct ia_css_binary *binary = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - - assert(stream != NULL); - assert(pipe != NULL); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_config_input_network() enter:\n"); - - if (pipe->pipeline.stages) - binary = pipe->pipeline.stages->binary; - - err = ia_css_isys_convert_stream_format_to_mipi_format( - stream->config.input_config.format, - stream->csi_rx_config.comp, - &fmt_type); - if (err != IA_CSS_SUCCESS) - return err; - sh_css_sp_program_input_circuit(fmt_type, - stream->config.channel_id, - stream->config.mode); - - if ((binary && (binary->online || stream->config.continuous)) || - pipe->config.mode == IA_CSS_PIPE_MODE_COPY) { - err = ia_css_ifmtr_configure(&stream->config, - binary); - if (err != IA_CSS_SUCCESS) - return err; - } - - if (stream->config.mode == IA_CSS_INPUT_MODE_TPG || - stream->config.mode == IA_CSS_INPUT_MODE_PRBS) { - unsigned int hblank_cycles = 100, - vblank_lines = 6, - width, - height, - vblank_cycles; - width = (stream->config.input_config.input_res.width) / (1 + (stream->config.pixels_per_clock == 2)); - height = stream->config.input_config.input_res.height; - vblank_cycles = vblank_lines * (width + hblank_cycles); - sh_css_sp_configure_sync_gen(width, height, hblank_cycles, - vblank_cycles); -#if defined(IS_ISP_2400_SYSTEM) - if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) { - /* TODO: move define to proper file in tools */ - #define GP_ISEL_TPG_MODE 0x90058 - ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0); - } -#endif - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_config_input_network() leave:\n"); - return IA_CSS_SUCCESS; -} -#elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401) -static unsigned int csi2_protocol_calculate_max_subpixels_per_line( - enum atomisp_input_format format, - unsigned int pixels_per_line) -{ - unsigned int rval; - - switch (format) { - case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: - /* - * The frame format layout is shown below. - * - * Line 0: UYY0 UYY0 ... UYY0 - * Line 1: VYY0 VYY0 ... VYY0 - * Line 2: UYY0 UYY0 ... UYY0 - * Line 3: VYY0 VYY0 ... VYY0 - * ... - * Line (n-2): UYY0 UYY0 ... UYY0 - * Line (n-1): VYY0 VYY0 ... VYY0 - * - * In this frame format, the even-line is - * as wide as the odd-line. - * The 0 is introduced by the input system - * (mipi backend). - */ - rval = pixels_per_line * 2; - break; - case ATOMISP_INPUT_FORMAT_YUV420_8: - case ATOMISP_INPUT_FORMAT_YUV420_10: - case ATOMISP_INPUT_FORMAT_YUV420_16: - /* - * The frame format layout is shown below. - * - * Line 0: YYYY YYYY ... YYYY - * Line 1: UYVY UYVY ... UYVY UYVY - * Line 2: YYYY YYYY ... YYYY - * Line 3: UYVY UYVY ... UYVY UYVY - * ... - * Line (n-2): YYYY YYYY ... YYYY - * Line (n-1): UYVY UYVY ... UYVY UYVY - * - * In this frame format, the odd-line is twice - * wider than the even-line. - */ - rval = pixels_per_line * 2; - break; - case ATOMISP_INPUT_FORMAT_YUV422_8: - case ATOMISP_INPUT_FORMAT_YUV422_10: - case ATOMISP_INPUT_FORMAT_YUV422_16: - /* - * The frame format layout is shown below. - * - * Line 0: UYVY UYVY ... UYVY - * Line 1: UYVY UYVY ... UYVY - * Line 2: UYVY UYVY ... UYVY - * Line 3: UYVY UYVY ... UYVY - * ... - * Line (n-2): UYVY UYVY ... UYVY - * Line (n-1): UYVY UYVY ... UYVY - * - * In this frame format, the even-line is - * as wide as the odd-line. - */ - rval = pixels_per_line * 2; - break; - case ATOMISP_INPUT_FORMAT_RGB_444: - case ATOMISP_INPUT_FORMAT_RGB_555: - case ATOMISP_INPUT_FORMAT_RGB_565: - case ATOMISP_INPUT_FORMAT_RGB_666: - case ATOMISP_INPUT_FORMAT_RGB_888: - /* - * The frame format layout is shown below. - * - * Line 0: ABGR ABGR ... ABGR - * Line 1: ABGR ABGR ... ABGR - * Line 2: ABGR ABGR ... ABGR - * Line 3: ABGR ABGR ... ABGR - * ... - * Line (n-2): ABGR ABGR ... ABGR - * Line (n-1): ABGR ABGR ... ABGR - * - * In this frame format, the even-line is - * as wide as the odd-line. - */ - rval = pixels_per_line * 4; - break; - case ATOMISP_INPUT_FORMAT_RAW_6: - case ATOMISP_INPUT_FORMAT_RAW_7: - case ATOMISP_INPUT_FORMAT_RAW_8: - case ATOMISP_INPUT_FORMAT_RAW_10: - case ATOMISP_INPUT_FORMAT_RAW_12: - case ATOMISP_INPUT_FORMAT_RAW_14: - case ATOMISP_INPUT_FORMAT_RAW_16: - case ATOMISP_INPUT_FORMAT_BINARY_8: - case ATOMISP_INPUT_FORMAT_USER_DEF1: - case ATOMISP_INPUT_FORMAT_USER_DEF2: - case ATOMISP_INPUT_FORMAT_USER_DEF3: - case ATOMISP_INPUT_FORMAT_USER_DEF4: - case ATOMISP_INPUT_FORMAT_USER_DEF5: - case ATOMISP_INPUT_FORMAT_USER_DEF6: - case ATOMISP_INPUT_FORMAT_USER_DEF7: - case ATOMISP_INPUT_FORMAT_USER_DEF8: - /* - * The frame format layout is shown below. - * - * Line 0: Pixel Pixel ... Pixel - * Line 1: Pixel Pixel ... Pixel - * Line 2: Pixel Pixel ... Pixel - * Line 3: Pixel Pixel ... Pixel - * ... - * Line (n-2): Pixel Pixel ... Pixel - * Line (n-1): Pixel Pixel ... Pixel - * - * In this frame format, the even-line is - * as wide as the odd-line. - */ - rval = pixels_per_line; - break; - default: - rval = 0; - break; - } - - return rval; -} - -static bool sh_css_translate_stream_cfg_to_input_system_input_port_id( - struct ia_css_stream_config *stream_cfg, - ia_css_isys_descr_t *isys_stream_descr) -{ - bool rc; - - rc = true; - switch (stream_cfg->mode) { - case IA_CSS_INPUT_MODE_TPG: - - if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID; - } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID; - } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID; - } - - break; - case IA_CSS_INPUT_MODE_PRBS: - - if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID; - } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID; - } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID; - } - - break; - case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: - - if (stream_cfg->source.port.port == MIPI_PORT0_ID) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID; - } else if (stream_cfg->source.port.port == MIPI_PORT1_ID) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID; - } else if (stream_cfg->source.port.port == MIPI_PORT2_ID) { - isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID; - } - - break; - default: - rc = false; - break; - } - - return rc; -} - -static bool sh_css_translate_stream_cfg_to_input_system_input_port_type( - struct ia_css_stream_config *stream_cfg, - ia_css_isys_descr_t *isys_stream_descr) -{ - bool rc; - - rc = true; - switch (stream_cfg->mode) { - case IA_CSS_INPUT_MODE_TPG: - - isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG; - - break; - case IA_CSS_INPUT_MODE_PRBS: - - isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS; - - break; - case IA_CSS_INPUT_MODE_SENSOR: - case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: - - isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR; - break; - - default: - rc = false; - break; - } - - return rc; -} - -static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr( - struct ia_css_stream_config *stream_cfg, - ia_css_isys_descr_t *isys_stream_descr, - int isys_stream_idx) -{ - bool rc; - - rc = true; - switch (stream_cfg->mode) { - case IA_CSS_INPUT_MODE_TPG: - if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) { - isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP; - } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) { - isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO; - } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) { - isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO; - } else { - rc = false; - } - - /* - * TODO - * - Make "color_cfg" as part of "ia_css_tpg_config". - */ - isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51; - isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102; - isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255; - isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0; - isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100; - isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160; - - isys_stream_descr->tpg_port_attr.mask_cfg.h_mask = stream_cfg->source.tpg.x_mask; - isys_stream_descr->tpg_port_attr.mask_cfg.v_mask = stream_cfg->source.tpg.y_mask; - isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask = stream_cfg->source.tpg.xy_mask; - - isys_stream_descr->tpg_port_attr.delta_cfg.h_delta = stream_cfg->source.tpg.x_delta; - isys_stream_descr->tpg_port_attr.delta_cfg.v_delta = stream_cfg->source.tpg.y_delta; - - /* - * TODO - * - Make "sync_gen_cfg" as part of "ia_css_tpg_config". - */ - isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100; - isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100; - isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock = stream_cfg->pixels_per_clock; - isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t) ~(0x0); - isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_line = stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width; - isys_stream_descr->tpg_port_attr.sync_gen_cfg.lines_per_frame = stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height; - - break; - case IA_CSS_INPUT_MODE_PRBS: - - isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed; - isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1; - - /* - * TODO - * - Make "sync_gen_cfg" as part of "ia_css_prbs_config". - */ - isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100; - isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100; - isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock = stream_cfg->pixels_per_clock; - isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t) ~(0x0); - isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line = stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width; - isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame = stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height; - - break; - case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: - { - enum ia_css_err err; - unsigned int fmt_type; - - err = ia_css_isys_convert_stream_format_to_mipi_format( - stream_cfg->isys_config[isys_stream_idx].format, - MIPI_PREDICTOR_NONE, - &fmt_type); - if (err != IA_CSS_SUCCESS) - rc = false; - - isys_stream_descr->csi_port_attr.active_lanes = stream_cfg->source.port.num_lanes; - isys_stream_descr->csi_port_attr.fmt_type = fmt_type; - isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - isys_stream_descr->online = stream_cfg->online; -#endif - err |= ia_css_isys_convert_compressed_format( - &stream_cfg->source.port.compression, - isys_stream_descr); - if (err != IA_CSS_SUCCESS) - rc = false; - - /* metadata */ - isys_stream_descr->metadata.enable = false; - if (stream_cfg->metadata_config.resolution.height > 0) { - err = ia_css_isys_convert_stream_format_to_mipi_format( - stream_cfg->metadata_config.data_type, - MIPI_PREDICTOR_NONE, - &fmt_type); - if (err != IA_CSS_SUCCESS) - rc = false; - isys_stream_descr->metadata.fmt_type = fmt_type; - isys_stream_descr->metadata.bits_per_pixel = - ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true); - isys_stream_descr->metadata.pixels_per_line = stream_cfg->metadata_config.resolution.width; - isys_stream_descr->metadata.lines_per_frame = stream_cfg->metadata_config.resolution.height; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* For new input system, number of str2mmio requests must be even. - * So we round up number of metadata lines to be even. */ - if (isys_stream_descr->metadata.lines_per_frame > 0) - isys_stream_descr->metadata.lines_per_frame += - (isys_stream_descr->metadata.lines_per_frame & 1); -#endif - isys_stream_descr->metadata.align_req_in_bytes = - ia_css_csi2_calculate_input_system_alignment(stream_cfg->metadata_config.data_type); - isys_stream_descr->metadata.enable = true; - } - - break; - } - default: - rc = false; - break; - } - - return rc; -} - -static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution( - struct ia_css_stream_config *stream_cfg, - ia_css_isys_descr_t *isys_stream_descr, - int isys_stream_idx) -{ - unsigned int bits_per_subpixel; - unsigned int max_subpixels_per_line; - unsigned int lines_per_frame; - unsigned int align_req_in_bytes; - enum atomisp_input_format fmt_type; - - fmt_type = stream_cfg->isys_config[isys_stream_idx].format; - if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR || - stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) && - stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) { - - if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == - UNCOMPRESSED_BITS_PER_PIXEL_10) { - fmt_type = ATOMISP_INPUT_FORMAT_RAW_10; - } - else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == - UNCOMPRESSED_BITS_PER_PIXEL_12) { - fmt_type = ATOMISP_INPUT_FORMAT_RAW_12; - } - else - return false; - } - - bits_per_subpixel = - sh_css_stream_format_2_bits_per_subpixel(fmt_type); - if (bits_per_subpixel == 0) - return false; - - max_subpixels_per_line = - csi2_protocol_calculate_max_subpixels_per_line(fmt_type, - stream_cfg->isys_config[isys_stream_idx].input_res.width); - if (max_subpixels_per_line == 0) - return false; - - lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height; - if (lines_per_frame == 0) - return false; - - align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type); - - /* HW needs subpixel info for their settings */ - isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel; - isys_stream_descr->input_port_resolution.pixels_per_line = max_subpixels_per_line; - isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame; - isys_stream_descr->input_port_resolution.align_req_in_bytes = align_req_in_bytes; - - return true; -} - -static bool sh_css_translate_stream_cfg_to_isys_stream_descr( - struct ia_css_stream_config *stream_cfg, - bool early_polling, - ia_css_isys_descr_t *isys_stream_descr, - int isys_stream_idx) -{ - bool rc; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n"); - rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg, isys_stream_descr); - rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg, isys_stream_descr); - rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg, isys_stream_descr, isys_stream_idx); - rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(stream_cfg, isys_stream_descr, isys_stream_idx); - - isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels; - isys_stream_descr->linked_isys_stream_id = (int8_t) stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id; - /* - * Early polling is required for timestamp accuracy in certain case. - * The ISYS HW polling is started on - * ia_css_isys_stream_capture_indication() instead of - * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of - * capture takes longer than getting an ISYS frame - * - * Only 2401 relevant ?? - */ - isys_stream_descr->polling_mode - = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST - : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n"); - - return rc; -} - -static bool sh_css_translate_binary_info_to_input_system_output_port_attr( - struct ia_css_binary *binary, - ia_css_isys_descr_t *isys_stream_descr) -{ - if (!binary) - return false; - - isys_stream_descr->output_port_attr.left_padding = binary->left_padding; - isys_stream_descr->output_port_attr.max_isp_input_width = binary->info->sp.input.max_width; - - return true; -} - -static enum ia_css_err -sh_css_config_input_network(struct ia_css_stream *stream) -{ - bool rc; - ia_css_isys_descr_t isys_stream_descr; - unsigned int sp_thread_id; - struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal; - struct ia_css_pipe *pipe = NULL; - struct ia_css_binary *binary = NULL; - int i; - uint32_t isys_stream_id; - bool early_polling = false; - - assert(stream != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_config_input_network() enter 0x%p:\n", stream); - - if (stream->config.continuous == true) { - if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { - pipe = stream->last_pipe; - } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) { - pipe = stream->last_pipe; - } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) { - pipe = stream->last_pipe->pipe_settings.preview.copy_pipe; - } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) { - pipe = stream->last_pipe->pipe_settings.video.copy_pipe; - } - } else { - pipe = stream->last_pipe; - if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { - /* - * We need to poll the ISYS HW in capture_indication itself - * for "non-continuous" capture usecase for getting accurate - * isys frame capture timestamps. - * This is because the capturepipe propcessing takes longer - * to execute than the input system frame capture. - * 2401 specific - */ - early_polling = true; - } - } - - assert(pipe != NULL); - if (pipe == NULL) - return IA_CSS_ERR_INTERNAL_ERROR; - - if (pipe->pipeline.stages != NULL) - if (pipe->pipeline.stages->binary != NULL) - binary = pipe->pipeline.stages->binary; - - - - if (binary) { - /* this was being done in ifmtr in 2400. - * online and cont bypass the init_in_frameinfo_memory_defaults - * so need to do it here - */ - ia_css_get_crop_offsets(pipe, &binary->in_frame_info); - } - - /* get the SP thread id */ - rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id); - if (!rc) - return IA_CSS_ERR_INTERNAL_ERROR; - /* get the target input terminal */ - sp_pipeline_input_terminal = &(sh_css_sp_group.pipe_io[sp_thread_id].input); - - for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) { - /* initialization */ - memset((void*)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t)); - sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0; - sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0; - - if (!stream->config.isys_config[i].valid) - continue; - - /* translate the stream configuration to the Input System (2401) configuration */ - rc = sh_css_translate_stream_cfg_to_isys_stream_descr( - &(stream->config), - early_polling, - &(isys_stream_descr), i); - - if (stream->config.online) { - rc &= sh_css_translate_binary_info_to_input_system_output_port_attr( - binary, - &(isys_stream_descr)); - } - - if (!rc) - return IA_CSS_ERR_INTERNAL_ERROR; - - isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i); - - /* create the virtual Input System (2401) */ - rc = ia_css_isys_stream_create( - &(isys_stream_descr), - &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]), - isys_stream_id); - if (!rc) - return IA_CSS_ERR_INTERNAL_ERROR; - - /* calculate the configuration of the virtual Input System (2401) */ - rc = ia_css_isys_stream_calculate_cfg( - &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]), - &(isys_stream_descr), - &(sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i])); - if (!rc) { - ia_css_isys_stream_destroy(&(sp_pipeline_input_terminal->context.virtual_input_system_stream[i])); - return IA_CSS_ERR_INTERNAL_ERROR; - } - } - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_config_input_network() leave:\n"); - - return IA_CSS_SUCCESS; -} - -static inline struct ia_css_pipe *stream_get_last_pipe( - struct ia_css_stream *stream) -{ - struct ia_css_pipe *last_pipe = NULL; - if (stream != NULL) - last_pipe = stream->last_pipe; - - return last_pipe; -} - -static inline struct ia_css_pipe *stream_get_copy_pipe( - struct ia_css_stream *stream) -{ - struct ia_css_pipe *copy_pipe = NULL; - struct ia_css_pipe *last_pipe = NULL; - enum ia_css_pipe_id pipe_id; - - last_pipe = stream_get_last_pipe(stream); - - if ((stream != NULL) && - (last_pipe != NULL) && - (stream->config.continuous)) { - - pipe_id = last_pipe->mode; - switch (pipe_id) { - case IA_CSS_PIPE_ID_PREVIEW: - copy_pipe = last_pipe->pipe_settings.preview.copy_pipe; - break; - case IA_CSS_PIPE_ID_VIDEO: - copy_pipe = last_pipe->pipe_settings.video.copy_pipe; - break; - default: - copy_pipe = NULL; - break; - } - } - - return copy_pipe; -} - -static inline struct ia_css_pipe *stream_get_target_pipe( - struct ia_css_stream *stream) -{ - struct ia_css_pipe *target_pipe; - - /* get the pipe that consumes the stream */ - if (stream->config.continuous) { - target_pipe = stream_get_copy_pipe(stream); - } else { - target_pipe = stream_get_last_pipe(stream); - } - - return target_pipe; -} - -static enum ia_css_err stream_csi_rx_helper( - struct ia_css_stream *stream, - enum ia_css_err (*func)(enum mipi_port_id, uint32_t)) -{ - enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR; - uint32_t sp_thread_id, stream_id; - bool rc; - struct ia_css_pipe *target_pipe = NULL; - - if ((stream == NULL) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)) - goto exit; - - target_pipe = stream_get_target_pipe(stream); - - if (target_pipe == NULL) - goto exit; - - rc = ia_css_pipeline_get_sp_thread_id( - ia_css_pipe_get_pipe_num(target_pipe), - &sp_thread_id); - - if (!rc) - goto exit; - - /* (un)register all valid "virtual isys streams" within the ia_css_stream */ - stream_id = 0; - do { - if (stream->config.isys_config[stream_id].valid) { - uint32_t isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id); - retval = func(stream->config.source.port.port, isys_stream_id); - } - stream_id++; - } while ((retval == IA_CSS_SUCCESS) && - (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)); - -exit: - return retval; -} - -static inline enum ia_css_err stream_register_with_csi_rx( - struct ia_css_stream *stream) -{ - return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream); -} - -static inline enum ia_css_err stream_unregister_with_csi_rx( - struct ia_css_stream *stream) -{ - return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream); -} -#endif - -#if WITH_PC_MONITORING -static struct task_struct *my_kthread; /* Handle for the monitoring thread */ -static int sh_binary_running; /* Enable sampling in the thread */ - -static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist) -{ - unsigned i; - unsigned cnt_run = 0; - unsigned cnt_stall = 0; - - if (hist == NULL) - return; - - sh_css_print("%s histogram length = %d\n", core_name, hist->length); - sh_css_print("%s PC\trun\tstall\n", core_name); - - for (i = 0; i < hist->length; i++) { - if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i])) - continue; - sh_css_print("%s %d\t%d\t%d\n", - core_name, i, hist->run[i], hist->stall[i]); - cnt_run += hist->run[i]; - cnt_stall += hist->stall[i]; - } - - sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, " - "hist->length = %d\n", - core_name, cnt_run, cnt_stall, hist->length); -} - -static void print_pc_histogram(void) -{ - struct ia_css_binary_metrics *metrics; - - for (metrics = sh_css_metrics.binary_metrics; - metrics; - metrics = metrics->next) { - if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW || - metrics->mode == IA_CSS_BINARY_MODE_VF_PP) { - sh_css_print("pc_histogram for binary %d is SKIPPED\n", - metrics->id); - continue; - } - - sh_css_print(" pc_histogram for binary %d\n", metrics->id); - print_pc_histo(" ISP", &metrics->isp_histogram); - print_pc_histo(" SP", &metrics->sp_histogram); - sh_css_print("print_pc_histogram() done for binay->id = %d, " - "done.\n", metrics->id); - } - - sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n"); -} - -static int pc_monitoring(void *data) -{ - int i = 0; - - (void)data; - while (true) { - if (sh_binary_running) { - sh_css_metrics_sample_pcs(); -#if MULTIPLE_SAMPLES - for (i = 0; i < NOF_SAMPLES; i++) - sh_css_metrics_sample_pcs(); -#endif - } - usleep_range(10, 50); - } - return 0; -} - -static void spying_thread_create(void) -{ - my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor"); - sh_css_metrics_enable_pc_histogram(1); -} - -static void input_frame_info(struct ia_css_frame_info frame_info) -{ - sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, " - "frame->info.res.height = %d, format = %d\n", - frame_info.res.width, frame_info.res.height, frame_info.format); -} -#endif /* WITH_PC_MONITORING */ - -static void -start_binary(struct ia_css_pipe *pipe, - struct ia_css_binary *binary) -{ - struct ia_css_stream *stream; - - assert(pipe != NULL); - /* Acceleration uses firmware, the binary thus can be NULL */ - /* assert(binary != NULL); */ - - (void)binary; - -#if !defined(HAS_NO_INPUT_SYSTEM) - stream = pipe->stream; -#else - (void)pipe; - (void)stream; -#endif - - if (binary) - sh_css_metrics_start_binary(&binary->metrics); - -#if WITH_PC_MONITORING - sh_css_print("PC_MONITORING: %s() -- binary id = %d , " - "enable_dvs_envelope = %d\n", - __func__, binary->info->sp.id, - binary->info->sp.enable.dvs_envelope); - input_frame_info(binary->in_frame_info); - - if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO) - sh_binary_running = true; -#endif - -#if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401) - if (stream->reconfigure_css_rx) { - ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, - pipe->stream->config.mode); - stream->reconfigure_css_rx = false; - } -#endif -} - -/* start the copy function on the SP */ -static enum ia_css_err -start_copy_on_sp(struct ia_css_pipe *pipe, - struct ia_css_frame *out_frame) -{ - - (void)out_frame; - assert(pipe != NULL); - assert(pipe->stream != NULL); - - if ((pipe == NULL) || (pipe->stream == NULL)) - return IA_CSS_ERR_INVALID_ARGUMENTS; - -#if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401) - if (pipe->stream->reconfigure_css_rx) - ia_css_isys_rx_disable(); -#endif - - if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8) - return IA_CSS_ERR_INTERNAL_ERROR; - sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2); - -#if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401) - if (pipe->stream->reconfigure_css_rx) { - ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, pipe->stream->config.mode); - pipe->stream->reconfigure_css_rx = false; - } -#endif - - return IA_CSS_SUCCESS; -} - -void sh_css_binary_args_reset(struct sh_css_binary_args *args) -{ - unsigned int i; - -#ifndef ISP2401 - for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) -#else - for (i = 0; i < NUM_TNR_FRAMES; i++) -#endif - args->tnr_frames[i] = NULL; - for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++) - args->delay_frames[i] = NULL; - args->in_frame = NULL; - for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) - args->out_frame[i] = NULL; - args->out_vf_frame = NULL; - args->copy_vf = false; - args->copy_output = true; - args->vf_downscale_log2 = 0; -} - -static void start_pipe( - struct ia_css_pipe *me, - enum sh_css_pipe_config_override copy_ovrd, - enum ia_css_input_mode input_mode) -{ -#if defined(HAS_NO_INPUT_SYSTEM) - (void)input_mode; -#endif - - IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d", - me, copy_ovrd, input_mode); - - assert(me != NULL); /* all callers are in this file and call with non null argument */ - - sh_css_sp_init_pipeline(&me->pipeline, - me->mode, - (uint8_t)ia_css_pipe_get_pipe_num(me), - me->config.default_capture_config.enable_xnr != 0, - me->stream->config.pixels_per_clock == 2, - me->stream->config.continuous, - false, - me->required_bds_factor, - copy_ovrd, - input_mode, - &me->stream->config.metadata_config, - &me->stream->info.metadata_info -#if !defined(HAS_NO_INPUT_SYSTEM) - ,(input_mode==IA_CSS_INPUT_MODE_MEMORY) ? - (enum mipi_port_id)0 : - me->stream->config.source.port.port -#endif -#ifdef ISP2401 - ,&me->config.internal_frame_origin_bqs_on_sctbl, - me->stream->isp_params_configs -#endif - ); - - if (me->config.mode != IA_CSS_PIPE_MODE_COPY) { - struct ia_css_pipeline_stage *stage; - stage = me->pipeline.stages; - if (stage) { - me->pipeline.current_stage = stage; - start_binary(me, stage->binary); - } - } - IA_CSS_LEAVE_PRIVATE("void"); -} - -void -sh_css_invalidate_shading_tables(struct ia_css_stream *stream) -{ - int i; - assert(stream != NULL); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "sh_css_invalidate_shading_tables() enter:\n"); - - for (i=0; i<stream->num_pipes; i++) { - assert(stream->pipes[i] != NULL); - sh_css_pipe_free_shading_table(stream->pipes[i]); - } - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "sh_css_invalidate_shading_tables() leave: return_void\n"); -} - -#ifndef ISP2401 -static void -enable_interrupts(enum ia_css_irq_type irq_type) -{ -#ifdef USE_INPUT_SYSTEM_VERSION_2 - enum mipi_port_id port; -#endif - bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE; - IA_CSS_ENTER_PRIVATE(""); - /* Enable IRQ on the SP which signals that SP goes to idle - * (aka ready state) */ - cnd_sp_irq_enable(SP0_ID, true); - /* Set the IRQ device 0 to either level or pulse */ - irq_enable_pulse(IRQ0_ID, enable_pulse); - - cnd_virq_enable_channel(virq_sp, true); - - /* Enable SW interrupt 0, this is used to signal ISYS events */ - cnd_virq_enable_channel( - (virq_id_t)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET), - true); - /* Enable SW interrupt 1, this is used to signal PSYS events */ - cnd_virq_enable_channel( - (virq_id_t)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET), - true); -#if !defined(HAS_IRQ_MAP_VERSION_2) - /* IRQ_SW_CHANNEL2_ID does not exist on 240x systems */ - cnd_virq_enable_channel( - (virq_id_t)(IRQ_SW_CHANNEL2_ID + IRQ_SW_CHANNEL_OFFSET), - true); - virq_clear_all(); -#endif - -#ifdef USE_INPUT_SYSTEM_VERSION_2 - for (port = 0; port < N_MIPI_PORT_ID; port++) - ia_css_isys_rx_enable_all_interrupts(port); -#endif - - IA_CSS_LEAVE_PRIVATE(""); -} - -#endif - -static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw, - const char * program, - ia_css_spctrl_cfg *spctrl_cfg) -{ - if((fw == NULL)||(spctrl_cfg == NULL)) - return false; - spctrl_cfg->sp_entry = 0; - spctrl_cfg->program_name = (char *)(program); - - spctrl_cfg->ddr_data_offset = fw->blob.data_source; - spctrl_cfg->dmem_data_addr = fw->blob.data_target; - spctrl_cfg->dmem_bss_addr = fw->blob.bss_target; - spctrl_cfg->data_size = fw->blob.data_size ; - spctrl_cfg->bss_size = fw->blob.bss_size; - - spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data; - spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state; - - spctrl_cfg->code_size = fw->blob.size; - spctrl_cfg->code = fw->blob.code; - spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */ - - return true; -} -void -ia_css_unload_firmware(void) -{ - if (sh_css_num_binaries) - { - /* we have already loaded before so get rid of the old stuff */ - ia_css_binary_uninit(); - sh_css_unload_firmware(); - } - fw_explicitly_loaded = false; -} - -static void -ia_css_reset_defaults(struct sh_css* css) -{ - struct sh_css default_css; - - /* Reset everything to zero */ - memset(&default_css, 0, sizeof(default_css)); - - /* Initialize the non zero values*/ - default_css.check_system_idle = true; - default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES; - - /* All should be 0: but memset does it already. - * default_css.num_mipi_frames[N_CSI_PORTS] = 0; - */ - - default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE; - - /*Set the defaults to the output */ - *css = default_css; -} - -bool -ia_css_check_firmware_version(const struct ia_css_fw *fw) -{ - bool retval = false; - - if (fw != NULL) { - retval = sh_css_check_firmware_version(fw->data); - } - return retval; -} - -enum ia_css_err -ia_css_load_firmware(const struct ia_css_env *env, - const struct ia_css_fw *fw) -{ - enum ia_css_err err; - - if (env == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - if (fw == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n"); - - /* make sure we initialize my_css */ - if (my_css.flush != env->cpu_mem_env.flush) { - ia_css_reset_defaults(&my_css); - my_css.flush = env->cpu_mem_env.flush; - } - - ia_css_unload_firmware(); /* in case we are called twice */ - err = sh_css_load_firmware(fw->data, fw->bytes); - if (err == IA_CSS_SUCCESS) { - err = ia_css_binary_init_infos(); - if (err == IA_CSS_SUCCESS) - fw_explicitly_loaded = true; - } - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave \n"); - return err; -} - -enum ia_css_err -ia_css_init(const struct ia_css_env *env, - const struct ia_css_fw *fw, - uint32_t mmu_l1_base, - enum ia_css_irq_type irq_type) -{ - enum ia_css_err err; - ia_css_spctrl_cfg spctrl_cfg; - - void (*flush_func)(struct ia_css_acc_fw *fw); - hrt_data select, enable; - - /* - * The C99 standard does not specify the exact object representation of structs; - * the representation is compiler dependent. - * - * The structs that are communicated between host and SP/ISP should have the - * exact same object representation. The compiler that is used to compile the - * firmware is hivecc. - * - * To check if a different compiler, used to compile a host application, uses - * another object representation, macros are defined specifying the size of - * the structs as expected by the firmware. - * - * A host application shall verify that a sizeof( ) of the struct is equal to - * the SIZE_OF_XXX macro of the corresponding struct. If they are not - * equal, functionality will break. - */ - /* Check struct sh_css_ddr_address_map */ - COMPILATION_ERROR_IF( sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT ); - /* Check struct host_sp_queues */ - COMPILATION_ERROR_IF( sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT ); - COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT ); - COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT ); - - /* Check struct host_sp_communication */ - COMPILATION_ERROR_IF( sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT ); - COMPILATION_ERROR_IF( sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT ); - - /* Check struct sh_css_hmm_buffer */ - COMPILATION_ERROR_IF( sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT ); - COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT ); - COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT ); - COMPILATION_ERROR_IF( sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT ); - - /* Check struct ia_css_init_dmem_cfg */ - COMPILATION_ERROR_IF( sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT ); - - if (fw == NULL && !fw_explicitly_loaded) - return IA_CSS_ERR_INVALID_ARGUMENTS; - if (env == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - sh_css_printf = env->print_env.debug_print; - - IA_CSS_ENTER("void"); - - flush_func = env->cpu_mem_env.flush; - - pipe_global_init(); - ia_css_pipeline_init(); - ia_css_queue_map_init(); - - ia_css_device_access_init(&env->hw_access_env); - - select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select) - & (~GPIO_FLASH_PIN_MASK); - enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e) - | GPIO_FLASH_PIN_MASK; - sh_css_mmu_set_page_table_base_index(mmu_l1_base); -#ifndef ISP2401 - my_css_save.mmu_base = mmu_l1_base; -#else - ia_css_save_mmu_base_addr(mmu_l1_base); -#endif - - ia_css_reset_defaults(&my_css); - - my_css_save.driver_env = *env; - my_css.flush = flush_func; - - err = ia_css_rmgr_init(); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } - -#ifndef ISP2401 - IA_CSS_LOG("init: %d", my_css_save_initialized); -#else - ia_css_save_restore_data_init(); -#endif - -#ifndef ISP2401 - if (!my_css_save_initialized) - { - my_css_save_initialized = true; - my_css_save.mode = sh_css_mode_working; - memset(my_css_save.stream_seeds, 0, sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS); - IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode); - } -#endif - mipi_init(); - -#ifndef ISP2401 - /* In case this has been programmed already, update internal - data structure ... DEPRECATED */ - my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID); - -#endif - my_css.irq_type = irq_type; -#ifndef ISP2401 - my_css_save.irq_type = irq_type; -#else - ia_css_save_irq_type(irq_type); -#endif - enable_interrupts(my_css.irq_type); - - /* configure GPIO to output mode */ - gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select); - gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable); - gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0); - - err = ia_css_refcount_init(REFCOUNT_SIZE); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } - err = sh_css_params_init(); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } - if (fw) - { - ia_css_unload_firmware(); /* in case we already had firmware loaded */ - err = sh_css_load_firmware(fw->data, fw->bytes); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } - err = ia_css_binary_init_infos(); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } - fw_explicitly_loaded = false; -#ifndef ISP2401 - my_css_save.loaded_fw = (struct ia_css_fw *)fw; -#endif - } - if(!sh_css_setup_spctrl_config(&sh_css_sp_fw,SP_PROG_NAME,&spctrl_cfg)) - return IA_CSS_ERR_INTERNAL_ERROR; - - err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } - -#if WITH_PC_MONITORING - if (!thread_alive) { - thread_alive++; - sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n", - __func__); - spying_thread_create(); - } -#endif - if (!sh_css_hrt_system_is_idle()) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_SYSTEM_NOT_IDLE); - return IA_CSS_ERR_SYSTEM_NOT_IDLE; - } - /* can be called here, queuing works, but: - - when sp is started later, it will wipe queued items - so for now we leave it for later and make sure - updates are not called to frequently. - sh_css_init_buffer_queues(); - */ - -#if defined(HAS_INPUT_SYSTEM_VERSION_2) && defined(HAS_INPUT_SYSTEM_VERSION_2401) -#if defined(USE_INPUT_SYSTEM_VERSION_2) - gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 0); -#elif defined (USE_INPUT_SYSTEM_VERSION_2401) - gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1); -#endif -#endif - -#if !defined(HAS_NO_INPUT_SYSTEM) - dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, - ISP_DMA_MAX_BURST_LENGTH); - - if(ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR) - err = IA_CSS_ERR_INVALID_ARGUMENTS; -#endif - - sh_css_params_map_and_store_default_gdc_lut(); - - IA_CSS_LEAVE_ERR(err); - return err; -} - -enum ia_css_err ia_css_suspend(void) -{ - int i; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() enter\n"); - my_css_save.mode = sh_css_mode_suspend; - for(i=0;i<MAX_ACTIVE_STREAMS;i++) - if (my_css_save.stream_seeds[i].stream != NULL) - { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> unloading seed %d (%p)\n", i, my_css_save.stream_seeds[i].stream); - ia_css_stream_unload(my_css_save.stream_seeds[i].stream); - } - my_css_save.mode = sh_css_mode_working; - ia_css_stop_sp(); - ia_css_uninit(); - for(i=0;i<MAX_ACTIVE_STREAMS;i++) - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> after 1: seed %d (%p)\n", i, my_css_save.stream_seeds[i].stream); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() leave\n"); - return IA_CSS_SUCCESS; -} - -enum ia_css_err -ia_css_resume(void) -{ - int i, j; - enum ia_css_err err; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() enter: void\n"); - - err = ia_css_init(&(my_css_save.driver_env), my_css_save.loaded_fw, my_css_save.mmu_base, my_css_save.irq_type); - if (err != IA_CSS_SUCCESS) - return err; - err = ia_css_start_sp(); - if (err != IA_CSS_SUCCESS) - return err; - my_css_save.mode = sh_css_mode_resume; - for(i=0;i<MAX_ACTIVE_STREAMS;i++) - { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> seed stream %p\n", my_css_save.stream_seeds[i].stream); - if (my_css_save.stream_seeds[i].stream != NULL) - { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> loading seed %d\n", i); - err = ia_css_stream_load(my_css_save.stream_seeds[i].stream); - if (err != IA_CSS_SUCCESS) - { - if (i) - for(j=0;j<i;j++) - ia_css_stream_unload(my_css_save.stream_seeds[j].stream); - return err; - } - err = ia_css_stream_start(my_css_save.stream_seeds[i].stream); - if (err != IA_CSS_SUCCESS) - { - for(j=0;j<=i;j++) - { - ia_css_stream_stop(my_css_save.stream_seeds[j].stream); - ia_css_stream_unload(my_css_save.stream_seeds[j].stream); - } - return err; - } - *my_css_save.stream_seeds[i].orig_stream = my_css_save.stream_seeds[i].stream; - for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++) - *(my_css_save.stream_seeds[i].orig_pipes[j]) = my_css_save.stream_seeds[i].pipes[j]; - } - } - my_css_save.mode = sh_css_mode_working; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() leave: return_void\n"); - return IA_CSS_SUCCESS; -} - -enum ia_css_err -ia_css_enable_isys_event_queue(bool enable) -{ - if (sh_css_sp_is_running()) - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - sh_css_sp_enable_isys_event_queue(enable); - return IA_CSS_SUCCESS; -} - -void *sh_css_malloc(size_t size) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_malloc() enter: size=%zu\n",size); - /* FIXME: This first test can probably go away */ - if (size == 0) - return NULL; - if (size > PAGE_SIZE) - return vmalloc(size); - return kmalloc(size, GFP_KERNEL); -} - -void *sh_css_calloc(size_t N, size_t size) -{ - void *p; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_calloc() enter: N=%zu, size=%zu\n",N,size); - - /* FIXME: this test can probably go away */ - if (size > 0) { - p = sh_css_malloc(N*size); - if (p) - memset(p, 0, size); - return p; - } - return NULL; -} - -void sh_css_free(void *ptr) -{ - if (is_vmalloc_addr(ptr)) - vfree(ptr); - else - kfree(ptr); -} - -/* For Acceleration API: Flush FW (shared buffer pointer) arguments */ -void -sh_css_flush(struct ia_css_acc_fw *fw) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n"); - if ((fw != NULL) && (my_css.flush != NULL)) - my_css.flush(fw); -} - -/* Mapping sp threads. Currently, this is done when a stream is created and - * pipelines are ready to be converted to sp pipelines. Be careful if you are - * doing it from stream_create since we could run out of sp threads due to - * allocation on inactive pipelines. */ -static enum ia_css_err -map_sp_threads(struct ia_css_stream *stream, bool map) -{ - struct ia_css_pipe *main_pipe = NULL; - struct ia_css_pipe *copy_pipe = NULL; - struct ia_css_pipe *capture_pipe = NULL; - struct ia_css_pipe *acc_pipe = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - enum ia_css_pipe_id pipe_id; - - assert(stream != NULL); - IA_CSS_ENTER_PRIVATE("stream = %p, map = %s", - stream, map ? "true" : "false"); - - if (stream == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - main_pipe = stream->last_pipe; - pipe_id = main_pipe->mode; - - ia_css_pipeline_map(main_pipe->pipe_num, map); - - switch (pipe_id) { - case IA_CSS_PIPE_ID_PREVIEW: - copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; - capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; - acc_pipe = main_pipe->pipe_settings.preview.acc_pipe; - break; - - case IA_CSS_PIPE_ID_VIDEO: - copy_pipe = main_pipe->pipe_settings.video.copy_pipe; - capture_pipe = main_pipe->pipe_settings.video.capture_pipe; - break; - - case IA_CSS_PIPE_ID_CAPTURE: - case IA_CSS_PIPE_ID_ACC: - default: - break; - } - - if (acc_pipe) { - ia_css_pipeline_map(acc_pipe->pipe_num, map); - } - - if(capture_pipe) { - ia_css_pipeline_map(capture_pipe->pipe_num, map); - } - - /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */ - if(copy_pipe) { - ia_css_pipeline_map(copy_pipe->pipe_num, map); - } - /* DH regular multi pipe - not continuous mode: map the next pipes too */ - if (!stream->config.continuous) { - int i; - for (i = 1; i < stream->num_pipes; i++) - ia_css_pipeline_map(stream->pipes[i]->pipe_num, map); - } - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -/* creates a host pipeline skeleton for all pipes in a stream. Called during - * stream_create. */ -static enum ia_css_err -create_host_pipeline_structure(struct ia_css_stream *stream) -{ - struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL; - struct ia_css_pipe *acc_pipe = NULL; - enum ia_css_pipe_id pipe_id; - struct ia_css_pipe *main_pipe = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - unsigned int copy_pipe_delay = 0, - capture_pipe_delay = 0; - - assert(stream != NULL); - IA_CSS_ENTER_PRIVATE("stream = %p", stream); - - if (stream == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - main_pipe = stream->last_pipe; - assert(main_pipe != NULL); - if (main_pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - pipe_id = main_pipe->mode; - - switch (pipe_id) { - case IA_CSS_PIPE_ID_PREVIEW: - copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; - copy_pipe_delay = main_pipe->dvs_frame_delay; - capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; - capture_pipe_delay = IA_CSS_FRAME_DELAY_0; - acc_pipe = main_pipe->pipe_settings.preview.acc_pipe; - err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay); - break; - - case IA_CSS_PIPE_ID_VIDEO: - copy_pipe = main_pipe->pipe_settings.video.copy_pipe; - copy_pipe_delay = main_pipe->dvs_frame_delay; - capture_pipe = main_pipe->pipe_settings.video.capture_pipe; - capture_pipe_delay = IA_CSS_FRAME_DELAY_0; - err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay); - break; - - case IA_CSS_PIPE_ID_CAPTURE: - capture_pipe = main_pipe; - capture_pipe_delay = main_pipe->dvs_frame_delay; - break; - - case IA_CSS_PIPE_ID_YUVPP: - err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, - main_pipe->pipe_num, main_pipe->dvs_frame_delay); - break; - - case IA_CSS_PIPE_ID_ACC: - err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay); - break; - - default: - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if ((IA_CSS_SUCCESS == err) && copy_pipe) { - err = ia_css_pipeline_create(©_pipe->pipeline, - copy_pipe->mode, - copy_pipe->pipe_num, - copy_pipe_delay); - } - - if ((IA_CSS_SUCCESS == err) && capture_pipe) { - err = ia_css_pipeline_create(&capture_pipe->pipeline, - capture_pipe->mode, - capture_pipe->pipe_num, - capture_pipe_delay); - } - - if ((IA_CSS_SUCCESS == err) && acc_pipe) { - err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode, acc_pipe->pipe_num, main_pipe->dvs_frame_delay); - } - - /* DH regular multi pipe - not continuous mode: create the next pipelines too */ - if (!stream->config.continuous) { - int i; - for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) { - main_pipe = stream->pipes[i]; - err = ia_css_pipeline_create(&main_pipe->pipeline, - main_pipe->mode, - main_pipe->pipe_num, - main_pipe->dvs_frame_delay); - } - } - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -/* creates a host pipeline for all pipes in a stream. Called during - * stream_start. */ -static enum ia_css_err -create_host_pipeline(struct ia_css_stream *stream) -{ - struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL; - struct ia_css_pipe *acc_pipe = NULL; - enum ia_css_pipe_id pipe_id; - struct ia_css_pipe *main_pipe = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - unsigned max_input_width = 0; - - IA_CSS_ENTER_PRIVATE("stream = %p", stream); - if (stream == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - main_pipe = stream->last_pipe; - pipe_id = main_pipe->mode; - - /* No continuous frame allocation for capture pipe. It uses the - * "main" pipe's frames. */ - if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) || - (pipe_id == IA_CSS_PIPE_ID_VIDEO)) { - /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY: - * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory - * based input frames) there is no continuous mode and thus no need for allocated continuous frames - * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this - * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added. - */ - if (stream->config.continuous || - (pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) { - err = alloc_continuous_frames(main_pipe, true); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - } - -#if defined(USE_INPUT_SYSTEM_VERSION_2) - /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */ - if (pipe_id != IA_CSS_PIPE_ID_ACC) { - err = allocate_mipi_frames(main_pipe, &stream->info); - if (err != IA_CSS_SUCCESS) - goto ERR; - } -#elif defined(USE_INPUT_SYSTEM_VERSION_2401) - if ((pipe_id != IA_CSS_PIPE_ID_ACC) && - (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { - err = allocate_mipi_frames(main_pipe, &stream->info); - if (err != IA_CSS_SUCCESS) - goto ERR; - } -#endif - - switch (pipe_id) { - case IA_CSS_PIPE_ID_PREVIEW: - copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; - capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; - acc_pipe = main_pipe->pipe_settings.preview.acc_pipe; - max_input_width = - main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width; - - err = create_host_preview_pipeline(main_pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - - break; - - case IA_CSS_PIPE_ID_VIDEO: - copy_pipe = main_pipe->pipe_settings.video.copy_pipe; - capture_pipe = main_pipe->pipe_settings.video.capture_pipe; - max_input_width = - main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width; - - err = create_host_video_pipeline(main_pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - - break; - - case IA_CSS_PIPE_ID_CAPTURE: - capture_pipe = main_pipe; - - break; - - case IA_CSS_PIPE_ID_YUVPP: - err = create_host_yuvpp_pipeline(main_pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - - break; - - case IA_CSS_PIPE_ID_ACC: - err = create_host_acc_pipeline(main_pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - - break; - default: - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } - if (err != IA_CSS_SUCCESS) - goto ERR; - - if(copy_pipe) { - err = create_host_copy_pipeline(copy_pipe, max_input_width, - main_pipe->continuous_frames[0]); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - if(capture_pipe) { - err = create_host_capture_pipeline(capture_pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - if (acc_pipe) { - err = create_host_acc_pipeline(acc_pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - /* DH regular multi pipe - not continuous mode: create the next pipelines too */ - if (!stream->config.continuous) { - int i; - for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) { - switch (stream->pipes[i]->mode) { - case IA_CSS_PIPE_ID_PREVIEW: - err = create_host_preview_pipeline(stream->pipes[i]); - break; - case IA_CSS_PIPE_ID_VIDEO: - err = create_host_video_pipeline(stream->pipes[i]); - break; - case IA_CSS_PIPE_ID_CAPTURE: - err = create_host_capture_pipeline(stream->pipes[i]); - break; - case IA_CSS_PIPE_ID_YUVPP: - err = create_host_yuvpp_pipeline(stream->pipes[i]); - break; - case IA_CSS_PIPE_ID_ACC: - err = create_host_acc_pipeline(stream->pipes[i]); - break; - default: - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } - if (err != IA_CSS_SUCCESS) - goto ERR; - } - } - -ERR: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -static enum ia_css_err -init_pipe_defaults(enum ia_css_pipe_mode mode, - struct ia_css_pipe *pipe, - bool copy_pipe) -{ - if (pipe == NULL) { - IA_CSS_ERROR("NULL pipe parameter"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - /* Initialize pipe to pre-defined defaults */ - *pipe = IA_CSS_DEFAULT_PIPE; - - /* TODO: JB should not be needed, but temporary backward reference */ - switch (mode) { - case IA_CSS_PIPE_MODE_PREVIEW: - pipe->mode = IA_CSS_PIPE_ID_PREVIEW; - pipe->pipe_settings.preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS; - break; - case IA_CSS_PIPE_MODE_CAPTURE: - if (copy_pipe) { - pipe->mode = IA_CSS_PIPE_ID_COPY; - } else { - pipe->mode = IA_CSS_PIPE_ID_CAPTURE; - } - pipe->pipe_settings.capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS; - break; - case IA_CSS_PIPE_MODE_VIDEO: - pipe->mode = IA_CSS_PIPE_ID_VIDEO; - pipe->pipe_settings.video = IA_CSS_DEFAULT_VIDEO_SETTINGS; - break; - case IA_CSS_PIPE_MODE_ACC: - pipe->mode = IA_CSS_PIPE_ID_ACC; - break; - case IA_CSS_PIPE_MODE_COPY: - pipe->mode = IA_CSS_PIPE_ID_CAPTURE; - break; - case IA_CSS_PIPE_MODE_YUVPP: - pipe->mode = IA_CSS_PIPE_ID_YUVPP; - pipe->pipe_settings.yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS; - break; - default: - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - return IA_CSS_SUCCESS; -} - -static void -pipe_global_init(void) -{ - uint8_t i; - - my_css.pipe_counter = 0; - for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { - my_css.all_pipes[i] = NULL; - } -} - -static enum ia_css_err -pipe_generate_pipe_num(const struct ia_css_pipe *pipe, unsigned int *pipe_number) -{ - const uint8_t INVALID_PIPE_NUM = (uint8_t)~(0); - uint8_t pipe_num = INVALID_PIPE_NUM; - uint8_t i; - - if (pipe == NULL) { - IA_CSS_ERROR("NULL pipe parameter"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - /* Assign a new pipe_num .... search for empty place */ - for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { - if (my_css.all_pipes[i] == NULL) { - /*position is reserved */ - my_css.all_pipes[i] = (struct ia_css_pipe *)pipe; - pipe_num = i; - break; - } - } - if (pipe_num == INVALID_PIPE_NUM) { - /* Max number of pipes already allocated */ - IA_CSS_ERROR("Max number of pipes already created"); - return IA_CSS_ERR_RESOURCE_EXHAUSTED; - } - - my_css.pipe_counter++; - - IA_CSS_LOG("pipe_num (%d)", pipe_num); - - *pipe_number = pipe_num; - return IA_CSS_SUCCESS; -} - -static void -pipe_release_pipe_num(unsigned int pipe_num) -{ - my_css.all_pipes[pipe_num] = NULL; - my_css.pipe_counter--; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "pipe_release_pipe_num (%d)\n", pipe_num); -} - -static enum ia_css_err -create_pipe(enum ia_css_pipe_mode mode, - struct ia_css_pipe **pipe, - bool copy_pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_pipe *me; - - if (pipe == NULL) { - IA_CSS_ERROR("NULL pipe parameter"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - me = kmalloc(sizeof(*me), GFP_KERNEL); - if (!me) - return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - - err = init_pipe_defaults(mode, me, copy_pipe); - if (err != IA_CSS_SUCCESS) { - kfree(me); - return err; - } - - err = pipe_generate_pipe_num(me, &(me->pipe_num)); - if (err != IA_CSS_SUCCESS) { - kfree(me); - return err; - } - - *pipe = me; - return IA_CSS_SUCCESS; -} - -struct ia_css_pipe * -find_pipe_by_num(uint32_t pipe_num) -{ - unsigned int i; - for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++){ - if (my_css.all_pipes[i] && - ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) { - return my_css.all_pipes[i]; - } - } - return NULL; -} - -static void sh_css_pipe_free_acc_binaries ( - struct ia_css_pipe *pipe) -{ - struct ia_css_pipeline *pipeline; - struct ia_css_pipeline_stage *stage; - - assert(pipe != NULL); - if (pipe == NULL) { - IA_CSS_ERROR("NULL input pointer"); - return; - } - pipeline = &pipe->pipeline; - - /* loop through the stages and unload them */ - for (stage = pipeline->stages; stage; stage = stage->next) { - struct ia_css_fw_info *firmware = (struct ia_css_fw_info *) - stage->firmware; - if (firmware) - ia_css_pipe_unload_extension(pipe, firmware); - } -} - -enum ia_css_err -ia_css_pipe_destroy(struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - IA_CSS_ENTER("pipe = %p", pipe); - - if (pipe == NULL) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if (pipe->stream != NULL) { - IA_CSS_LOG("ia_css_stream_destroy not called!"); - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - switch (pipe->config.mode) { - case IA_CSS_PIPE_MODE_PREVIEW: - /* need to take into account that this function is also called - on the internal copy pipe */ - if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) { - ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES, - pipe->continuous_frames); - ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES, - pipe->cont_md_buffers); - if (pipe->pipe_settings.preview.copy_pipe) { - err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_destroy(): " - "destroyed internal copy pipe err=%d\n", err); - } - } - break; - case IA_CSS_PIPE_MODE_VIDEO: - if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) { - ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES, - pipe->continuous_frames); - ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES, - pipe->cont_md_buffers); - if (pipe->pipe_settings.video.copy_pipe) { - err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_destroy(): " - "destroyed internal copy pipe err=%d\n", err); - } - } -#ifndef ISP2401 - ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames); -#else - ia_css_frame_free_multiple(NUM_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames); -#endif - ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.video.delay_frames); - break; - case IA_CSS_PIPE_MODE_CAPTURE: - ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.capture.delay_frames); - break; - case IA_CSS_PIPE_MODE_ACC: - sh_css_pipe_free_acc_binaries(pipe); - break; - case IA_CSS_PIPE_MODE_COPY: - break; - case IA_CSS_PIPE_MODE_YUVPP: - break; - } - - sh_css_params_free_gdc_lut(pipe->scaler_pp_lut); - pipe->scaler_pp_lut = mmgr_NULL; - - my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL; - sh_css_pipe_free_shading_table(pipe); - - ia_css_pipeline_destroy(&pipe->pipeline); - pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe)); - - /* Temporarily, not every sh_css_pipe has an acc_extension. */ - if (pipe->config.acc_extension) { - ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension); - } - kfree(pipe); - IA_CSS_LEAVE("err = %d", err); - return err; -} - -void -ia_css_uninit(void) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n"); -#if WITH_PC_MONITORING - sh_css_print("PC_MONITORING: %s() -- started\n", __func__); - print_pc_histogram(); -#endif - - sh_css_params_free_default_gdc_lut(); - - - /* TODO: JB: implement decent check and handling of freeing mipi frames */ - //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed - /* cleanup generic data */ - sh_css_params_uninit(); - ia_css_refcount_uninit(); - - ia_css_rmgr_uninit(); - -#if !defined(HAS_NO_INPUT_FORMATTER) - /* needed for reprogramming the inputformatter after power cycle of css */ - ifmtr_set_if_blocking_mode_reset = true; -#endif - - if (!fw_explicitly_loaded) { - ia_css_unload_firmware(); - } - ia_css_spctrl_unload_fw(SP0_ID); - sh_css_sp_set_sp_running(false); -#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) - /* check and free any remaining mipi frames */ - free_mipi_frames(NULL); -#endif - - sh_css_sp_reset_global_vars(); - -#if !defined(HAS_NO_INPUT_SYSTEM) - ia_css_isys_uninit(); -#endif - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n"); -} - -#if defined(HAS_IRQ_MAP_VERSION_2) -enum ia_css_err ia_css_irq_translate( - unsigned int *irq_infos) -{ - virq_id_t irq; - enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs; - unsigned int infos = 0; - -/* irq_infos can be NULL, but that would make the function useless */ -/* assert(irq_infos != NULL); */ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() enter: irq_infos=%p\n",irq_infos); - - while (status == hrt_isp_css_irq_status_more_irqs) { - status = virq_get_channel_id(&irq); - if (status == hrt_isp_css_irq_status_error) - return IA_CSS_ERR_INTERNAL_ERROR; - -#if WITH_PC_MONITORING - sh_css_print("PC_MONITORING: %s() irq = %d, " - "sh_binary_running set to 0\n", __func__, irq); - sh_binary_running = 0 ; -#endif - - switch (irq) { - case virq_sp: - /* When SP goes to idle, info is available in the - * event queue. */ - infos |= IA_CSS_IRQ_INFO_EVENTS_READY; - break; - case virq_isp: - break; -#if !defined(HAS_NO_INPUT_SYSTEM) - case virq_isys_sof: - infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF; - break; - case virq_isys_eof: - infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF; - break; - case virq_isys_csi: - infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR; - break; -#endif -#if !defined(HAS_NO_INPUT_FORMATTER) - case virq_ifmt0_id: - infos |= IA_CSS_IRQ_INFO_IF_ERROR; - break; -#endif - case virq_dma: - infos |= IA_CSS_IRQ_INFO_DMA_ERROR; - break; - case virq_sw_pin_0: - infos |= sh_css_get_sw_interrupt_value(0); - break; - case virq_sw_pin_1: - infos |= sh_css_get_sw_interrupt_value(1); - /* pqiao TODO: also assumption here */ - break; - default: - break; - } - } - - if (irq_infos) - *irq_infos = infos; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() " - "leave: irq_infos=%u\n", infos); - - return IA_CSS_SUCCESS; -} - -enum ia_css_err ia_css_irq_enable( - enum ia_css_irq_info info, - bool enable) -{ - virq_id_t irq = N_virq_id; - IA_CSS_ENTER("info=%d, enable=%d", info, enable); - - switch (info) { -#if !defined(HAS_NO_INPUT_FORMATTER) - case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF: - irq = virq_isys_sof; - break; - case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF: - irq = virq_isys_eof; - break; - case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR: - irq = virq_isys_csi; - break; -#endif -#if !defined(HAS_NO_INPUT_FORMATTER) - case IA_CSS_IRQ_INFO_IF_ERROR: - irq = virq_ifmt0_id; - break; -#endif - case IA_CSS_IRQ_INFO_DMA_ERROR: - irq = virq_dma; - break; - case IA_CSS_IRQ_INFO_SW_0: - irq = virq_sw_pin_0; - break; - case IA_CSS_IRQ_INFO_SW_1: - irq = virq_sw_pin_1; - break; - default: - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - cnd_virq_enable_channel(irq, enable); - - IA_CSS_LEAVE_ERR(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - -#else -#error "sh_css.c: IRQ MAP must be one of \ - {IRQ_MAP_VERSION_2}" -#endif - -static unsigned int -sh_css_get_sw_interrupt_value(unsigned int irq) -{ - unsigned int irq_value; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_get_sw_interrupt_value() enter: irq=%d\n",irq); - irq_value = sh_css_sp_get_sw_interrupt_value(irq); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n",irq_value); - return irq_value; -} - -/* configure and load the copy binary, the next binary is used to - determine whether the copy binary needs to do left padding. */ -static enum ia_css_err load_copy_binary( - struct ia_css_pipe *pipe, - struct ia_css_binary *copy_binary, - struct ia_css_binary *next_binary) -{ - struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info; - unsigned int left_padding; - enum ia_css_err err; - struct ia_css_binary_descr copy_descr; - - /* next_binary can be NULL */ - assert(pipe != NULL); - assert(copy_binary != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "load_copy_binary() enter:\n"); - - if (next_binary != NULL) { - copy_out_info = next_binary->in_frame_info; - left_padding = next_binary->left_padding; - } else { - copy_out_info = pipe->output_info[0]; - copy_vf_info = pipe->vf_output_info[0]; - ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); - left_padding = 0; - } - - ia_css_pipe_get_copy_binarydesc(pipe, ©_descr, - ©_in_info, ©_out_info, (next_binary != NULL) ? NULL : NULL/*TODO: ©_vf_info*/); - err = ia_css_binary_find(©_descr, copy_binary); - if (err != IA_CSS_SUCCESS) - return err; - copy_binary->left_padding = left_padding; - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -alloc_continuous_frames( - struct ia_css_pipe *pipe, bool init_time) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_frame_info ref_info; - enum ia_css_pipe_id pipe_id; - bool continuous; - unsigned int i, idx; - unsigned int num_frames; - struct ia_css_pipe *capture_pipe = NULL; - - IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time); - - if ((pipe == NULL) || (pipe->stream == NULL)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - pipe_id = pipe->mode; - continuous = pipe->stream->config.continuous; - - if (continuous) { - if (init_time) { - num_frames = pipe->stream->config.init_num_cont_raw_buf; - pipe->stream->continuous_pipe = pipe; - } else - num_frames = pipe->stream->config.target_num_cont_raw_buf; - } else { - num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES; - } - - if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) { - ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info; - } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) { - ref_info = pipe->pipe_settings.video.video_binary.in_frame_info; - } - else { - /* should not happen */ - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - -#if defined(USE_INPUT_SYSTEM_VERSION_2401) - /* For CSI2+, the continuous frame will hold the full input frame */ - ref_info.res.width = pipe->stream->config.input_config.input_res.width; - ref_info.res.height = pipe->stream->config.input_config.input_res.height; - - /* Ensure padded width is aligned for 2401 */ - ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS); -#endif - -#if !defined(HAS_NO_PACKED_RAW_PIXELS) - if (pipe->stream->config.pack_raw_pixels) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n"); - ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED; - } else -#endif - { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n"); - ref_info.format = IA_CSS_FRAME_FORMAT_RAW; - } - - /* Write format back to binary */ - if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) { - pipe->pipe_settings.preview.preview_binary.in_frame_info.format = ref_info.format; - capture_pipe = pipe->pipe_settings.preview.capture_pipe; - } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) { - pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format; - capture_pipe = pipe->pipe_settings.video.capture_pipe; - } else { - /* should not happen */ - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - - if (init_time) - idx = 0; - else - idx = pipe->stream->config.init_num_cont_raw_buf; - - for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) { - /* free previous frame */ - if (pipe->continuous_frames[i]) { - ia_css_frame_free(pipe->continuous_frames[i]); - pipe->continuous_frames[i] = NULL; - } - /* free previous metadata buffer */ - ia_css_metadata_free(pipe->cont_md_buffers[i]); - pipe->cont_md_buffers[i] = NULL; - - /* check if new frame needed */ - if (i < num_frames) { - /* allocate new frame */ - err = ia_css_frame_allocate_from_info( - &pipe->continuous_frames[i], - &ref_info); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - /* allocate metadata buffer */ - pipe->cont_md_buffers[i] = ia_css_metadata_allocate( - &pipe->stream->info.metadata_info); - } - } - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - -enum ia_css_err -ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) -{ - if (stream == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - return alloc_continuous_frames(stream->continuous_pipe, false); -} - -static enum ia_css_err -load_preview_binaries(struct ia_css_pipe *pipe) -{ - struct ia_css_frame_info prev_in_info, - prev_bds_out_info, - prev_out_info, - prev_vf_info; - struct ia_css_binary_descr preview_descr; - bool online; - enum ia_css_err err = IA_CSS_SUCCESS; - bool continuous, need_vf_pp = false; - bool need_isp_copy_binary = false; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - bool sensor = false; -#endif - /* preview only have 1 output pin now */ - struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0]; - struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->stream != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW); - - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#endif - - if (mycs->preview_binary.info) - return IA_CSS_SUCCESS; - - err = ia_css_util_check_input(&pipe->stream->config, false, false); - if (err != IA_CSS_SUCCESS) - return err; - err = ia_css_frame_check_info(pipe_out_info); - if (err != IA_CSS_SUCCESS) - return err; - - /* Note: the current selection of vf_pp binary and - * parameterization of the preview binary contains a few pieces - * of hardcoded knowledge. This needs to be cleaned up such that - * the binary selection becomes more generic. - * The vf_pp binary is needed if one or more of the following features - * are required: - * 1. YUV downscaling. - * 2. Digital zoom. - * 3. An output format that is not supported by the preview binary. - * In practice this means something other than yuv_line or nv12. - * The decision if the vf_pp binary is needed for YUV downscaling is - * made after the preview binary selection, since some preview binaries - * can perform the requested YUV downscaling. - * */ - need_vf_pp = pipe->config.enable_dz; - need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE && - !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 || - pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 || - pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY); - - /* Preview step 1 */ - if (pipe->vf_yuv_ds_input_info.res.width) - prev_vf_info = pipe->vf_yuv_ds_input_info; - else - prev_vf_info = *pipe_out_info; - /* If vf_pp is needed, then preview must output yuv_line. - * The exception is when vf_pp is manually disabled, that is only - * used in combination with a pipeline extension that requires - * yuv_line as input. - * */ - if (need_vf_pp) - ia_css_frame_info_set_format(&prev_vf_info, - IA_CSS_FRAME_FORMAT_YUV_LINE); - - err = ia_css_pipe_get_preview_binarydesc( - pipe, - &preview_descr, - &prev_in_info, - &prev_bds_out_info, - &prev_out_info, - &prev_vf_info); - if (err != IA_CSS_SUCCESS) - return err; - err = ia_css_binary_find(&preview_descr, &mycs->preview_binary); - if (err != IA_CSS_SUCCESS) - return err; - -#ifdef ISP2401 - /* The delay latency determines the number of invalid frames after - * a stream is started. */ - pipe->num_invalid_frames = pipe->dvs_frame_delay; - pipe->info.num_invalid_frames = pipe->num_invalid_frames; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n", - pipe->num_invalid_frames, pipe->dvs_frame_delay); - -#endif - /* The vf_pp binary is needed when (further) YUV downscaling is required */ - need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width; - need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height; - - /* When vf_pp is needed, then the output format of the selected - * preview binary must be yuv_line. If this is not the case, - * then the preview binary selection is done again. - */ - if (need_vf_pp && - (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) { - - /* Preview step 2 */ - if (pipe->vf_yuv_ds_input_info.res.width) - prev_vf_info = pipe->vf_yuv_ds_input_info; - else - prev_vf_info = *pipe_out_info; - - ia_css_frame_info_set_format(&prev_vf_info, - IA_CSS_FRAME_FORMAT_YUV_LINE); - - err = ia_css_pipe_get_preview_binarydesc( - pipe, - &preview_descr, - &prev_in_info, - &prev_bds_out_info, - &prev_out_info, - &prev_vf_info); - if (err != IA_CSS_SUCCESS) - return err; - err = ia_css_binary_find(&preview_descr, - &mycs->preview_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - - if (need_vf_pp) { - struct ia_css_binary_descr vf_pp_descr; - - /* Viewfinder post-processing */ - ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr, - &mycs->preview_binary.out_frame_info[0], - pipe_out_info); - err = ia_css_binary_find(&vf_pp_descr, - &mycs->vf_pp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* When the input system is 2401, only the Direct Sensor Mode - * Offline Preview uses the ISP copy binary. - */ - need_isp_copy_binary = !online && sensor; -#else -#ifndef ISP2401 - need_isp_copy_binary = !online && !continuous; -#else - /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY: - * This is typical the case with SkyCam (which has no input system) but it also applies to all cases - * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical - * copies sensor data to DDR) does not have much use. - */ - need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY); -#endif -#endif - - /* Copy */ - if (need_isp_copy_binary) { - err = load_copy_binary(pipe, - &mycs->copy_binary, - &mycs->preview_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - - if (pipe->shading_table) { - ia_css_shading_table_free(pipe->shading_table); - pipe->shading_table = NULL; - } - - return IA_CSS_SUCCESS; -} - -static void -ia_css_binary_unload(struct ia_css_binary *binary) -{ - ia_css_binary_destroy_isp_parameters(binary); -} - -static enum ia_css_err -unload_preview_binaries(struct ia_css_pipe *pipe) -{ - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - - if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary); - ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary); - ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary); - - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - -static const struct ia_css_fw_info *last_output_firmware( - const struct ia_css_fw_info *fw) -{ - const struct ia_css_fw_info *last_fw = NULL; -/* fw can be NULL */ - IA_CSS_ENTER_LEAVE_PRIVATE(""); - - for (; fw; fw = fw->next) { - const struct ia_css_fw_info *info = fw; - if (info->info.isp.sp.enable.output) - last_fw = fw; - } - return last_fw; -} - -static enum ia_css_err add_firmwares( - struct ia_css_pipeline *me, - struct ia_css_binary *binary, - const struct ia_css_fw_info *fw, - const struct ia_css_fw_info *last_fw, - unsigned int binary_mode, - struct ia_css_frame *in_frame, - struct ia_css_frame *out_frame, - struct ia_css_frame *vf_frame, - struct ia_css_pipeline_stage **my_stage, - struct ia_css_pipeline_stage **vf_stage) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_pipeline_stage *extra_stage = NULL; - struct ia_css_pipeline_stage_desc stage_desc; - -/* all args can be NULL ??? */ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "add_firmwares() enter:\n"); - - for (; fw; fw = fw->next) { - struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL}; - struct ia_css_frame *in = NULL; - struct ia_css_frame *vf = NULL; - if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) { - out[0] = out_frame; - } - if (fw->info.isp.sp.enable.in_frame != 0) { - in = in_frame; - } - if (fw->info.isp.sp.enable.out_frame != 0) { - vf = vf_frame; - } - ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary, - out, in, vf, fw, binary_mode); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - &extra_stage); - if (err != IA_CSS_SUCCESS) - return err; - if (fw->info.isp.sp.enable.output != 0) - in_frame = extra_stage->args.out_frame[0]; - if (my_stage && !*my_stage && extra_stage) - *my_stage = extra_stage; - if (vf_stage && !*vf_stage && extra_stage && - fw->info.isp.sp.enable.vf_veceven) - *vf_stage = extra_stage; - } - return err; -} - -static enum ia_css_err add_vf_pp_stage( - struct ia_css_pipe *pipe, - struct ia_css_frame *in_frame, - struct ia_css_frame *out_frame, - struct ia_css_binary *vf_pp_binary, - struct ia_css_pipeline_stage **vf_pp_stage) -{ - - struct ia_css_pipeline *me = NULL; - const struct ia_css_fw_info *last_fw = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; - struct ia_css_pipeline_stage_desc stage_desc; - -/* out_frame can be NULL ??? */ - - if (pipe == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - if (in_frame == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - if (vf_pp_binary == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - if (vf_pp_stage == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - ia_css_pipe_util_create_output_frames(out_frames); - me = &pipe->pipeline; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "add_vf_pp_stage() enter:\n"); - - *vf_pp_stage = NULL; - - last_fw = last_output_firmware(pipe->vf_stage); - if (!pipe->extra_config.disable_vf_pp) { - if (last_fw) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary, - out_frames, in_frame, NULL); - } else{ - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary, - out_frames, in_frame, NULL); - } - err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage); - if (err != IA_CSS_SUCCESS) - return err; - in_frame = (*vf_pp_stage)->args.out_frame[0]; - } - err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw, - IA_CSS_BINARY_MODE_VF_PP, - in_frame, out_frame, NULL, - vf_pp_stage, NULL); - return err; -} - -static enum ia_css_err add_yuv_scaler_stage( - struct ia_css_pipe *pipe, - struct ia_css_pipeline *me, - struct ia_css_frame *in_frame, - struct ia_css_frame *out_frame, - struct ia_css_frame *internal_out_frame, - struct ia_css_binary *yuv_scaler_binary, - struct ia_css_pipeline_stage **pre_vf_pp_stage) -{ - const struct ia_css_fw_info *last_fw; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_frame *vf_frame = NULL; - struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; - struct ia_css_pipeline_stage_desc stage_desc; - - /* out_frame can be NULL ??? */ - assert(in_frame != NULL); - assert(pipe != NULL); - assert(me != NULL); - assert(yuv_scaler_binary != NULL); - assert(pre_vf_pp_stage != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "add_yuv_scaler_stage() enter:\n"); - - *pre_vf_pp_stage = NULL; - ia_css_pipe_util_create_output_frames(out_frames); - - last_fw = last_output_firmware(pipe->output_stage); - - if(last_fw) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, - yuv_scaler_binary, out_frames, in_frame, vf_frame); - } else { - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); - ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, - yuv_scaler_binary, out_frames, in_frame, vf_frame); - } - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - pre_vf_pp_stage); - if (err != IA_CSS_SUCCESS) - return err; - in_frame = (*pre_vf_pp_stage)->args.out_frame[0]; - - err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw, - IA_CSS_BINARY_MODE_CAPTURE_PP, - in_frame, out_frame, vf_frame, - NULL, pre_vf_pp_stage); - /* If a firmware produce vf_pp output, we set that as vf_pp input */ - (*pre_vf_pp_stage)->args.vf_downscale_log2 = yuv_scaler_binary->vf_downscale_log2; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "add_yuv_scaler_stage() leave:\n"); - return err; -} - -static enum ia_css_err add_capture_pp_stage( - struct ia_css_pipe *pipe, - struct ia_css_pipeline *me, - struct ia_css_frame *in_frame, - struct ia_css_frame *out_frame, - struct ia_css_binary *capture_pp_binary, - struct ia_css_pipeline_stage **capture_pp_stage) -{ - const struct ia_css_fw_info *last_fw = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_frame *vf_frame = NULL; - struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; - struct ia_css_pipeline_stage_desc stage_desc; - - /* out_frame can be NULL ??? */ - assert(in_frame != NULL); - assert(pipe != NULL); - assert(me != NULL); - assert(capture_pp_binary != NULL); - assert(capture_pp_stage != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "add_capture_pp_stage() enter:\n"); - - *capture_pp_stage = NULL; - ia_css_pipe_util_create_output_frames(out_frames); - - last_fw = last_output_firmware(pipe->output_stage); - err = ia_css_frame_allocate_from_info(&vf_frame, - &capture_pp_binary->vf_frame_info); - if (err != IA_CSS_SUCCESS) - return err; - if(last_fw) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, - capture_pp_binary, out_frames, NULL, vf_frame); - } else { - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, - capture_pp_binary, out_frames, NULL, vf_frame); - } - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - capture_pp_stage); - if (err != IA_CSS_SUCCESS) - return err; - err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw, - IA_CSS_BINARY_MODE_CAPTURE_PP, - in_frame, out_frame, vf_frame, - NULL, capture_pp_stage); - /* If a firmware produce vf_pp output, we set that as vf_pp input */ - if (*capture_pp_stage) { - (*capture_pp_stage)->args.vf_downscale_log2 = - capture_pp_binary->vf_downscale_log2; - } - return err; -} - -static void sh_css_setup_queues(void) -{ - const struct ia_css_fw_info *fw; - unsigned int HIVE_ADDR_host_sp_queues_initialized; - - sh_css_hmm_buffer_record_init(); - - sh_css_event_init_irq_mask(); - - fw = &sh_css_sp_fw; - HIVE_ADDR_host_sp_queues_initialized = - fw->info.sp.host_sp_queues_initialized; - - ia_css_bufq_init(); - - /* set "host_sp_queues_initialized" to "true" */ - sp_dmem_store_uint32(SP0_ID, - (unsigned int)sp_address_of(host_sp_queues_initialized), - (uint32_t)(1)); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n"); -} - -static enum ia_css_err -init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, - struct ia_css_frame *vf_frame, unsigned int idx) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - unsigned int thread_id; - enum sh_css_queue_id queue_id; - - assert(vf_frame != NULL); - - sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx); - vf_frame->contiguous = false; - vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id); - vf_frame->dynamic_queue_id = queue_id; - vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx; - - err = ia_css_frame_init_planes(vf_frame); - return err; -} - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 -static unsigned int -get_crop_lines_for_bayer_order ( - const struct ia_css_stream_config *config) -{ - assert(config != NULL); - if ((IA_CSS_BAYER_ORDER_BGGR == config->input_config.bayer_order) - || (IA_CSS_BAYER_ORDER_GBRG == config->input_config.bayer_order)) - return 1; - - return 0; -} - -static unsigned int -get_crop_columns_for_bayer_order ( - const struct ia_css_stream_config *config) -{ - assert(config != NULL); - if ((IA_CSS_BAYER_ORDER_RGGB == config->input_config.bayer_order) - || (IA_CSS_BAYER_ORDER_GBRG == config->input_config.bayer_order)) - return 1; - - return 0; -} - -/* This function is to get the sum of all extra pixels in addition to the effective - * input, it includes dvs envelop and filter run-in */ -static void get_pipe_extra_pixel(struct ia_css_pipe *pipe, - unsigned int *extra_row, unsigned int *extra_column) -{ - enum ia_css_pipe_id pipe_id = pipe->mode; - unsigned int left_cropping = 0, top_cropping = 0; - unsigned int i; - struct ia_css_resolution dvs_env = pipe->config.dvs_envelope; - - /* The dvs envelope info may not be correctly sent down via pipe config - * The check is made and the correct value is populated in the binary info - * Use this value when computing crop, else excess lines may get trimmed - */ - switch (pipe_id) { - case IA_CSS_PIPE_ID_PREVIEW: - if (pipe->pipe_settings.preview.preview_binary.info) { - left_cropping = pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping; - top_cropping = pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping; - } - dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope; - break; - case IA_CSS_PIPE_ID_VIDEO: - if (pipe->pipe_settings.video.video_binary.info) { - left_cropping = pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping; - top_cropping = pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping; - } - dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope; - break; - case IA_CSS_PIPE_ID_CAPTURE: - for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { - if (pipe->pipe_settings.capture.primary_binary[i].info) { - left_cropping += pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping; - top_cropping += pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping; - } - dvs_env.width += pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width; - dvs_env.height += pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height; - } - break; - default: - break; - } - - *extra_row = top_cropping + dvs_env.height; - *extra_column = left_cropping + dvs_env.width; -} - -void -ia_css_get_crop_offsets ( - struct ia_css_pipe *pipe, - struct ia_css_frame_info *in_frame) -{ - unsigned int row = 0; - unsigned int column = 0; - struct ia_css_resolution *input_res; - struct ia_css_resolution *effective_res; - unsigned int extra_row = 0, extra_col = 0; - unsigned int min_reqd_height, min_reqd_width; - - assert(pipe != NULL); - assert(pipe->stream != NULL); - assert(in_frame != NULL); - - IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u", - pipe, pipe->config.input_effective_res.width, - pipe->config.input_effective_res.height); - - input_res = &pipe->stream->config.input_config.input_res; -#ifndef ISP2401 - effective_res = &pipe->stream->config.input_config.effective_res; -#else - effective_res = &pipe->config.input_effective_res; -#endif - - get_pipe_extra_pixel(pipe, &extra_row, &extra_col); - - in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order; - - min_reqd_height = effective_res->height + extra_row; - min_reqd_width = effective_res->width + extra_col; - - if (input_res->height > min_reqd_height) { - row = (input_res->height - min_reqd_height) / 2; - row &= ~0x1; - } - if (input_res->width > min_reqd_width) { - column = (input_res->width - min_reqd_width) / 2; - column &= ~0x1; - } - - /* - * TODO: - * 1. Require the special support for RAW10 packed mode. - * 2. Require the special support for the online use cases. - */ - - /* ISP expects GRBG bayer order, we skip one line and/or one row - * to correct in case the input bayer order is different. - */ - column += get_crop_columns_for_bayer_order(&pipe->stream->config); - row += get_crop_lines_for_bayer_order(&pipe->stream->config); - - in_frame->crop_info.start_column = column; - in_frame->crop_info.start_line = row; - - IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row); - - return; -} -#endif - -static enum ia_css_err -init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe, - struct ia_css_frame *frame, enum ia_css_frame_format format) -{ - struct ia_css_frame *in_frame; - enum ia_css_err err = IA_CSS_SUCCESS; - unsigned int thread_id; - enum sh_css_queue_id queue_id; - - assert(frame != NULL); - in_frame = frame; - - in_frame->info.format = format; - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - if (format == IA_CSS_FRAME_FORMAT_RAW) - in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ? - IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW; -#endif - - - in_frame->info.res.width = pipe->stream->config.input_config.input_res.width; - in_frame->info.res.height = pipe->stream->config.input_config.input_res.height; - in_frame->info.raw_bit_depth = - ia_css_pipe_util_pipe_input_format_bpp(pipe); - ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0); - in_frame->contiguous = false; - in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id); - in_frame->dynamic_queue_id = queue_id; - in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - ia_css_get_crop_offsets(pipe, &in_frame->info); -#endif - err = ia_css_frame_init_planes(in_frame); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order); - - return err; -} - -static enum ia_css_err -init_out_frameinfo_defaults(struct ia_css_pipe *pipe, - struct ia_css_frame *out_frame, unsigned int idx) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - unsigned int thread_id; - enum sh_css_queue_id queue_id; - - assert(out_frame != NULL); - - sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx); - out_frame->contiguous = false; - out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id); - out_frame->dynamic_queue_id = queue_id; - out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx; - err = ia_css_frame_init_planes(out_frame); - - return err; -} - -/* Create stages for video pipe */ -static enum ia_css_err create_host_video_pipeline(struct ia_css_pipe *pipe) -{ - struct ia_css_pipeline_stage_desc stage_desc; - struct ia_css_binary *copy_binary, *video_binary, - *yuv_scaler_binary, *vf_pp_binary; - struct ia_css_pipeline_stage *copy_stage = NULL; - struct ia_css_pipeline_stage *video_stage = NULL; - struct ia_css_pipeline_stage *yuv_scaler_stage = NULL; - struct ia_css_pipeline_stage *vf_pp_stage = NULL; - struct ia_css_pipeline *me; - struct ia_css_frame *in_frame = NULL; - struct ia_css_frame *out_frame; - struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; - struct ia_css_frame *vf_frame = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - bool need_copy = false; - bool need_vf_pp = false; - bool need_yuv_pp = false; - unsigned num_output_pins; - bool need_in_frameinfo_memory = false; - - unsigned int i, num_yuv_scaler; - bool *is_output_stage = NULL; - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ia_css_pipe_util_create_output_frames(out_frames); - out_frame = &pipe->out_frame_struct; - - /* pipeline already created as part of create_host_pipeline_structure */ - me = &pipe->pipeline; - ia_css_pipeline_clean(me); - - me->dvs_frame_delay = pipe->dvs_frame_delay; - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: online or continuous - */ - need_in_frameinfo_memory = !(pipe->stream->config.online || pipe->stream->config.continuous); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif - - /* Construct in_frame info (only in case we have dynamic input */ - if (need_in_frameinfo_memory) { - in_frame = &pipe->in_frame_struct; - err = init_in_frameinfo_memory_defaults(pipe, in_frame, IA_CSS_FRAME_FORMAT_RAW); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - out_frame->data = 0; - err = init_out_frameinfo_defaults(pipe, out_frame, 0); - if (err != IA_CSS_SUCCESS) - goto ERR; - - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { - vf_frame = &pipe->vf_frame_struct; - vf_frame->data = 0; - err = init_vf_frameinfo_defaults(pipe, vf_frame, 0); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - copy_binary = &pipe->pipe_settings.video.copy_binary; - video_binary = &pipe->pipe_settings.video.video_binary; - vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary; - num_output_pins = video_binary->info->num_output_pins; - - yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary; - num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler; - is_output_stage = pipe->pipe_settings.video.is_output_stage; - - need_copy = (copy_binary != NULL && copy_binary->info != NULL); - need_vf_pp = (vf_pp_binary != NULL && vf_pp_binary->info != NULL); - need_yuv_pp = (yuv_scaler_binary != NULL && yuv_scaler_binary->info != NULL); - - if (need_copy) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, - out_frames, NULL, NULL); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - ©_stage); - if (err != IA_CSS_SUCCESS) - goto ERR; - in_frame = me->stages->args.out_frame[0]; - } else if (pipe->stream->config.continuous) { -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* When continuous is enabled, configure in_frame with the - * last pipe, which is the copy pipe. - */ - in_frame = pipe->stream->last_pipe->continuous_frames[0]; -#else - in_frame = pipe->continuous_frames[0]; -#endif - } - - ia_css_pipe_util_set_output_frames(out_frames, 0, need_yuv_pp ? NULL : out_frame); - - /* when the video binary supports a second output pin, - it can directly produce the vf_frame. */ - if(need_vf_pp) { - ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary, - out_frames, in_frame, NULL); - } else { - ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary, - out_frames, in_frame, vf_frame); - } - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - &video_stage); - if (err != IA_CSS_SUCCESS) - goto ERR; - - /* If we use copy iso video, the input must be yuv iso raw */ - if(video_stage) { - video_stage->args.copy_vf = - video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY; - video_stage->args.copy_output = video_stage->args.copy_vf; - } - - /* when the video binary supports only 1 output pin, vf_pp is needed to - produce the vf_frame.*/ - if (need_vf_pp && video_stage) { - in_frame = video_stage->args.out_vf_frame; - err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary, - &vf_pp_stage); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - if (video_stage) { - int frm; -#ifndef ISP2401 - for (frm = 0; frm < NUM_VIDEO_TNR_FRAMES; frm++) { -#else - for (frm = 0; frm < NUM_TNR_FRAMES; frm++) { -#endif - video_stage->args.tnr_frames[frm] = - pipe->pipe_settings.video.tnr_frames[frm]; - } - for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) { - video_stage->args.delay_frames[frm] = - pipe->pipe_settings.video.delay_frames[frm]; - } - } - - /* Append Extension on Video out, if enabled */ - if (!need_vf_pp && video_stage && pipe->config.acc_extension && - (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) - { - struct ia_css_frame *out = NULL; - struct ia_css_frame *in = NULL; - - if ((pipe->config.acc_extension->info.isp.sp.enable.output) && - (pipe->config.acc_extension->info.isp.sp.enable.in_frame) && - (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) { - - /* In/Out Frame mapping to support output frame extension.*/ - out = video_stage->args.out_frame[0]; - err = ia_css_frame_allocate_from_info(&in, &(pipe->output_info[0])); - if (err != IA_CSS_SUCCESS) - goto ERR; - video_stage->args.out_frame[0] = in; - } - - err = add_firmwares( me, video_binary, pipe->output_stage, - last_output_firmware(pipe->output_stage), - IA_CSS_BINARY_MODE_VIDEO, - in, out, NULL, &video_stage, NULL); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - if (need_yuv_pp && video_stage) { - struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0]; - struct ia_css_frame *tmp_out_frame = NULL; - - for (i = 0; i < num_yuv_scaler; i++) { - if (is_output_stage[i] == true) { - tmp_out_frame = out_frame; - } else { - tmp_out_frame = NULL; - } - err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, - NULL, - &yuv_scaler_binary[i], - &yuv_scaler_stage); - - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - /* we use output port 1 as internal output port */ - if (yuv_scaler_stage) - tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; - } - } - - pipe->pipeline.acquire_isp_each_stage = false; - ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); - -ERR: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -static enum ia_css_err -create_host_acc_pipeline(struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - const struct ia_css_fw_info *fw; - unsigned int i; - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - if ((pipe == NULL) || (pipe->stream == NULL)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - pipe->pipeline.num_execs = pipe->config.acc_num_execs; - /* Reset pipe_qos_config to default disable all QOS extension stages */ - if (pipe->config.acc_extension) - pipe->pipeline.pipe_qos_config = 0; - - fw = pipe->vf_stage; - for (i = 0; fw; fw = fw->next){ - err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - for (i=0; i<pipe->config.num_acc_stages; i++) { - struct ia_css_fw_info *fw = pipe->config.acc_stages[i]; - err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); - -ERR: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -/* Create stages for preview */ -static enum ia_css_err -create_host_preview_pipeline(struct ia_css_pipe *pipe) -{ - struct ia_css_pipeline_stage *copy_stage = NULL; - struct ia_css_pipeline_stage *preview_stage = NULL; - struct ia_css_pipeline_stage *vf_pp_stage = NULL; - struct ia_css_pipeline_stage_desc stage_desc; - struct ia_css_pipeline *me = NULL; - struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL; - struct ia_css_frame *in_frame = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_frame *out_frame; - struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; - bool need_in_frameinfo_memory = false; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - bool sensor = false; - bool buffered_sensor = false; - bool online = false; - bool continuous = false; -#endif - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - - ia_css_pipe_util_create_output_frames(out_frames); - /* pipeline already created as part of create_host_pipeline_structure */ - me = &pipe->pipeline; - ia_css_pipeline_clean(me); - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Preview - * - Buffered Sensor Mode Online Preview - * - Direct Sensor Mode Continuous Preview - * - Buffered Sensor Mode Continuous Preview - */ - sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); - buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif - if (need_in_frameinfo_memory) { - err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW); - if (err != IA_CSS_SUCCESS) - goto ERR; - - in_frame = &me->in_frame; - } else { - in_frame = NULL; - } - - err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); - if (err != IA_CSS_SUCCESS) - goto ERR; - out_frame = &me->out_frame[0]; - - copy_binary = &pipe->pipe_settings.preview.copy_binary; - preview_binary = &pipe->pipe_settings.preview.preview_binary; - if (pipe->pipe_settings.preview.vf_pp_binary.info) - vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary; - - if (pipe->pipe_settings.preview.copy_binary.info) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, - out_frames, NULL, NULL); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - ©_stage); - if (err != IA_CSS_SUCCESS) - goto ERR; - in_frame = me->stages->args.out_frame[0]; -#ifndef ISP2401 - } else { -#else - } else if (pipe->stream->config.continuous) { -#endif -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* When continuous is enabled, configure in_frame with the - * last pipe, which is the copy pipe. - */ - if (continuous || !online){ - in_frame = pipe->stream->last_pipe->continuous_frames[0]; - } -#else - in_frame = pipe->continuous_frames[0]; -#endif - } - - if (vf_pp_binary) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, - out_frames, in_frame, NULL); - } else { - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, - out_frames, in_frame, NULL); - } - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - &preview_stage); - if (err != IA_CSS_SUCCESS) - goto ERR; - /* If we use copy iso preview, the input must be yuv iso raw */ - preview_stage->args.copy_vf = - preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY; - preview_stage->args.copy_output = !preview_stage->args.copy_vf; - if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) { - /* in case of copy, use the vf frame as output frame */ - preview_stage->args.out_vf_frame = - preview_stage->args.out_frame[0]; - } - if (vf_pp_binary) { - if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY) - in_frame = preview_stage->args.out_vf_frame; - else - in_frame = preview_stage->args.out_frame[0]; - err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary, - &vf_pp_stage); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - - pipe->pipeline.acquire_isp_each_stage = false; - ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); - -ERR: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -static void send_raw_frames(struct ia_css_pipe *pipe) -{ - if (pipe->stream->config.continuous) { - unsigned int i; - - sh_css_update_host2sp_cont_num_raw_frames - (pipe->stream->config.init_num_cont_raw_buf, true); - sh_css_update_host2sp_cont_num_raw_frames - (pipe->stream->config.target_num_cont_raw_buf, false); - - /* Hand-over all the SP-internal buffers */ - for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) { - sh_css_update_host2sp_offline_frame(i, - pipe->continuous_frames[i], pipe->cont_md_buffers[i]); - } - } - - return; -} - -static enum ia_css_err -preview_start(struct ia_css_pipe *pipe) -{ - struct ia_css_pipeline *me ; - struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_pipe *copy_pipe, *capture_pipe; - struct ia_css_pipe *acc_pipe; - enum sh_css_pipe_config_override copy_ovrd; - enum ia_css_input_mode preview_pipe_input_mode; - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - me = &pipe->pipeline; - - preview_pipe_input_mode = pipe->stream->config.mode; - - copy_pipe = pipe->pipe_settings.preview.copy_pipe; - capture_pipe = pipe->pipe_settings.preview.capture_pipe; - acc_pipe = pipe->pipe_settings.preview.acc_pipe; - - copy_binary = &pipe->pipe_settings.preview.copy_binary; - preview_binary = &pipe->pipe_settings.preview.preview_binary; - if (pipe->pipe_settings.preview.vf_pp_binary.info) - vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary; - - sh_css_metrics_start_frame(); - -#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) - /* multi stream video needs mipi buffers */ - err = send_mipi_frames(pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; -#endif - send_raw_frames(pipe); - - { - unsigned int thread_id; - - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - copy_ovrd = 1 << thread_id; - - if (pipe->stream->cont_capt) { - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id); - copy_ovrd |= 1 << thread_id; - } - } - - /* Construct and load the copy pipe */ - if (pipe->stream->config.continuous) { - sh_css_sp_init_pipeline(©_pipe->pipeline, - IA_CSS_PIPE_ID_COPY, - (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe), - false, - pipe->stream->config.pixels_per_clock == 2, false, - false, pipe->required_bds_factor, - copy_ovrd, - pipe->stream->config.mode, - &pipe->stream->config.metadata_config, -#ifndef ISP2401 - &pipe->stream->info.metadata_info -#else - &pipe->stream->info.metadata_info, -#endif -#if !defined(HAS_NO_INPUT_SYSTEM) -#ifndef ISP2401 - , pipe->stream->config.source.port.port -#else - pipe->stream->config.source.port.port, -#endif -#endif -#ifndef ISP2401 - ); -#else - &pipe->config.internal_frame_origin_bqs_on_sctbl, - pipe->stream->isp_params_configs); -#endif - - /* make the preview pipe start with mem mode input, copy handles - the actual mode */ - preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; - } - - /* Construct and load the capture pipe */ - if (pipe->stream->cont_capt) { - sh_css_sp_init_pipeline(&capture_pipe->pipeline, - IA_CSS_PIPE_ID_CAPTURE, - (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe), - capture_pipe->config.default_capture_config.enable_xnr != 0, - capture_pipe->stream->config.pixels_per_clock == 2, - true, /* continuous */ - false, /* offline */ - capture_pipe->required_bds_factor, - 0, - IA_CSS_INPUT_MODE_MEMORY, - &pipe->stream->config.metadata_config, -#ifndef ISP2401 - &pipe->stream->info.metadata_info -#else - &pipe->stream->info.metadata_info, -#endif -#if !defined(HAS_NO_INPUT_SYSTEM) -#ifndef ISP2401 - , (enum mipi_port_id)0 -#else - (enum mipi_port_id)0, -#endif -#endif -#ifndef ISP2401 - ); -#else - &capture_pipe->config.internal_frame_origin_bqs_on_sctbl, - capture_pipe->stream->isp_params_configs); -#endif - } - - if (acc_pipe) { - sh_css_sp_init_pipeline(&acc_pipe->pipeline, - IA_CSS_PIPE_ID_ACC, - (uint8_t) ia_css_pipe_get_pipe_num(acc_pipe), - false, - pipe->stream->config.pixels_per_clock == 2, - false, /* continuous */ - false, /* offline */ - pipe->required_bds_factor, - 0, - IA_CSS_INPUT_MODE_MEMORY, - NULL, -#ifndef ISP2401 - NULL -#else - NULL, -#endif -#if !defined(HAS_NO_INPUT_SYSTEM) -#ifndef ISP2401 - , (enum mipi_port_id) 0 -#else - (enum mipi_port_id) 0, -#endif -#endif -#ifndef ISP2401 - ); -#else - &pipe->config.internal_frame_origin_bqs_on_sctbl, - pipe->stream->isp_params_configs); -#endif - } - - start_pipe(pipe, copy_ovrd, preview_pipe_input_mode); - -#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) -ERR: -#endif - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -enum ia_css_err -ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, - const struct ia_css_buffer *buffer) -{ - enum ia_css_err return_err = IA_CSS_SUCCESS; - unsigned int thread_id; - enum sh_css_queue_id queue_id; - struct ia_css_pipeline *pipeline; - struct ia_css_pipeline_stage *stage; - struct ia_css_rmgr_vbuf_handle p_vbuf; - struct ia_css_rmgr_vbuf_handle *h_vbuf; - struct sh_css_hmm_buffer ddr_buffer; - enum ia_css_buffer_type buf_type; - enum ia_css_pipe_id pipe_id; - bool ret_err; - - IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer); - - if ((pipe == NULL) || (buffer == NULL)) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - buf_type = buffer->type; - /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME - is removed */ -#if 0 - if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { - bool found_pipe = false; - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) && - (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) { - buf_type += i; - found_pipe = true; - break; - } - } - if (!found_pipe) - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) { - bool found_pipe = false; - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) && - (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) { - buf_type += i; - found_pipe = true; - break; - } - } - if (!found_pipe) - return IA_CSS_ERR_INVALID_ARGUMENTS; - } -#endif - pipe_id = pipe->mode; - - IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type); - - - assert(pipe_id < IA_CSS_PIPE_ID_NUM); - assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE); - if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) || - (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) || - (pipe_id >= IA_CSS_PIPE_ID_NUM)) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - - ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - if (!ret_err) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id); - if (!ret_err) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if (!sh_css_sp_is_running()) { - IA_CSS_LOG("SP is not running!"); - IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); - /* SP is not running. The queues are not valid */ - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - - - pipeline = &pipe->pipeline; - - assert(pipeline != NULL || - pipe_id == IA_CSS_PIPE_ID_COPY || - pipe_id == IA_CSS_PIPE_ID_ACC); - - assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr)); - ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL); - ddr_buffer.cookie_ptr = buffer->driver_cookie; - ddr_buffer.timing_data = buffer->timing_data; - - if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) { - if (buffer->data.stats_3a == NULL) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a); - ddr_buffer.payload.s3a = *buffer->data.stats_3a; - } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) { - if (buffer->data.stats_dvs == NULL) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs); - ddr_buffer.payload.dis = *buffer->data.stats_dvs; - } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) { - if (buffer->data.metadata == NULL) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata); - ddr_buffer.payload.metadata = *buffer->data.metadata; - } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)) { - if (buffer->data.frame == NULL) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame); - ddr_buffer.payload.frame.frame_data = buffer->data.frame->data; - ddr_buffer.payload.frame.flashed = 0; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n", - buf_type, buffer->data.frame->data); - - -#if CONFIG_ON_FRAME_ENQUEUE() - return_err = set_config_on_frame_enqueue( - &buffer->data.frame->info, - &ddr_buffer.payload.frame); - if (IA_CSS_SUCCESS != return_err) { - IA_CSS_LEAVE_ERR(return_err); - return return_err; - } -#endif - } - - /* start of test for using rmgr for acq/rel memory */ - p_vbuf.vptr = 0; - p_vbuf.count = 0; - p_vbuf.size = sizeof(struct sh_css_hmm_buffer); - h_vbuf = &p_vbuf; - /* TODO: change next to correct pool for optimization */ - ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf); - - assert(h_vbuf != NULL); - assert(h_vbuf->vptr != 0x0); - - if ((h_vbuf == NULL) || (h_vbuf->vptr == 0x0)) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - - mmgr_store(h_vbuf->vptr, - (void *)(&ddr_buffer), - sizeof(struct sh_css_hmm_buffer)); - if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) - || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) - || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) { - if (pipeline == NULL) { - ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf); - IA_CSS_LOG("pipeline is empty!"); - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - - for (stage = pipeline->stages; stage; stage = stage->next) { - /* The SP will read the params - after it got empty 3a and dis */ - if (STATS_ENABLED(stage)) { - /* there is a stage that needs it */ - return_err = ia_css_bufq_enqueue_buffer(thread_id, - queue_id, - (uint32_t)h_vbuf->vptr); - } - } - } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME) - || (buf_type == IA_CSS_BUFFER_TYPE_METADATA)) { - - return_err = ia_css_bufq_enqueue_buffer(thread_id, - queue_id, - (uint32_t)h_vbuf->vptr); -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) - if ((return_err == IA_CSS_SUCCESS) && (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME == buf_type)) { - IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d", - ddr_buffer.payload.frame.frame_data, - queue_id, thread_id); - } -#endif - - } - - if (return_err == IA_CSS_SUCCESS) { - if (sh_css_hmm_buffer_record_acquire( - h_vbuf, buf_type, - HOST_ADDRESS(ddr_buffer.kernel_ptr))) { - IA_CSS_LOG("send vbuf=%p", h_vbuf); - } else { - return_err = IA_CSS_ERR_INTERNAL_ERROR; - IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n"); - } - } - - /* - * Tell the SP which queues are not empty, - * by sending the software event. - */ - if (return_err == IA_CSS_SUCCESS) { - if (!sh_css_sp_is_running()) { - /* SP is not running. The queues are not valid */ - IA_CSS_LOG("SP is not running!"); - IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - return_err = ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED, - (uint8_t)thread_id, - queue_id, - 0); - } else { - ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf); - IA_CSS_ERROR("buffer not enqueued"); - } - - IA_CSS_LEAVE("return value = %d", return_err); - - return return_err; -} - -/* - * TODO: Free up the hmm memory space. - */ -enum ia_css_err -ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, - struct ia_css_buffer *buffer) -{ - enum ia_css_err return_err; - enum sh_css_queue_id queue_id; - hrt_vaddress ddr_buffer_addr = (hrt_vaddress)0; - struct sh_css_hmm_buffer ddr_buffer; - enum ia_css_buffer_type buf_type; - enum ia_css_pipe_id pipe_id; - unsigned int thread_id; - hrt_address kernel_ptr = 0; - bool ret_err; - - IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer); - - if ((pipe == NULL) || (buffer == NULL)) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - pipe_id = pipe->mode; - - buf_type = buffer->type; - - IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type); - - ddr_buffer.kernel_ptr = 0; - - ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - if (!ret_err) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id); - if (!ret_err) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if (!sh_css_sp_is_running()) { - IA_CSS_LOG("SP is not running!"); - IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); - /* SP is not running. The queues are not valid */ - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - - return_err = ia_css_bufq_dequeue_buffer(queue_id, - (uint32_t *)&ddr_buffer_addr); - - if (return_err == IA_CSS_SUCCESS) { - struct ia_css_frame *frame; - struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL; - - IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr); - - /* Validate the ddr_buffer_addr and buf_type */ - hmm_buffer_record = sh_css_hmm_buffer_record_validate( - ddr_buffer_addr, buf_type); - if (hmm_buffer_record != NULL) { - /* valid hmm_buffer_record found. Save the kernel_ptr - * for validation after performing mmgr_load. The - * vbuf handle and buffer_record can be released. - */ - kernel_ptr = hmm_buffer_record->kernel_ptr; - ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf); - sh_css_hmm_buffer_record_reset(hmm_buffer_record); - } else { - IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)", - ddr_buffer_addr, buf_type); - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - - mmgr_load(ddr_buffer_addr, - &ddr_buffer, - sizeof(struct sh_css_hmm_buffer)); - - /* if the kernel_ptr is 0 or an invalid, return an error. - * do not access the buffer via the kernal_ptr. - */ - if ((ddr_buffer.kernel_ptr == 0) || - (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) { - IA_CSS_ERROR("kernel_ptr invalid"); - IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr); - IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr)); - IA_CSS_ERROR("buf_type: %d\n", buf_type); - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - - if (ddr_buffer.kernel_ptr != 0) { - /* buffer->exp_id : all instances to be removed later once the driver change - * is completed. See patch #5758 for reference */ - buffer->exp_id = 0; - buffer->driver_cookie = ddr_buffer.cookie_ptr; - buffer->timing_data = ddr_buffer.timing_data; - - if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) || - (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) { - buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick; - } - - switch (buf_type) { - case IA_CSS_BUFFER_TYPE_INPUT_FRAME: - case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: - case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: - if ((pipe) && (pipe->stop_requested == true)) - { - -#if defined(USE_INPUT_SYSTEM_VERSION_2) - /* free mipi frames only for old input system - * for 2401 it is done in ia_css_stream_destroy call - */ - return_err = free_mipi_frames(pipe); - if (return_err != IA_CSS_SUCCESS) { - IA_CSS_LOG("free_mipi_frames() failed"); - IA_CSS_LEAVE_ERR(return_err); - return return_err; - } -#endif - pipe->stop_requested = false; - } - case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME: - case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME: - frame = (struct ia_css_frame*)HOST_ADDRESS(ddr_buffer.kernel_ptr); - buffer->data.frame = frame; - buffer->exp_id = ddr_buffer.payload.frame.exp_id; - frame->exp_id = ddr_buffer.payload.frame.exp_id; - frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id; - if (ddr_buffer.payload.frame.flashed == 1) - frame->flash_state = - IA_CSS_FRAME_FLASH_STATE_PARTIAL; - if (ddr_buffer.payload.frame.flashed == 2) - frame->flash_state = - IA_CSS_FRAME_FLASH_STATE_FULL; - frame->valid = pipe->num_invalid_frames == 0; - if (!frame->valid) - pipe->num_invalid_frames--; - - if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) { -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - frame->planes.binary.size = frame->data_bytes; -#else - frame->planes.binary.size = - sh_css_sp_get_binary_copy_size(); -#endif - } -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) - if (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME == buf_type) { - IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d", - frame->data, frame->isp_config_id, thread_id); - } -#endif - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n", - buf_type, buffer->data.frame->data); - - break; - case IA_CSS_BUFFER_TYPE_3A_STATISTICS: - buffer->data.stats_3a = - (struct ia_css_isp_3a_statistics*)HOST_ADDRESS(ddr_buffer.kernel_ptr); - buffer->exp_id = ddr_buffer.payload.s3a.exp_id; - buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id; - buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id; - break; - case IA_CSS_BUFFER_TYPE_DIS_STATISTICS: - buffer->data.stats_dvs = - (struct ia_css_isp_dvs_statistics*) - HOST_ADDRESS(ddr_buffer.kernel_ptr); - buffer->exp_id = ddr_buffer.payload.dis.exp_id; - buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id; - break; - case IA_CSS_BUFFER_TYPE_LACE_STATISTICS: - break; - case IA_CSS_BUFFER_TYPE_METADATA: - buffer->data.metadata = - (struct ia_css_metadata*)HOST_ADDRESS(ddr_buffer.kernel_ptr); - buffer->exp_id = ddr_buffer.payload.metadata.exp_id; - buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id; - break; - default: - return_err = IA_CSS_ERR_INTERNAL_ERROR; - break; - } - } - } - - /* - * Tell the SP which queues are not full, - * by sending the software event. - */ - if (return_err == IA_CSS_SUCCESS){ - if (!sh_css_sp_is_running()) { - IA_CSS_LOG("SP is not running!"); - IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); - /* SP is not running. The queues are not valid */ - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED, - 0, - queue_id, - 0); - } - IA_CSS_LEAVE("buffer=%p", buffer); - - return return_err; -} - -/* - * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h - * TODO: modify and move it if possible. - * - * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC: - * 1) "enum ia_css_event_type" (ia_css_event_public.h) - * 2) "enum sh_css_sp_event_type" (sh_css_internal.h) - * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c) - * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c) - */ -static enum ia_css_event_type convert_event_sp_to_host_domain[] = { - IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */ - IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */ - IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */ - IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */ - IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */ - IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */ - IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */ - IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */ - IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */ - IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */ - IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */ - IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */ - IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */ - IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */ - IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */ - IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */ - 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */ -}; - -enum ia_css_err -ia_css_dequeue_event(struct ia_css_event *event) -{ - return ia_css_dequeue_psys_event(event); -} - -enum ia_css_err -ia_css_dequeue_psys_event(struct ia_css_event *event) -{ - enum ia_css_pipe_id pipe_id = 0; - uint8_t payload[4] = {0,0,0,0}; - enum ia_css_err ret_err; - - /*TODO: - * a) use generic decoding function , same as the one used by sp. - * b) group decode and dequeue into eventQueue module - * - * We skip the IA_CSS_ENTER logging call - * to avoid flooding the logs when the host application - * uses polling. */ - if (event == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - if (!sh_css_sp_is_running()) { - /* SP is not running. The queues are not valid */ - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - - /* dequeue the event (if any) from the psys event queue */ - ret_err = ia_css_bufq_dequeue_psys_event(payload); - if (ret_err != IA_CSS_SUCCESS) - return ret_err; - - IA_CSS_LOG("event dequeued from psys event queue"); - - /* Tell the SP that we dequeued an event from the event queue. */ - ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0); - - /* Events are decoded into 4 bytes of payload, the first byte - * contains the sp event type. This is converted to a host enum. - * TODO: can this enum conversion be eliminated */ - event->type = convert_event_sp_to_host_domain[payload[0]]; - /* Some sane default values since not all events use all fields. */ - event->pipe = NULL; - event->port = MIPI_PORT0_ID; - event->exp_id = 0; - event->fw_warning = IA_CSS_FW_WARNING_NONE; - event->fw_handle = 0; - event->timer_data = 0; - event->timer_code = 0; - event->timer_subcode = 0; - - if (event->type == IA_CSS_EVENT_TYPE_TIMER) { - /* timer event ??? get the 2nd event and decode the data into the event struct */ - uint32_t tmp_data; - /* 1st event: LSB 16-bit timer data and code */ - event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8)); - event->timer_code = payload[2]; - payload[0] = payload[1] = payload[2] = payload[3] = 0; - ret_err = ia_css_bufq_dequeue_psys_event(payload); - if (ret_err != IA_CSS_SUCCESS) { - /* no 2nd event ??? an error */ - /* Putting IA_CSS_ERROR is resulting in failures in - * Merrifield smoke testing */ - IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n"); - return ret_err; - } - ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0); - event->type = convert_event_sp_to_host_domain[payload[0]]; - /* It's a timer */ - if (event->type == IA_CSS_EVENT_TYPE_TIMER) { - /* 2nd event data: MSB 16-bit timer and subcode */ - tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8)); - event->timer_data |= (tmp_data << 16); - event->timer_subcode = payload[2]; - } - /* It's a non timer event. So clear first half of the timer event data. - * If the second part of the TIMER event is not received, we discard - * the first half of the timer data and process the non timer event without - * affecting the flow. So the non timer event falls through - * the code. */ - else { - event->timer_data = 0; - event->timer_code = 0; - event->timer_subcode = 0; - IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded"); - } - } - if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) { - event->port = (enum mipi_port_id)payload[1]; - event->exp_id = payload[3]; - } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) { - event->fw_warning = (enum ia_css_fw_warning)payload[1]; - /* exp_id is only available in these warning types */ - if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED || - event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED) - event->exp_id = payload[3]; - } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) { - event->fw_assert_module_id = payload[1]; /* module */ - event->fw_assert_line_no = (payload[2] << 8) + payload[3]; - /* payload[2] is line_no>>8, payload[3] is line_no&0xff */ - } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) { - /* pipe related events. - * payload[1] contains the pipe_num, - * payload[2] contains the pipe_id. These are different. */ - event->pipe = find_pipe_by_num(payload[1]); - pipe_id = (enum ia_css_pipe_id)payload[2]; - /* Check to see if pipe still exists */ - if (!event->pipe) - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - - if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) { - /* find the capture pipe that goes with this */ - int i, n; - n = event->pipe->stream->num_pipes; - for (i = 0; i < n; i++) { - struct ia_css_pipe *p = - event->pipe->stream->pipes[i]; - if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { - event->pipe = p; - break; - } - } - event->exp_id = payload[3]; - } - if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) { - /* payload[3] contains the acc fw handle. */ - uint32_t stage_num = (uint32_t)payload[3]; - ret_err = ia_css_pipeline_get_fw_from_stage( - &(event->pipe->pipeline), - stage_num, - &(event->fw_handle)); - if (ret_err != IA_CSS_SUCCESS) { - IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u", - stage_num); - return ret_err; - } - } - } - - if (event->pipe) - IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id); - else - IA_CSS_LEAVE("event_id=%d", event->type); - - return IA_CSS_SUCCESS; -} - -enum ia_css_err -ia_css_dequeue_isys_event(struct ia_css_event *event) -{ - uint8_t payload[4] = {0, 0, 0, 0}; - enum ia_css_err err = IA_CSS_SUCCESS; - - /* We skip the IA_CSS_ENTER logging call - * to avoid flooding the logs when the host application - * uses polling. */ - if (event == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - if (!sh_css_sp_is_running()) { - /* SP is not running. The queues are not valid */ - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - - err = ia_css_bufq_dequeue_isys_event(payload); - if (err != IA_CSS_SUCCESS) - return err; - - IA_CSS_LOG("event dequeued from isys event queue"); - - /* Update SP state to indicate that element was dequeued. */ - ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED); - - /* Fill return struct with appropriate info */ - event->type = IA_CSS_EVENT_TYPE_PORT_EOF; - /* EOF events are associated with a CSI port, not with a pipe */ - event->pipe = NULL; - event->port = payload[1]; - event->exp_id = payload[3]; - - IA_CSS_LEAVE_ERR(err); - return err; -} - -static void -acc_start(struct ia_css_pipe *pipe) -{ - assert(pipe != NULL); - assert(pipe->stream != NULL); - - start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD, - pipe->stream->config.mode); -} - -static enum ia_css_err -sh_css_pipe_start(struct ia_css_stream *stream) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - struct ia_css_pipe *pipe; - enum ia_css_pipe_id pipe_id; - unsigned int thread_id; - - IA_CSS_ENTER_PRIVATE("stream = %p", stream); - - if (stream == NULL) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - pipe = stream->last_pipe; - if (pipe == NULL) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - pipe_id = pipe->mode; - - if(stream->started == true) { - IA_CSS_WARNING("Cannot start stream that is already started"); - IA_CSS_LEAVE_ERR(err); - return err; - } - - pipe->stop_requested = false; - - switch (pipe_id) { - case IA_CSS_PIPE_ID_PREVIEW: - err = preview_start(pipe); - break; - case IA_CSS_PIPE_ID_VIDEO: - err = video_start(pipe); - break; - case IA_CSS_PIPE_ID_CAPTURE: - err = capture_start(pipe); - break; - case IA_CSS_PIPE_ID_YUVPP: - err = yuvpp_start(pipe); - break; - case IA_CSS_PIPE_ID_ACC: - acc_start(pipe); - break; - default: - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } - /* DH regular multi pipe - not continuous mode: start the next pipes too */ - if (!stream->config.continuous) { - int i; - for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err ; i++) { - switch (stream->pipes[i]->mode) { - case IA_CSS_PIPE_ID_PREVIEW: - stream->pipes[i]->stop_requested = false; - err = preview_start(stream->pipes[i]); - break; - case IA_CSS_PIPE_ID_VIDEO: - stream->pipes[i]->stop_requested = false; - err = video_start(stream->pipes[i]); - break; - case IA_CSS_PIPE_ID_CAPTURE: - stream->pipes[i]->stop_requested = false; - err = capture_start(stream->pipes[i]); - break; - case IA_CSS_PIPE_ID_YUVPP: - stream->pipes[i]->stop_requested = false; - err = yuvpp_start(stream->pipes[i]); - break; - case IA_CSS_PIPE_ID_ACC: - stream->pipes[i]->stop_requested = false; - acc_start(stream->pipes[i]); - break; - default: - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } - } - } - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - /* Force ISP parameter calculation after a mode change - * Acceleration API examples pass NULL for stream but they - * don't use ISP parameters anyway. So this should be okay. - * The SP binary (jpeg) copy does not use any parameters. - */ - if (!copy_on_sp(pipe)) { - sh_css_invalidate_params(stream); - err = sh_css_param_update_isp_params(pipe, - stream->isp_params_configs, true, NULL); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - - ia_css_debug_pipe_graph_dump_epilogue(); - - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - - if (!sh_css_sp_is_running()) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); - /* SP is not running. The queues are not valid */ - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM, - (uint8_t)thread_id, 0, 0); - - /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */ - if (!stream->config.continuous) { - int i; - for (i = 1; i < stream->num_pipes; i++) { - ia_css_pipeline_get_sp_thread_id( - ia_css_pipe_get_pipe_num(stream->pipes[i]), - &thread_id); - ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_START_STREAM, - (uint8_t)thread_id, 0, 0); - } - } - - /* in case of continuous capture mode, we also start capture thread and copy thread*/ - if (pipe->stream->config.continuous) { - struct ia_css_pipe *copy_pipe = NULL; - - if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) - copy_pipe = pipe->pipe_settings.preview.copy_pipe; - else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) - copy_pipe = pipe->pipe_settings.video.copy_pipe; - - if (copy_pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe), &thread_id); - /* by the time we reach here q is initialized and handle is available.*/ - ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_START_STREAM, - (uint8_t)thread_id, 0, 0); - } - if (pipe->stream->cont_capt) { - struct ia_css_pipe *capture_pipe = NULL; - if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) - capture_pipe = pipe->pipe_settings.preview.capture_pipe; - else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) - capture_pipe = pipe->pipe_settings.video.capture_pipe; - - if (capture_pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id); - /* by the time we reach here q is initialized and handle is available.*/ - ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_START_STREAM, - (uint8_t)thread_id, 0, 0); - } - - /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */ - if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) { - struct ia_css_pipe *acc_pipe = NULL; - acc_pipe = pipe->pipe_settings.preview.acc_pipe; - - if (acc_pipe){ - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe), &thread_id); - /* by the time we reach here q is initialized and handle is available.*/ - ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_START_STREAM, - (uint8_t) thread_id, 0, 0); - } - } - - stream->started = true; - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -#ifndef ISP2401 -void -sh_css_enable_cont_capt(bool enable, bool stop_copy_preview) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "sh_css_enable_cont_capt() enter: enable=%d\n", enable); -//my_css.cont_capt = enable; - my_css.stop_copy_preview = stop_copy_preview; -} - -bool -sh_css_continuous_is_enabled(uint8_t pipe_num) -#else -/* - * @brief Stop all "ia_css_pipe" instances in the target - * "ia_css_stream" instance. - * - * Refer to "Local prototypes" for more info. - */ -static enum ia_css_err -sh_css_pipes_stop(struct ia_css_stream *stream) -#endif -{ -#ifndef ISP2401 - struct ia_css_pipe *pipe; - bool continuous; -#else - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_pipe *main_pipe; - enum ia_css_pipe_id main_pipe_id; - int i; -#endif - -#ifndef ISP2401 - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num); -#else - assert(stream != NULL); - if (stream == NULL) { - IA_CSS_LOG("stream does NOT exist!"); - err = IA_CSS_ERR_INTERNAL_ERROR; - goto ERR; - } -#endif - -#ifndef ISP2401 - pipe = find_pipe_by_num(pipe_num); - continuous = pipe && pipe->stream->config.continuous; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "sh_css_continuous_is_enabled() leave: enable=%d\n", - continuous); - return continuous; -} -#else - main_pipe = stream->last_pipe; - assert(main_pipe != NULL); - if (main_pipe == NULL) { - IA_CSS_LOG("main_pipe does NOT exist!"); - err = IA_CSS_ERR_INTERNAL_ERROR; - goto ERR; - } -#endif - -#ifndef ISP2401 -enum ia_css_err -ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, int *buffer_depth) -{ - if (buffer_depth == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n"); - (void)stream; - *buffer_depth = NUM_CONTINUOUS_FRAMES; - return IA_CSS_SUCCESS; -} -#else - main_pipe_id = main_pipe->mode; - IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id); -#endif - -#ifndef ISP2401 -enum ia_css_err -ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth); - (void)stream; - if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1) - return IA_CSS_ERR_INVALID_ARGUMENTS; - /* ok, value allowed */ - stream->config.target_num_cont_raw_buf = buffer_depth; - /* TODO: check what to regarding initialization */ - return IA_CSS_SUCCESS; -} -#else - /* - * Stop all "ia_css_pipe" instances in this target - * "ia_css_stream" instance. - */ - for (i = 0; i < stream->num_pipes; i++) { - /* send the "stop" request to the "ia_css_pipe" instance */ - IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", - stream->pipes[i]->pipeline.pipe_id); - err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline); -#endif - -#ifndef ISP2401 -enum ia_css_err -ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, int *buffer_depth) -{ - if (buffer_depth == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n"); -#else - /* - * Exit this loop if "ia_css_pipeline_request_stop()" - * returns the error code. - * - * The error code would be generated in the following - * two cases: - * (1) The Scalar Processor has already been stopped. - * (2) The "Host->SP" event queue is full. - * - * As the convention of using CSS API 2.0/2.1, such CSS - * error code would be propogated from the CSS-internal - * API returned value to the CSS API returned value. Then - * the CSS driver should capture these error code and - * handle it in the driver exception handling mechanism. - */ - if (err != IA_CSS_SUCCESS) { - goto ERR; - } - } - - /* - * In the CSS firmware use scenario "Continuous Preview" - * as well as "Continuous Video", the "ia_css_pipe" instance - * "Copy Pipe" is activated. This "Copy Pipe" is private to - * the CSS firmware so that it is not listed in the target - * "ia_css_stream" instance. - * - * We need to stop this "Copy Pipe", as well. - */ - if (main_pipe->stream->config.continuous) { - struct ia_css_pipe *copy_pipe = NULL; - - /* get the reference to "Copy Pipe" */ - if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW) - copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; - else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO) - copy_pipe = main_pipe->pipe_settings.video.copy_pipe; - - /* return the error code if "Copy Pipe" does NOT exist */ - assert(copy_pipe != NULL); - if (copy_pipe == NULL) { - IA_CSS_LOG("Copy Pipe does NOT exist!"); - err = IA_CSS_ERR_INTERNAL_ERROR; - goto ERR; - } - - /* send the "stop" request to "Copy Pipe" */ - IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", - copy_pipe->pipeline.pipe_id); - err = ia_css_pipeline_request_stop(©_pipe->pipeline); - } - -ERR: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -/* - * @brief Check if all "ia_css_pipe" instances in the target - * "ia_css_stream" instance have stopped. - * - * Refer to "Local prototypes" for more info. - */ -static bool -sh_css_pipes_have_stopped(struct ia_css_stream *stream) -{ - bool rval = true; - - struct ia_css_pipe *main_pipe; - enum ia_css_pipe_id main_pipe_id; - - int i; - - assert(stream != NULL); - if (stream == NULL) { - IA_CSS_LOG("stream does NOT exist!"); - rval = false; - goto RET; - } - - main_pipe = stream->last_pipe; - assert(main_pipe != NULL); - - if (main_pipe == NULL) { - IA_CSS_LOG("main_pipe does NOT exist!"); - rval = false; - goto RET; - } - - main_pipe_id = main_pipe->mode; - IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id); - - /* - * Check if every "ia_css_pipe" instance in this target - * "ia_css_stream" instance has stopped. - */ - for (i = 0; i < stream->num_pipes; i++) { - rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline); - IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d", - stream->pipes[i]->pipeline.pipe_id, - rval); - } - - /* - * In the CSS firmware use scenario "Continuous Preview" - * as well as "Continuous Video", the "ia_css_pipe" instance - * "Copy Pipe" is activated. This "Copy Pipe" is private to - * the CSS firmware so that it is not listed in the target - * "ia_css_stream" instance. - * - * We need to check if this "Copy Pipe" has stopped, as well. - */ - if (main_pipe->stream->config.continuous) { - struct ia_css_pipe *copy_pipe = NULL; - - /* get the reference to "Copy Pipe" */ - if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW) - copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; - else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO) - copy_pipe = main_pipe->pipe_settings.video.copy_pipe; - - /* return if "Copy Pipe" does NOT exist */ - assert(copy_pipe != NULL); - if (copy_pipe == NULL) { - IA_CSS_LOG("Copy Pipe does NOT exist!"); - - rval = false; - goto RET; - } - - /* check if "Copy Pipe" has stopped or not */ - rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline); - IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d", - copy_pipe->pipeline.pipe_id, - rval); - } - -RET: - IA_CSS_LEAVE_PRIVATE("rval=%d", rval); - return rval; -} - -bool -sh_css_continuous_is_enabled(uint8_t pipe_num) -{ - struct ia_css_pipe *pipe; - bool continuous; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num); - - pipe = find_pipe_by_num(pipe_num); - continuous = pipe && pipe->stream->config.continuous; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "sh_css_continuous_is_enabled() leave: enable=%d\n", - continuous); - return continuous; -} - -enum ia_css_err -ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, int *buffer_depth) -{ - if (buffer_depth == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n"); - (void)stream; - *buffer_depth = NUM_CONTINUOUS_FRAMES; - return IA_CSS_SUCCESS; -} - -enum ia_css_err -ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth); - (void)stream; - if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1) - return IA_CSS_ERR_INVALID_ARGUMENTS; - /* ok, value allowed */ - stream->config.target_num_cont_raw_buf = buffer_depth; - /* TODO: check what to regarding initialization */ - return IA_CSS_SUCCESS; -} - -enum ia_css_err -ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, int *buffer_depth) -{ - if (buffer_depth == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n"); -#endif - (void)stream; - *buffer_depth = stream->config.target_num_cont_raw_buf; - return IA_CSS_SUCCESS; -} - -#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) -unsigned int -sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx) -{ - OP___assert(port < N_CSI_PORTS); - OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n", - port, idx, my_css.mipi_sizes_for_check[port][idx]); - return my_css.mipi_sizes_for_check[port][idx]; -} -#endif - -static enum ia_css_err sh_css_pipe_configure_output( - struct ia_css_pipe *pipe, - unsigned int width, - unsigned int height, - unsigned int padded_width, - enum ia_css_frame_format format, - unsigned int idx) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, paddaed width = %d, format = %d, idx = %d", - pipe, width, height, padded_width, format, idx); - if (pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - err = ia_css_util_check_res(width, height); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - if (pipe->output_info[idx].res.width != width || - pipe->output_info[idx].res.height != height || - pipe->output_info[idx].format != format) - { - ia_css_frame_info_init( - &pipe->output_info[idx], - width, - height, - format, - padded_width); - } - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe, -#ifndef ISP2401 - struct ia_css_shading_info *info) -#else - struct ia_css_shading_info *shading_info, - struct ia_css_pipe_config *pipe_config) -#endif -{ - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_binary *binary = NULL; - - assert(pipe != NULL); -#ifndef ISP2401 - assert(info != NULL); -#else - assert(shading_info != NULL); - assert(pipe_config != NULL); -#endif - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_pipe_get_shading_info() enter:\n"); - - binary = ia_css_pipe_get_shading_correction_binary(pipe); - - if (binary) { - err = ia_css_binary_get_shading_info(binary, - IA_CSS_SHADING_CORRECTION_TYPE_1, - pipe->required_bds_factor, - (const struct ia_css_stream_config *)&pipe->stream->config, -#ifndef ISP2401 - info); -#else - shading_info, pipe_config); -#endif - /* Other function calls can be added here when other shading correction types will be added - * in the future. - */ - } else { - /* When the pipe does not have a binary which has the shading - * correction, this function does not need to fill the shading - * information. It is not a error case, and then - * this function should return IA_CSS_SUCCESS. - */ -#ifndef ISP2401 - memset(info, 0, sizeof(*info)); -#else - memset(shading_info, 0, sizeof(*shading_info)); -#endif - } - return err; -} - -static enum ia_css_err -sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe, - struct ia_css_grid_info *info) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_binary *binary = NULL; - - assert(pipe != NULL); - assert(info != NULL); - - IA_CSS_ENTER_PRIVATE(""); - - binary = ia_css_pipe_get_s3a_binary(pipe); - - if (binary) { - err = ia_css_binary_3a_grid_info(binary, info, pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - } else - memset(&info->s3a_grid, 0, sizeof(info->s3a_grid)); - - binary = ia_css_pipe_get_sdis_binary(pipe); - - if (binary) { - ia_css_binary_dvs_grid_info(binary, info, pipe); - ia_css_binary_dvs_stat_grid_info(binary, info, pipe); - } else { - memset(&info->dvs_grid.dvs_grid_info, 0, - sizeof(info->dvs_grid.dvs_grid_info)); - memset(&info->dvs_grid.dvs_stat_grid_info, 0, - sizeof(info->dvs_grid.dvs_stat_grid_info)); - } - - if (binary != NULL) { - /* copy pipe does not have ISP binary*/ - info->isp_in_width = binary->internal_frame_info.res.width; - info->isp_in_height = binary->internal_frame_info.res.height; - } - -#if defined(HAS_VAMEM_VERSION_2) - info->vamem_type = IA_CSS_VAMEM_TYPE_2; -#elif defined(HAS_VAMEM_VERSION_1) - info->vamem_type = IA_CSS_VAMEM_TYPE_1; -#else -#error "Unknown VAMEM version" -#endif - -ERR: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -#ifdef ISP2401 -/* - * @brief Check if a format is supported by the pipe. - * - */ -static enum ia_css_err -ia_css_pipe_check_format(struct ia_css_pipe *pipe, enum ia_css_frame_format format) -{ - const enum ia_css_frame_format *supported_formats; - int number_of_formats; - int found = 0; - int i; - - IA_CSS_ENTER_PRIVATE(""); - - if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) { - IA_CSS_ERROR("Pipe or binary info is not set"); - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats; - number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats)/sizeof(enum ia_css_frame_format); - - for (i = 0; i < number_of_formats && !found; i++) { - if (supported_formats[i] == format) { - found = 1; - break; - } - } - if (!found) { - IA_CSS_ERROR("Requested format is not supported by binary"); - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } else { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; - } -} -#endif - -static enum ia_css_err load_video_binaries(struct ia_css_pipe *pipe) -{ - struct ia_css_frame_info video_in_info, tnr_info, - *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info; - bool online; - enum ia_css_err err = IA_CSS_SUCCESS; - bool continuous = pipe->stream->config.continuous; - unsigned int i; - unsigned num_output_pins; - struct ia_css_frame_info video_bin_out_info; - bool need_scaler = false; - bool vf_res_different_than_output = false; - bool need_vf_pp = false; - int vf_ds_log2; - struct ia_css_video_settings *mycs = &pipe->pipe_settings.video; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO); - /* we only test the video_binary because offline video doesn't need a - * vf_pp binary and online does not (always use) the copy_binary. - * All are always reset at the same time anyway. - */ - if (mycs->video_binary.info) - return IA_CSS_SUCCESS; - - online = pipe->stream->config.online; - pipe_out_info = &pipe->output_info[0]; - pipe_vf_out_info = &pipe->vf_output_info[0]; - - assert(pipe_out_info != NULL); - - /* - * There is no explicit input format requirement for raw or yuv - * What matters is that there is a binary that supports the stream format. - * This is checked in the binary_find(), so no need to check it here - */ - err = ia_css_util_check_input(&pipe->stream->config, false, false); - if (err != IA_CSS_SUCCESS) - return err; - /* cannot have online video and input_mode memory */ - if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY) - return IA_CSS_ERR_INVALID_ARGUMENTS; - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { - err = ia_css_util_check_vf_out_info(pipe_out_info, - pipe_vf_out_info); - if (err != IA_CSS_SUCCESS) - return err; - } else { - err = ia_css_frame_check_info(pipe_out_info); - if (err != IA_CSS_SUCCESS) - return err; - } - - if (pipe->out_yuv_ds_input_info.res.width) - video_bin_out_info = pipe->out_yuv_ds_input_info; - else - video_bin_out_info = *pipe_out_info; - - /* Video */ - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]){ - video_vf_info = pipe_vf_out_info; - vf_res_different_than_output = (video_vf_info->res.width != video_bin_out_info.res.width) || - (video_vf_info->res.height != video_bin_out_info.res.height); - } - else { - video_vf_info = NULL; - } - - need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res); - - /* we build up the pipeline starting at the end */ - /* YUV post-processing if needed */ - if (need_scaler) { - struct ia_css_cas_binary_descr cas_scaler_descr = { }; - - /* NV12 is the common format that is supported by both */ - /* yuv_scaler and the video_xx_isp2_min binaries. */ - video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12; - - err = ia_css_pipe_create_cas_scaler_desc_single_output( - &video_bin_out_info, - pipe_out_info, - NULL, - &cas_scaler_descr); - if (err != IA_CSS_SUCCESS) - return err; - mycs->num_yuv_scaler = cas_scaler_descr.num_stage; - mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * - sizeof(struct ia_css_binary), GFP_KERNEL); - if (!mycs->yuv_scaler_binary) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - return err; - } - mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage - * sizeof(bool), GFP_KERNEL); - if (!mycs->is_output_stage) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - return err; - } - for (i = 0; i < cas_scaler_descr.num_stage; i++) { - struct ia_css_binary_descr yuv_scaler_descr; - mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; - ia_css_pipe_get_yuvscaler_binarydesc(pipe, - &yuv_scaler_descr, &cas_scaler_descr.in_info[i], - &cas_scaler_descr.out_info[i], - &cas_scaler_descr.internal_out_info[i], - &cas_scaler_descr.vf_info[i]); - err = ia_css_binary_find(&yuv_scaler_descr, - &mycs->yuv_scaler_binary[i]); - if (err != IA_CSS_SUCCESS) { - kfree(mycs->is_output_stage); - mycs->is_output_stage = NULL; - return err; - } - } - ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); - } - - - { - struct ia_css_binary_descr video_descr; - enum ia_css_frame_format vf_info_format; - - err = ia_css_pipe_get_video_binarydesc(pipe, - &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info, video_vf_info, - pipe->stream->config.left_padding); - if (err != IA_CSS_SUCCESS) - return err; - - /* In the case where video_vf_info is not NULL, this allows - * us to find a potential video library with desired vf format. - * If success, no vf_pp binary is needed. - * If failed, we will look up video binary with YUV_LINE vf format - */ - err = ia_css_binary_find(&video_descr, - &mycs->video_binary); - - if (err != IA_CSS_SUCCESS) { - if (video_vf_info) { - /* This will do another video binary lookup later for YUV_LINE format*/ - need_vf_pp = true; - } else - return err; - } else if (video_vf_info) { - /* The first video binary lookup is successful, but we may - * still need vf_pp binary based on additiona check */ - num_output_pins = mycs->video_binary.info->num_output_pins; - vf_ds_log2 = mycs->video_binary.vf_downscale_log2; - - /* If the binary has dual output pins, we need vf_pp if the resolution - * is different. */ - need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output); - - /* If the binary has single output pin, we need vf_pp if additional - * scaling is needed for vf */ - need_vf_pp |= ((num_output_pins == 1) && - ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) || - (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height))); - } - - if (need_vf_pp) { - /* save the current vf_info format for restoration later */ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n"); - - vf_info_format = video_vf_info->format; - - if (!pipe->config.enable_vfpp_bci) - ia_css_frame_info_set_format(video_vf_info, - IA_CSS_FRAME_FORMAT_YUV_LINE); - - ia_css_binary_destroy_isp_parameters(&mycs->video_binary); - - err = ia_css_binary_find(&video_descr, - &mycs->video_binary); - - /* restore original vf_info format */ - ia_css_frame_info_set_format(video_vf_info, - vf_info_format); - if (err != IA_CSS_SUCCESS) - return err; - } - } - - /* If a video binary does not use a ref_frame, we set the frame delay - * to 0. This is the case for the 1-stage low-power video binary. */ - if (!mycs->video_binary.info->sp.enable.ref_frame) - pipe->dvs_frame_delay = 0; - - /* The delay latency determines the number of invalid frames after - * a stream is started. */ - pipe->num_invalid_frames = pipe->dvs_frame_delay; - pipe->info.num_invalid_frames = pipe->num_invalid_frames; - - /* Viewfinder frames also decrement num_invalid_frames. If the pipe - * outputs a viewfinder output, then we need double the number of - * invalid frames */ - if (video_vf_info) - pipe->num_invalid_frames *= 2; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n", - pipe->num_invalid_frames, pipe->dvs_frame_delay); - -/* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */ -#if !defined(USE_INPUT_SYSTEM_VERSION_2401) - /* Copy */ - if (!online && !continuous) { - /* TODO: what exactly needs doing, prepend the copy binary to - * video base this only on !online? - */ - err = load_copy_binary(pipe, - &mycs->copy_binary, - &mycs->video_binary); - if (err != IA_CSS_SUCCESS) - return err; - } -#else - (void)continuous; -#endif - -#if !defined(HAS_OUTPUT_SYSTEM) - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) { - struct ia_css_binary_descr vf_pp_descr; - - if (mycs->video_binary.vf_frame_info.format - == IA_CSS_FRAME_FORMAT_YUV_LINE) { - ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr, - &mycs->video_binary.vf_frame_info, - pipe_vf_out_info); - } else { - /* output from main binary is not yuv line. currently this is - * possible only when bci is enabled on vfpp output */ - assert(pipe->config.enable_vfpp_bci == true); - ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr, - &mycs->video_binary.vf_frame_info, - pipe_vf_out_info, NULL, NULL); - } - - err = ia_css_binary_find(&vf_pp_descr, - &mycs->vf_pp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } -#endif - - err = allocate_delay_frames(pipe); - - if (err != IA_CSS_SUCCESS) - return err; - - if (mycs->video_binary.info->sp.enable.block_output) { -#ifdef ISP2401 - unsigned int tnr_width; - unsigned int tnr_height; -#endif - tnr_info = mycs->video_binary.out_frame_info[0]; -#ifdef ISP2401 - - /* Select resolution for TNR. If - * output_system_in_resolution(GDC_out_resolution) is - * being used, then select that as it will also be in resolution for - * TNR. At present, it only make sense for Skycam */ - if (pipe->config.output_system_in_res.width && pipe->config.output_system_in_res.height) { - tnr_width = pipe->config.output_system_in_res.width; - tnr_height = pipe->config.output_system_in_res.height; - } else { - tnr_width = tnr_info.res.width; - tnr_height = tnr_info.res.height; - } - - /* Make tnr reference buffers output block width(in pix) align */ - tnr_info.res.width = - CEIL_MUL(tnr_width, - (mycs->video_binary.info->sp.block.block_width * ISP_NWAY)); - tnr_info.padded_width = tnr_info.res.width; - -#endif - /* Make tnr reference buffers output block height align */ -#ifndef ISP2401 - tnr_info.res.height = - CEIL_MUL(tnr_info.res.height, - mycs->video_binary.info->sp.block.output_block_height); -#else - tnr_info.res.height = - CEIL_MUL(tnr_height, - mycs->video_binary.info->sp.block.output_block_height); -#endif - } else { - tnr_info = mycs->video_binary.internal_frame_info; - } - tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE; - tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH; - -#ifndef ISP2401 - for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) { -#else - for (i = 0; i < NUM_TNR_FRAMES; i++) { -#endif - if (mycs->tnr_frames[i]) { - ia_css_frame_free(mycs->tnr_frames[i]); - mycs->tnr_frames[i] = NULL; - } - err = ia_css_frame_allocate_from_info( - &mycs->tnr_frames[i], - &tnr_info); - if (err != IA_CSS_SUCCESS) - return err; - } - IA_CSS_LEAVE_PRIVATE(""); - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -unload_video_binaries(struct ia_css_pipe *pipe) -{ - unsigned int i; - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - - if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary); - ia_css_binary_unload(&pipe->pipe_settings.video.video_binary); - ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary); -#ifndef ISP2401 - ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary); -#endif - - for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++) - ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]); - - kfree(pipe->pipe_settings.video.is_output_stage); - pipe->pipe_settings.video.is_output_stage = NULL; - kfree(pipe->pipe_settings.video.yuv_scaler_binary); - pipe->pipe_settings.video.yuv_scaler_binary = NULL; - - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - -static enum ia_css_err video_start(struct ia_css_pipe *pipe) -{ - struct ia_css_binary *copy_binary; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_pipe *copy_pipe, *capture_pipe; - enum sh_css_pipe_config_override copy_ovrd; - enum ia_css_input_mode video_pipe_input_mode; - - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - video_pipe_input_mode = pipe->stream->config.mode; - - copy_pipe = pipe->pipe_settings.video.copy_pipe; - capture_pipe = pipe->pipe_settings.video.capture_pipe; - - copy_binary = &pipe->pipe_settings.video.copy_binary; - - sh_css_metrics_start_frame(); - - /* multi stream video needs mipi buffers */ - -#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) - err = send_mipi_frames(pipe); - if (err != IA_CSS_SUCCESS) - return err; -#endif - - send_raw_frames(pipe); - { - unsigned int thread_id; - - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - copy_ovrd = 1 << thread_id; - - if (pipe->stream->cont_capt) { - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id); - copy_ovrd |= 1 << thread_id; - } - } - - /* Construct and load the copy pipe */ - if (pipe->stream->config.continuous) { - sh_css_sp_init_pipeline(©_pipe->pipeline, - IA_CSS_PIPE_ID_COPY, - (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe), - false, - pipe->stream->config.pixels_per_clock == 2, false, - false, pipe->required_bds_factor, - copy_ovrd, - pipe->stream->config.mode, - &pipe->stream->config.metadata_config, -#ifndef ISP2401 - &pipe->stream->info.metadata_info -#else - &pipe->stream->info.metadata_info, -#endif -#if !defined(HAS_NO_INPUT_SYSTEM) -#ifndef ISP2401 - , pipe->stream->config.source.port.port -#else - pipe->stream->config.source.port.port, -#endif -#endif -#ifndef ISP2401 - ); -#else - ©_pipe->config.internal_frame_origin_bqs_on_sctbl, - copy_pipe->stream->isp_params_configs); -#endif - - /* make the video pipe start with mem mode input, copy handles - the actual mode */ - video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; - } - - /* Construct and load the capture pipe */ - if (pipe->stream->cont_capt) { - sh_css_sp_init_pipeline(&capture_pipe->pipeline, - IA_CSS_PIPE_ID_CAPTURE, - (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe), - capture_pipe->config.default_capture_config.enable_xnr != 0, - capture_pipe->stream->config.pixels_per_clock == 2, - true, /* continuous */ - false, /* offline */ - capture_pipe->required_bds_factor, - 0, - IA_CSS_INPUT_MODE_MEMORY, - &pipe->stream->config.metadata_config, -#ifndef ISP2401 - &pipe->stream->info.metadata_info -#else - &pipe->stream->info.metadata_info, -#endif -#if !defined(HAS_NO_INPUT_SYSTEM) -#ifndef ISP2401 - , (enum mipi_port_id)0 -#else - (enum mipi_port_id)0, -#endif -#endif -#ifndef ISP2401 - ); -#else - &capture_pipe->config.internal_frame_origin_bqs_on_sctbl, - capture_pipe->stream->isp_params_configs); -#endif - } - - start_pipe(pipe, copy_ovrd, video_pipe_input_mode); - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -static -enum ia_css_err sh_css_pipe_get_viewfinder_frame_info( - struct ia_css_pipe *pipe, - struct ia_css_frame_info *info, - unsigned int idx) -{ - assert(pipe != NULL); - assert(info != NULL); - -/* We could print the pointer as input arg, and the values as output */ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_get_viewfinder_frame_info() enter: void\n"); - - if ( pipe->mode == IA_CSS_PIPE_ID_CAPTURE && - (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)) - return IA_CSS_ERR_MODE_HAS_NO_VIEWFINDER; - /* offline video does not generate viewfinder output */ - *info = pipe->vf_output_info[idx]; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_pipe_get_viewfinder_frame_info() leave: \ - info.res.width=%d, info.res.height=%d, \ - info.padded_width=%d, info.format=%d, \ - info.raw_bit_depth=%d, info.raw_bayer_order=%d\n", - info->res.width,info->res.height, - info->padded_width,info->format, - info->raw_bit_depth,info->raw_bayer_order); - - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width, - unsigned int height, unsigned int min_width, - enum ia_css_frame_format format, - unsigned int idx) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n", - pipe, width, height, min_width, format, idx); - - if (pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - - err = ia_css_util_check_res(width, height); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - if (pipe->vf_output_info[idx].res.width != width || - pipe->vf_output_info[idx].res.height != height || - pipe->vf_output_info[idx].format != format) { - ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height, - format, min_width); - } - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - -static enum ia_css_err load_copy_binaries(struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - assert(pipe != NULL); - IA_CSS_ENTER_PRIVATE(""); - - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); - if (pipe->pipe_settings.capture.copy_binary.info) - return IA_CSS_SUCCESS; - - err = ia_css_frame_check_info(&pipe->output_info[0]); - if (err != IA_CSS_SUCCESS) - goto ERR; - - err = verify_copy_out_frame_format(pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - - err = load_copy_binary(pipe, - &pipe->pipe_settings.capture.copy_binary, - NULL); - -ERR: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -static bool need_capture_pp( - const struct ia_css_pipe *pipe) -{ - const struct ia_css_frame_info *out_info = &pipe->output_info[0]; - IA_CSS_ENTER_LEAVE_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); -#ifdef ISP2401 - - /* ldc and capture_pp are not supported in the same pipeline */ - if (need_capt_ldc(pipe) == true) - return false; -#endif - /* determine whether we need to use the capture_pp binary. - * This is needed for: - * 1. XNR or - * 2. Digital Zoom or - * 3. YUV downscaling - */ - if (pipe->out_yuv_ds_input_info.res.width && - ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) || - (pipe->out_yuv_ds_input_info.res.height != out_info->res.height))) - return true; - - if (pipe->config.default_capture_config.enable_xnr != 0) - return true; - - if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) || - (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) || - pipe->config.enable_dz) - return true; - - return false; -} - -static bool need_capt_ldc( - const struct ia_css_pipe *pipe) -{ - IA_CSS_ENTER_LEAVE_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); - return (pipe->extra_config.enable_dvs_6axis) ? true:false; -} - -static enum ia_css_err set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - if (num == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - switch (version) { - case IA_CSS_PIPE_VERSION_2_6_1: - *num = NUM_PRIMARY_HQ_STAGES; - break; - case IA_CSS_PIPE_VERSION_2_2: - case IA_CSS_PIPE_VERSION_1: - *num = NUM_PRIMARY_STAGES; - break; - default: - err = IA_CSS_ERR_INVALID_ARGUMENTS; - break; - } - - return err; -} - -static enum ia_css_err load_primary_binaries( - struct ia_css_pipe *pipe) -{ - bool online = false; - bool memory = false; - bool continuous = false; - bool need_pp = false; - bool need_isp_copy_binary = false; - bool need_ldc = false; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - bool sensor = false; -#endif - struct ia_css_frame_info prim_in_info, - prim_out_info, - capt_pp_out_info, vf_info, - *vf_pp_in_info, *pipe_out_info, -#ifndef ISP2401 - *pipe_vf_out_info, *capt_pp_in_info, - capt_ldc_out_info; -#else - *pipe_vf_out_info; -#endif - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_capture_settings *mycs; - unsigned int i; - bool need_extra_yuv_scaler = false; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->stream != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); - - online = pipe->stream->config.online; - memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; - continuous = pipe->stream->config.continuous; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); -#endif - - mycs = &pipe->pipe_settings.capture; - pipe_out_info = &pipe->output_info[0]; - pipe_vf_out_info = &pipe->vf_output_info[0]; - - if (mycs->primary_binary[0].info) - return IA_CSS_SUCCESS; - - err = set_num_primary_stages(&mycs->num_primary_stage, pipe->config.isp_pipe_version); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { - err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - else{ - err = ia_css_frame_check_info(pipe_out_info); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - need_pp = need_capture_pp(pipe); - - /* we use the vf output info to get the primary/capture_pp binary - configured for vf_veceven. It will select the closest downscaling - factor. */ - vf_info = *pipe_vf_out_info; - -/* - * WARNING: The #if def flag has been added below as a - * temporary solution to solve the problem of enabling the - * view finder in a single binary in a capture flow. The - * vf-pp stage has been removed for Skycam in the solution - * provided. The vf-pp stage should be re-introduced when - * required. This should not be considered as a clean solution. - * Proper investigation should be done to come up with the clean - * solution. - * */ - ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); - - /* TODO: All this yuv_scaler and capturepp calculation logic - * can be shared later. Capture_pp is also a yuv_scale binary - * with extra XNR funcionality. Therefore, it can be made as the - * first step of the cascade. */ - capt_pp_out_info = pipe->out_yuv_ds_input_info; - capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420; - capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP; - capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP; - ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0); - -/* - * WARNING: The #if def flag has been added below as a - * temporary solution to solve the problem of enabling the - * view finder in a single binary in a capture flow. The - * vf-pp stage has been removed for Skycam in the solution - * provided. The vf-pp stage should be re-introduced when - * required. This should not be considered as a clean solution. - * Proper investigation should be done to come up with the clean - * solution. - * */ - need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res, - pipe_out_info->res); - - if (need_extra_yuv_scaler) { - struct ia_css_cas_binary_descr cas_scaler_descr = { }; - - err = ia_css_pipe_create_cas_scaler_desc_single_output( - &capt_pp_out_info, - pipe_out_info, - NULL, - &cas_scaler_descr); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - mycs->num_yuv_scaler = cas_scaler_descr.num_stage; - mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * - sizeof(struct ia_css_binary), GFP_KERNEL); - if (!mycs->yuv_scaler_binary) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage * - sizeof(bool), GFP_KERNEL); - if (!mycs->is_output_stage) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - for (i = 0; i < cas_scaler_descr.num_stage; i++) { - struct ia_css_binary_descr yuv_scaler_descr; - mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; - ia_css_pipe_get_yuvscaler_binarydesc(pipe, - &yuv_scaler_descr, &cas_scaler_descr.in_info[i], - &cas_scaler_descr.out_info[i], - &cas_scaler_descr.internal_out_info[i], - &cas_scaler_descr.vf_info[i]); - err = ia_css_binary_find(&yuv_scaler_descr, - &mycs->yuv_scaler_binary[i]); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); - - } else { - capt_pp_out_info = pipe->output_info[0]; - } - - /* TODO Do we disable ldc for skycam */ - need_ldc = need_capt_ldc(pipe); -#ifdef ISP2401 - /* ldc and capt_pp are not supported in the same pipeline */ - if (need_ldc) { - struct ia_css_binary_descr capt_ldc_descr; - ia_css_pipe_get_ldc_binarydesc(pipe, - &capt_ldc_descr, &prim_out_info, - &capt_pp_out_info); -#endif - -#ifdef ISP2401 - err = ia_css_binary_find(&capt_ldc_descr, - &mycs->capture_ldc_binary); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } else if (need_pp) { -#endif - /* we build up the pipeline starting at the end */ - /* Capture post-processing */ -#ifndef ISP2401 - if (need_pp) { -#endif - struct ia_css_binary_descr capture_pp_descr; -#ifndef ISP2401 - capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info; -#endif - - ia_css_pipe_get_capturepp_binarydesc(pipe, -#ifndef ISP2401 - &capture_pp_descr, capt_pp_in_info, -#else - &capture_pp_descr, &prim_out_info, -#endif - &capt_pp_out_info, &vf_info); - err = ia_css_binary_find(&capture_pp_descr, - &mycs->capture_pp_binary); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } -#ifndef ISP2401 - - if(need_ldc) { - struct ia_css_binary_descr capt_ldc_descr; - ia_css_pipe_get_ldc_binarydesc(pipe, - &capt_ldc_descr, &prim_out_info, - &capt_ldc_out_info); - - err = ia_css_binary_find(&capt_ldc_descr, - &mycs->capture_ldc_binary); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } -#endif - } else { - prim_out_info = *pipe_out_info; - } - - /* Primary */ - { - struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES]; - - for (i = 0; i < mycs->num_primary_stage; i++) { - struct ia_css_frame_info *local_vf_info = NULL; - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && (i == mycs->num_primary_stage - 1)) - local_vf_info = &vf_info; - ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info, &prim_out_info, local_vf_info, i); - err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - } - - /* Viewfinder post-processing */ - if (need_pp) { - vf_pp_in_info = - &mycs->capture_pp_binary.vf_frame_info; - } else { - vf_pp_in_info = - &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info; - } - -/* - * WARNING: The #if def flag has been added below as a - * temporary solution to solve the problem of enabling the - * view finder in a single binary in a capture flow. The - * vf-pp stage has been removed for Skycam in the solution - * provided. The vf-pp stage should be re-introduced when - * required. Thisshould not be considered as a clean solution. - * Proper * investigation should be done to come up with the clean - * solution. - * */ - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) - { - struct ia_css_binary_descr vf_pp_descr; - - ia_css_pipe_get_vfpp_binarydesc(pipe, - &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); - err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - err = allocate_delay_frames(pipe); - - if (err != IA_CSS_SUCCESS) - return err; - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* When the input system is 2401, only the Direct Sensor Mode - * Offline Capture uses the ISP copy binary. - */ - need_isp_copy_binary = !online && sensor; -#else - need_isp_copy_binary = !online && !continuous && !memory; -#endif - - /* ISP Copy */ - if (need_isp_copy_binary) { - err = load_copy_binary(pipe, - &mycs->copy_binary, - &mycs->primary_binary[0]); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -allocate_delay_frames(struct ia_css_pipe *pipe) -{ - unsigned int num_delay_frames = 0, i = 0; - unsigned int dvs_frame_delay = 0; - struct ia_css_frame_info ref_info; - enum ia_css_err err = IA_CSS_SUCCESS; - enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO; - struct ia_css_frame **delay_frames = NULL; - - IA_CSS_ENTER_PRIVATE(""); - - if (pipe == NULL) { - IA_CSS_ERROR("Invalid args - pipe %p", pipe); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - mode = pipe->mode; - dvs_frame_delay = pipe->dvs_frame_delay; - - if (dvs_frame_delay > 0) - num_delay_frames = dvs_frame_delay + 1; - - switch (mode) { - case IA_CSS_PIPE_ID_CAPTURE: - { - struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture; - (void)mycs_capture; - return err; - } - break; - case IA_CSS_PIPE_ID_VIDEO: - { - struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video; - ref_info = mycs_video->video_binary.internal_frame_info; - /*The ref frame expects - * 1. Y plane - * 2. UV plane with line interleaving, like below - * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) - * - * This format is not YUV420(which has Y, U and V planes). - * Its closer to NV12, except that the UV plane has UV - * interleaving, like UVUVUVUVUVUVUVUVU... - * - * TODO: make this ref_frame format as a separate frame format - */ - ref_info.format = IA_CSS_FRAME_FORMAT_NV12; - delay_frames = mycs_video->delay_frames; - } - break; - case IA_CSS_PIPE_ID_PREVIEW: - { - struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview; - ref_info = mycs_preview->preview_binary.internal_frame_info; - /*The ref frame expects - * 1. Y plane - * 2. UV plane with line interleaving, like below - * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) - * - * This format is not YUV420(which has Y, U and V planes). - * Its closer to NV12, except that the UV plane has UV - * interleaving, like UVUVUVUVUVUVUVUVU... - * - * TODO: make this ref_frame format as a separate frame format - */ - ref_info.format = IA_CSS_FRAME_FORMAT_NV12; - delay_frames = mycs_preview->delay_frames; - } - break; - default: - return IA_CSS_ERR_INVALID_ARGUMENTS; - - } - - ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH; - - assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES); - for (i = 0; i < num_delay_frames; i++) { - err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info); - if (err != IA_CSS_SUCCESS) - return err; - } - IA_CSS_LEAVE_PRIVATE(""); - return IA_CSS_SUCCESS; -} - -static enum ia_css_err load_advanced_binaries( - struct ia_css_pipe *pipe) -{ - struct ia_css_frame_info pre_in_info, gdc_in_info, - post_in_info, post_out_info, - vf_info, *vf_pp_in_info, *pipe_out_info, - *pipe_vf_out_info; - bool need_pp; - bool need_isp_copy = true; - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER_PRIVATE(""); - - assert(pipe != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); - if (pipe->pipe_settings.capture.pre_isp_binary.info) - return IA_CSS_SUCCESS; - pipe_out_info = &pipe->output_info[0]; - pipe_vf_out_info = &pipe->vf_output_info[0]; - - vf_info = *pipe_vf_out_info; - err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info); - if (err != IA_CSS_SUCCESS) - return err; - need_pp = need_capture_pp(pipe); - - ia_css_frame_info_set_format(&vf_info, - IA_CSS_FRAME_FORMAT_YUV_LINE); - - /* we build up the pipeline starting at the end */ - /* Capture post-processing */ - if (need_pp) { - struct ia_css_binary_descr capture_pp_descr; - - ia_css_pipe_get_capturepp_binarydesc(pipe, - &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info); - err = ia_css_binary_find(&capture_pp_descr, - &pipe->pipe_settings.capture.capture_pp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } else { - post_out_info = *pipe_out_info; - } - - /* Post-gdc */ - { - struct ia_css_binary_descr post_gdc_descr; - - ia_css_pipe_get_post_gdc_binarydesc(pipe, - &post_gdc_descr, &post_in_info, &post_out_info, &vf_info); - err = ia_css_binary_find(&post_gdc_descr, - &pipe->pipe_settings.capture.post_isp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - - /* Gdc */ - { - struct ia_css_binary_descr gdc_descr; - - ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info, - &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); - err = ia_css_binary_find(&gdc_descr, - &pipe->pipe_settings.capture.anr_gdc_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - pipe->pipe_settings.capture.anr_gdc_binary.left_padding = - pipe->pipe_settings.capture.post_isp_binary.left_padding; - - /* Pre-gdc */ - { - struct ia_css_binary_descr pre_gdc_descr; - - ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info, - &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); - err = ia_css_binary_find(&pre_gdc_descr, - &pipe->pipe_settings.capture.pre_isp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - pipe->pipe_settings.capture.pre_isp_binary.left_padding = - pipe->pipe_settings.capture.anr_gdc_binary.left_padding; - - /* Viewfinder post-processing */ - if (need_pp) { - vf_pp_in_info = - &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info; - } else { - vf_pp_in_info = - &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info; - } - - { - struct ia_css_binary_descr vf_pp_descr; - - ia_css_pipe_get_vfpp_binarydesc(pipe, - &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); - err = ia_css_binary_find(&vf_pp_descr, - &pipe->pipe_settings.capture.vf_pp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - - /* Copy */ -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* For CSI2+, only the direct sensor mode/online requires ISP copy */ - need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#endif - if (need_isp_copy) - load_copy_binary(pipe, - &pipe->pipe_settings.capture.copy_binary, - &pipe->pipe_settings.capture.pre_isp_binary); - - return err; -} - -static enum ia_css_err load_bayer_isp_binaries( - struct ia_css_pipe *pipe) -{ - struct ia_css_frame_info pre_isp_in_info, *pipe_out_info; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_binary_descr pre_de_descr; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); - pipe_out_info = &pipe->output_info[0]; - - if (pipe->pipe_settings.capture.pre_isp_binary.info) - return IA_CSS_SUCCESS; - - err = ia_css_frame_check_info(pipe_out_info); - if (err != IA_CSS_SUCCESS) - return err; - - ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr, - &pre_isp_in_info, - pipe_out_info); - - err = ia_css_binary_find(&pre_de_descr, - &pipe->pipe_settings.capture.pre_isp_binary); - - return err; -} - -static enum ia_css_err load_low_light_binaries( - struct ia_css_pipe *pipe) -{ - struct ia_css_frame_info pre_in_info, anr_in_info, - post_in_info, post_out_info, - vf_info, *pipe_vf_out_info, *pipe_out_info, - *vf_pp_in_info; - bool need_pp; - bool need_isp_copy = true; - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); - - if (pipe->pipe_settings.capture.pre_isp_binary.info) - return IA_CSS_SUCCESS; - pipe_vf_out_info = &pipe->vf_output_info[0]; - pipe_out_info = &pipe->output_info[0]; - - vf_info = *pipe_vf_out_info; - err = ia_css_util_check_vf_out_info(pipe_out_info, - &vf_info); - if (err != IA_CSS_SUCCESS) - return err; - need_pp = need_capture_pp(pipe); - - ia_css_frame_info_set_format(&vf_info, - IA_CSS_FRAME_FORMAT_YUV_LINE); - - /* we build up the pipeline starting at the end */ - /* Capture post-processing */ - if (need_pp) { - struct ia_css_binary_descr capture_pp_descr; - - ia_css_pipe_get_capturepp_binarydesc(pipe, - &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info); - err = ia_css_binary_find(&capture_pp_descr, - &pipe->pipe_settings.capture.capture_pp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } else { - post_out_info = *pipe_out_info; - } - - /* Post-anr */ - { - struct ia_css_binary_descr post_anr_descr; - - ia_css_pipe_get_post_anr_binarydesc(pipe, - &post_anr_descr, &post_in_info, &post_out_info, &vf_info); - err = ia_css_binary_find(&post_anr_descr, - &pipe->pipe_settings.capture.post_isp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - - /* Anr */ - { - struct ia_css_binary_descr anr_descr; - - ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info, - &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); - err = ia_css_binary_find(&anr_descr, - &pipe->pipe_settings.capture.anr_gdc_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - pipe->pipe_settings.capture.anr_gdc_binary.left_padding = - pipe->pipe_settings.capture.post_isp_binary.left_padding; - - /* Pre-anr */ - { - struct ia_css_binary_descr pre_anr_descr; - - ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info, - &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); - err = ia_css_binary_find(&pre_anr_descr, - &pipe->pipe_settings.capture.pre_isp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - pipe->pipe_settings.capture.pre_isp_binary.left_padding = - pipe->pipe_settings.capture.anr_gdc_binary.left_padding; - - /* Viewfinder post-processing */ - if (need_pp) { - vf_pp_in_info = - &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info; - } else { - vf_pp_in_info = - &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info; - } - - { - struct ia_css_binary_descr vf_pp_descr; - - ia_css_pipe_get_vfpp_binarydesc(pipe, - &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); - err = ia_css_binary_find(&vf_pp_descr, - &pipe->pipe_settings.capture.vf_pp_binary); - if (err != IA_CSS_SUCCESS) - return err; - } - - /* Copy */ -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* For CSI2+, only the direct sensor mode/online requires ISP copy */ - need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#endif - if (need_isp_copy) - err = load_copy_binary(pipe, - &pipe->pipe_settings.capture.copy_binary, - &pipe->pipe_settings.capture.pre_isp_binary); - - return err; -} - -static bool copy_on_sp(struct ia_css_pipe *pipe) -{ - bool rval; - - assert(pipe != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n"); - - rval = true; - - rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE); - - rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW); - - rval &= ((pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) || - (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)); - - return rval; -} - -static enum ia_css_err load_capture_binaries( - struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - bool must_be_raw; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); - - if (pipe->pipe_settings.capture.primary_binary[0].info) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; - } - - /* in primary, advanced,low light or bayer, - the input format must be raw */ - must_be_raw = - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED || - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER || - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT; - err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - if (copy_on_sp(pipe) && - pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { - ia_css_frame_info_init( - &pipe->output_info[0], - JPEG_BYTES, - 1, - IA_CSS_FRAME_FORMAT_BINARY_8, - 0); - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; - } - - switch (pipe->config.default_capture_config.mode) { - case IA_CSS_CAPTURE_MODE_RAW: - err = load_copy_binaries(pipe); -#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401) - if (err == IA_CSS_SUCCESS) - pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; -#endif - break; - case IA_CSS_CAPTURE_MODE_BAYER: - err = load_bayer_isp_binaries(pipe); - break; - case IA_CSS_CAPTURE_MODE_PRIMARY: - err = load_primary_binaries(pipe); - break; - case IA_CSS_CAPTURE_MODE_ADVANCED: - err = load_advanced_binaries(pipe); - break; - case IA_CSS_CAPTURE_MODE_LOW_LIGHT: - err = load_low_light_binaries(pipe); - break; - } - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -static enum ia_css_err -unload_capture_binaries(struct ia_css_pipe *pipe) -{ - unsigned int i; - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - - if ((pipe == NULL) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY))) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary); - for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++) - ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]); - ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary); - ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary); - ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary); - ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary); - ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary); - ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary); - - for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++) - ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]); - - kfree(pipe->pipe_settings.capture.is_output_stage); - pipe->pipe_settings.capture.is_output_stage = NULL; - kfree(pipe->pipe_settings.capture.yuv_scaler_binary); - pipe->pipe_settings.capture.yuv_scaler_binary = NULL; - - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - -static bool -need_downscaling(const struct ia_css_resolution in_res, - const struct ia_css_resolution out_res) -{ - - if (in_res.width > out_res.width || in_res.height > out_res.height) - return true; - - return false; -} - -static bool -need_yuv_scaler_stage(const struct ia_css_pipe *pipe) -{ - unsigned int i; - struct ia_css_resolution in_res, out_res; - - bool need_format_conversion = false; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP); - - /* TODO: make generic function */ - need_format_conversion = - ((pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) && - (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8)); - - in_res = pipe->config.input_effective_res; - - if (pipe->config.enable_dz) - return true; - - if ((pipe->output_info[0].res.width != 0) && need_format_conversion) - return true; - - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - out_res = pipe->output_info[i].res; - - /* A non-zero width means it is a valid output port */ - if ((out_res.width != 0) && need_downscaling(in_res, out_res)) - return true; - } - - return false; -} - -/* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */ -/* which has some hard-coded knowledge which prevents reuse of the function. */ -/* Later, merge this with ia_css_pipe_create_cas_scaler_desc */ -static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output( - struct ia_css_frame_info *cas_scaler_in_info, - struct ia_css_frame_info *cas_scaler_out_info, - struct ia_css_frame_info *cas_scaler_vf_info, - struct ia_css_cas_binary_descr *descr) -{ - unsigned int i; - unsigned int hor_ds_factor = 0, ver_ds_factor = 0; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_frame_info tmp_in_info; - - unsigned max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP; - - assert(cas_scaler_in_info != NULL); - assert(cas_scaler_out_info != NULL); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() enter:\n"); - - /* We assume that this function is used only for single output port case. */ - descr->num_output_stage = 1; - - hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width , cas_scaler_out_info->res.width); - ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height, cas_scaler_out_info->res.height); - /* use the same horizontal and vertical downscaling factor for simplicity */ - assert(hor_ds_factor == ver_ds_factor); - - i = 1; - while (i < hor_ds_factor) { - descr->num_stage++; - i *= max_scale_factor_per_stage; - } - - descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL); - if (!descr->in_info) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - descr->internal_out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL); - if (!descr->internal_out_info) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL); - if (!descr->out_info) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL); - if (!descr->vf_info) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL); - if (!descr->is_output_stage) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - - tmp_in_info = *cas_scaler_in_info; - for (i = 0; i < descr->num_stage; i++) { - - descr->in_info[i] = tmp_in_info; - if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= cas_scaler_out_info->res.width) { - descr->is_output_stage[i] = true; - if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) { - descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width; - descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height; - descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width; - descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; - } else { - assert(i == (descr->num_stage - 1)); - descr->internal_out_info[i].res.width = 0; - descr->internal_out_info[i].res.height = 0; - } - descr->out_info[i].res.width = cas_scaler_out_info->res.width; - descr->out_info[i].res.height = cas_scaler_out_info->res.height; - descr->out_info[i].padded_width = cas_scaler_out_info->padded_width; - descr->out_info[i].format = cas_scaler_out_info->format; - if (cas_scaler_vf_info != NULL) { - descr->vf_info[i].res.width = cas_scaler_vf_info->res.width; - descr->vf_info[i].res.height = cas_scaler_vf_info->res.height; - descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width; - ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE); - } else { - descr->vf_info[i].res.width = 0; - descr->vf_info[i].res.height = 0; - descr->vf_info[i].padded_width = 0; - } - } else { - descr->is_output_stage[i] = false; - descr->internal_out_info[i].res.width = tmp_in_info.res.width / max_scale_factor_per_stage; - descr->internal_out_info[i].res.height = tmp_in_info.res.height / max_scale_factor_per_stage; - descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; - ia_css_frame_info_init(&descr->internal_out_info[i], - tmp_in_info.res.width / max_scale_factor_per_stage, - tmp_in_info.res.height / max_scale_factor_per_stage, - IA_CSS_FRAME_FORMAT_YUV420, 0); - descr->out_info[i].res.width = 0; - descr->out_info[i].res.height = 0; - descr->vf_info[i].res.width = 0; - descr->vf_info[i].res.height = 0; - } - tmp_in_info = descr->internal_out_info[i]; - } -ERR: - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n", - err); - return err; -} - -/* FIXME: merge most of this and single output version */ -static enum ia_css_err ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe *pipe, - struct ia_css_cas_binary_descr *descr) -{ - struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; - struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; - struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; - struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; - unsigned int i, j; - unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE], - ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE], - scale_factor = 0; - unsigned int num_stages = 0; - enum ia_css_err err = IA_CSS_SUCCESS; - - unsigned max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() enter:\n"); - - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - out_info[i] = NULL; - vf_out_info[i] = NULL; - hor_scale_factor[i] = 0; - ver_scale_factor[i] = 0; - } - - in_info.res = pipe->config.input_effective_res; - in_info.padded_width = in_info.res.width; - descr->num_output_stage = 0; - /* Find out how much scaling we need for each output */ - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - if (pipe->output_info[i].res.width != 0) { - out_info[i] = &pipe->output_info[i]; - if (pipe->vf_output_info[i].res.width != 0) - vf_out_info[i] = &pipe->vf_output_info[i]; - descr->num_output_stage += 1; - } - - if (out_info[i] != NULL) { - hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width); - ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height); - /* use the same horizontal and vertical scaling factor for simplicity */ - assert(hor_scale_factor[i] == ver_scale_factor[i]); - scale_factor = 1; - do { - num_stages++; - scale_factor *= max_scale_factor_per_stage; - } while (scale_factor < hor_scale_factor[i]); - - in_info.res = out_info[i]->res; - } - } - - if (need_yuv_scaler_stage(pipe) && (num_stages == 0)) - num_stages = 1; - - descr->num_stage = num_stages; - - descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL); - if (!descr->in_info) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - descr->internal_out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL); - if (!descr->internal_out_info) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL); - if (!descr->out_info) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL); - if (!descr->vf_info) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL); - if (descr->is_output_stage == NULL) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - if (out_info[i]) { - if (i > 0) { - assert((out_info[i-1]->res.width >= out_info[i]->res.width) && - (out_info[i-1]->res.height >= out_info[i]->res.height)); - } - } - } - - tmp_in_info.res = pipe->config.input_effective_res; - tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420; - for (i = 0, j = 0; i < descr->num_stage; i++) { - assert(j < 2); - assert(out_info[j] != NULL); - - descr->in_info[i] = tmp_in_info; - if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= out_info[j]->res.width) { - descr->is_output_stage[i] = true; - if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) { - descr->internal_out_info[i].res.width = out_info[j]->res.width; - descr->internal_out_info[i].res.height = out_info[j]->res.height; - descr->internal_out_info[i].padded_width = out_info[j]->padded_width; - descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; - } else { - assert(i == (descr->num_stage - 1)); - descr->internal_out_info[i].res.width = 0; - descr->internal_out_info[i].res.height = 0; - } - descr->out_info[i].res.width = out_info[j]->res.width; - descr->out_info[i].res.height = out_info[j]->res.height; - descr->out_info[i].padded_width = out_info[j]->padded_width; - descr->out_info[i].format = out_info[j]->format; - if (vf_out_info[j] != NULL) { - descr->vf_info[i].res.width = vf_out_info[j]->res.width; - descr->vf_info[i].res.height = vf_out_info[j]->res.height; - descr->vf_info[i].padded_width = vf_out_info[j]->padded_width; - ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE); - } else { - descr->vf_info[i].res.width = 0; - descr->vf_info[i].res.height = 0; - descr->vf_info[i].padded_width = 0; - } - j++; - } else { - descr->is_output_stage[i] = false; - descr->internal_out_info[i].res.width = tmp_in_info.res.width / max_scale_factor_per_stage; - descr->internal_out_info[i].res.height = tmp_in_info.res.height / max_scale_factor_per_stage; - descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; - ia_css_frame_info_init(&descr->internal_out_info[i], - tmp_in_info.res.width / max_scale_factor_per_stage, - tmp_in_info.res.height / max_scale_factor_per_stage, - IA_CSS_FRAME_FORMAT_YUV420, 0); - descr->out_info[i].res.width = 0; - descr->out_info[i].res.height = 0; - descr->vf_info[i].res.width = 0; - descr->vf_info[i].res.height = 0; - } - tmp_in_info = descr->internal_out_info[i]; - } -ERR: - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n", - err); - return err; -} - -static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr *descr) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_destroy_cas_scaler_desc() enter:\n"); - kfree(descr->in_info); - descr->in_info = NULL; - kfree(descr->internal_out_info); - descr->internal_out_info = NULL; - kfree(descr->out_info); - descr->out_info = NULL; - kfree(descr->vf_info); - descr->vf_info = NULL; - kfree(descr->is_output_stage); - descr->is_output_stage = NULL; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_destroy_cas_scaler_desc() leave\n"); -} - -static enum ia_css_err -load_yuvpp_binaries(struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - bool need_scaler = false; - struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; - struct ia_css_yuvpp_settings *mycs; - struct ia_css_binary *next_binary; - struct ia_css_cas_binary_descr cas_scaler_descr = { }; - unsigned int i, j; - bool need_isp_copy_binary = false; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->stream != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP); - - if (pipe->pipe_settings.yuvpp.copy_binary.info) - goto ERR; - - /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */ - err = ia_css_util_check_input(&pipe->stream->config, false, false); - if (err != IA_CSS_SUCCESS) - goto ERR; - - mycs = &pipe->pipe_settings.yuvpp; - - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - if (pipe->vf_output_info[i].res.width != 0) { - err = ia_css_util_check_vf_out_info(&pipe->output_info[i], - &pipe->vf_output_info[i]); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - vf_pp_in_info[i] = NULL; - } - - need_scaler = need_yuv_scaler_stage(pipe); - - /* we build up the pipeline starting at the end */ - /* Capture post-processing */ - if (need_scaler) { - struct ia_css_binary_descr yuv_scaler_descr; - - err = ia_css_pipe_create_cas_scaler_desc(pipe, - &cas_scaler_descr); - if (err != IA_CSS_SUCCESS) - goto ERR; - mycs->num_output = cas_scaler_descr.num_output_stage; - mycs->num_yuv_scaler = cas_scaler_descr.num_stage; - mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * - sizeof(struct ia_css_binary), GFP_KERNEL); - if (!mycs->yuv_scaler_binary) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage * - sizeof(bool), GFP_KERNEL); - if (!mycs->is_output_stage) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - for (i = 0; i < cas_scaler_descr.num_stage; i++) { - mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; - ia_css_pipe_get_yuvscaler_binarydesc(pipe, - &yuv_scaler_descr, &cas_scaler_descr.in_info[i], - &cas_scaler_descr.out_info[i], - &cas_scaler_descr.internal_out_info[i], - &cas_scaler_descr.vf_info[i]); - err = ia_css_binary_find(&yuv_scaler_descr, - &mycs->yuv_scaler_binary[i]); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); - } else { - mycs->num_output = 1; - } - - if (need_scaler) { - next_binary = &mycs->yuv_scaler_binary[0]; - } else { - next_binary = NULL; - } - -#if defined(USE_INPUT_SYSTEM_VERSION_2401) - /* - * NOTES - * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when - * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"? - * - * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_ - * binary". However, the "yuv_scale_binary" does NOT support the input-frame - * format as "IA_CSS_STREAM _FORMAT_YUV422_8". - * - * Hence, the "isp_copy_binary" is required to be present in front of the "yuv - * _scale_binary". It would translate the input-frame to the frame formats that - * are supported by the "yuv_scale_binary". - * - * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_ - * pp_defs.h" for the list of input-frame formats that are supported by the - * "yuv_scale_binary". - */ - need_isp_copy_binary = - (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); -#else /* !USE_INPUT_SYSTEM_VERSION_2401 */ - need_isp_copy_binary = true; -#endif /* USE_INPUT_SYSTEM_VERSION_2401 */ - - if (need_isp_copy_binary) { - err = load_copy_binary(pipe, - &mycs->copy_binary, - next_binary); - - if (err != IA_CSS_SUCCESS) - goto ERR; - - /* - * NOTES - * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified? - * - * In some use cases, the first stage in the "yuvpp" pipe is the - * "isp_copy_binary". The "isp_copy_binary" is designed to process - * the input from either the system DDR or from the IPU internal VMEM. - * So it provides the flag "online" to specify where its input is from, - * i.e.: - * - * (1) "online <= true", the input is from the IPU internal VMEM. - * (2) "online <= false", the input is from the system DDR. - * - * In other use cases, the first stage in the "yuvpp" pipe is the - * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the - * input ONLY from the system DDR. So it does not provide the flag "online" - * to specify where its input is from. - */ - pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; - } - - /* Viewfinder post-processing */ - if (need_scaler) { - for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) { - if (mycs->is_output_stage[i]) { - assert(j < 2); - vf_pp_in_info[j] = - &mycs->yuv_scaler_binary[i].vf_frame_info; - j++; - } - } - mycs->num_vf_pp = j; - } else { - vf_pp_in_info[0] = - &mycs->copy_binary.vf_frame_info; - for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - vf_pp_in_info[i] = NULL; - } - mycs->num_vf_pp = 1; - } - mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary), - GFP_KERNEL); - if (!mycs->vf_pp_binary) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - goto ERR; - } - - { - struct ia_css_binary_descr vf_pp_descr; - - for (i = 0; i < mycs->num_vf_pp; i++) { - if (pipe->vf_output_info[i].res.width != 0) { - ia_css_pipe_get_vfpp_binarydesc(pipe, - &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]); - err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - } - } - - if (err != IA_CSS_SUCCESS) - goto ERR; - -ERR: - if (need_scaler) { - ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n", - err); - return err; -} - -static enum ia_css_err -unload_yuvpp_binaries(struct ia_css_pipe *pipe) -{ - unsigned int i; - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - - if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary); - for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++) { - ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]); - } - for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++) { - ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]); - } - kfree(pipe->pipe_settings.yuvpp.is_output_stage); - pipe->pipe_settings.yuvpp.is_output_stage = NULL; - kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary); - pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL; - kfree(pipe->pipe_settings.yuvpp.vf_pp_binary); - pipe->pipe_settings.yuvpp.vf_pp_binary = NULL; - - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - -static enum ia_css_err yuvpp_start(struct ia_css_pipe *pipe) -{ - struct ia_css_binary *copy_binary; - enum ia_css_err err = IA_CSS_SUCCESS; - enum sh_css_pipe_config_override copy_ovrd; - enum ia_css_input_mode yuvpp_pipe_input_mode; - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - yuvpp_pipe_input_mode = pipe->stream->config.mode; - - copy_binary = &pipe->pipe_settings.yuvpp.copy_binary; - - sh_css_metrics_start_frame(); - - /* multi stream video needs mipi buffers */ - -#if !defined(HAS_NO_INPUT_SYSTEM) && ( defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) ) - err = send_mipi_frames(pipe); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } -#endif - - { - unsigned int thread_id; - - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - copy_ovrd = 1 << thread_id; - } - - start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode); - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -static enum ia_css_err -sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - - if (pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ - if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; - } - - switch (pipe->mode) { - case IA_CSS_PIPE_ID_PREVIEW: - err = unload_preview_binaries(pipe); - break; - case IA_CSS_PIPE_ID_VIDEO: - err = unload_video_binaries(pipe); - break; - case IA_CSS_PIPE_ID_CAPTURE: - err = unload_capture_binaries(pipe); - break; - case IA_CSS_PIPE_ID_YUVPP: - err = unload_yuvpp_binaries(pipe); - break; - default: - break; - } - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -static enum ia_css_err -sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - assert(pipe != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n"); - - /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ - if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) - return err; - - switch (pipe->mode) { - case IA_CSS_PIPE_ID_PREVIEW: - err = load_preview_binaries(pipe); - break; - case IA_CSS_PIPE_ID_VIDEO: - err = load_video_binaries(pipe); - break; - case IA_CSS_PIPE_ID_CAPTURE: - err = load_capture_binaries(pipe); - break; - case IA_CSS_PIPE_ID_YUVPP: - err = load_yuvpp_binaries(pipe); - break; - case IA_CSS_PIPE_ID_ACC: - break; - default: - err = IA_CSS_ERR_INTERNAL_ERROR; - break; - } - if (err != IA_CSS_SUCCESS) { - if (sh_css_pipe_unload_binaries(pipe) != IA_CSS_SUCCESS) { - /* currently css does not support multiple error returns in a single function, - * using IA_CSS_ERR_INTERNAL_ERROR in this case */ - err = IA_CSS_ERR_INTERNAL_ERROR; - } - } - return err; -} - -static enum ia_css_err -create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) -{ - struct ia_css_pipeline *me; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_pipeline_stage *vf_pp_stage = NULL, - *copy_stage = NULL, - *yuv_scaler_stage = NULL; - struct ia_css_binary *copy_binary, - *vf_pp_binary, - *yuv_scaler_binary; - bool need_scaler = false; - unsigned int num_stage, num_vf_pp_stage, num_output_stage; - unsigned int i, j; - - struct ia_css_frame *in_frame = NULL; - struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; - struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; - struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; - struct ia_css_pipeline_stage_desc stage_desc; - bool need_in_frameinfo_memory = false; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - bool sensor = false; - bool buffered_sensor = false; - bool online = false; - bool continuous = false; -#endif - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - me = &pipe->pipeline; - ia_css_pipeline_clean(me); - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - out_frame[i] = NULL; - vf_frame[i] = NULL; - } - ia_css_pipe_util_create_output_frames(bin_out_frame); - num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler; - num_vf_pp_stage = pipe->pipe_settings.yuvpp.num_vf_pp; - num_output_stage = pipe->pipe_settings.yuvpp.num_output; - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Continuous Capture - * - Buffered Sensor Mode Continuous Capture - */ - sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; - buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && continuous)); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif - /* the input frame can come from: - * a) memory: connect yuvscaler to me->in_frame - * b) sensor, via copy binary: connect yuvscaler to copy binary later on */ - if (need_in_frameinfo_memory) { - /* TODO: improve for different input formats. */ - - /* - * "pipe->stream->config.input_config.format" represents the sensor output - * frame format, e.g. YUV422 8-bit. - * - * "in_frame_format" represents the imaging pipe's input frame format, e.g. - * Bayer-Quad RAW. - */ - int in_frame_format; - if (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) { - in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8; - } else if (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8) { - /* - * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8", - * the "isp_copy_var" binary is selected as the first stage in the yuvpp - * pipe. - * - * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from - * the frame buffer (at DDR) to the frame-line buffer (at VMEM). - * - * By now, the "isp_copy_var" binary does NOT provide a separated - * frame-line buffer to store the YUV422-8 pixels. Instead, it stores - * the YUV422-8 pixels in the frame-line buffer which is designed to - * store the Bayer-Quad RAW pixels. - * - * To direct the "isp_copy_var" binary reading from the RAW frame-line - * buffer, its input frame format must be specified as "IA_CSS_FRAME_ - * FORMAT_RAW". - */ - in_frame_format = IA_CSS_FRAME_FORMAT_RAW; - } else { - in_frame_format = IA_CSS_FRAME_FORMAT_NV12; - } - - err = init_in_frameinfo_memory_defaults(pipe, - &me->in_frame, - in_frame_format); - - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - in_frame = &me->in_frame; - } else { - in_frame = NULL; - } - - for (i = 0; i < num_output_stage; i++) { - assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE); - if (pipe->output_info[i].res.width != 0) { - err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - out_frame[i] = &me->out_frame[i]; - } - - /* Construct vf_frame info (only in case we have VF) */ - if (pipe->vf_output_info[i].res.width != 0) { - err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - vf_frame[i] = &me->vf_frame[i]; - } - } - - copy_binary = &pipe->pipe_settings.yuvpp.copy_binary; - vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary; - yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary; - need_scaler = need_yuv_scaler_stage(pipe); - - if (pipe->pipe_settings.yuvpp.copy_binary.info) { - - struct ia_css_frame *in_frame_local = NULL; - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* After isp copy is enabled in_frame needs to be passed. */ - if (!online) - in_frame_local = in_frame; -#endif - - if (need_scaler) { - ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, - bin_out_frame, in_frame_local, NULL); - } else { - ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]); - ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, - bin_out_frame, in_frame_local, NULL); - } - - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - ©_stage); - - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - if (copy_stage) { - /* if we use yuv scaler binary, vf output should be from there */ - copy_stage->args.copy_vf = !need_scaler; - /* for yuvpp pipe, it should always be enabled */ - copy_stage->args.copy_output = true; - /* connect output of copy binary to input of yuv scaler */ - in_frame = copy_stage->args.out_frame[0]; - } - } - - if (need_scaler) { - struct ia_css_frame *tmp_out_frame = NULL; - struct ia_css_frame *tmp_vf_frame = NULL; - struct ia_css_frame *tmp_in_frame = in_frame; - - for (i = 0, j = 0; i < num_stage; i++) { - assert(j < num_output_stage); - if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { - tmp_out_frame = out_frame[j]; - tmp_vf_frame = vf_frame[j]; - } else { - tmp_out_frame = NULL; - tmp_vf_frame = NULL; - } - - err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, - NULL, - &yuv_scaler_binary[i], - &yuv_scaler_stage); - - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - /* we use output port 1 as internal output port */ - tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; - if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { - if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) { - in_frame = yuv_scaler_stage->args.out_vf_frame; - err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j], - &vf_pp_stage); - - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - j++; - } - } - } else if (copy_stage != NULL) { - if (vf_frame[0] != NULL && vf_frame[0]->info.res.width != 0) { - in_frame = copy_stage->args.out_vf_frame; - err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0], - &vf_pp_stage); - } - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - - ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); - - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -create_host_copy_pipeline(struct ia_css_pipe *pipe, - unsigned max_input_width, - struct ia_css_frame *out_frame) -{ - struct ia_css_pipeline *me; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_pipeline_stage_desc stage_desc; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "create_host_copy_pipeline() enter:\n"); - - /* pipeline already created as part of create_host_pipeline_structure */ - me = &pipe->pipeline; - ia_css_pipeline_clean(me); - - /* Construct out_frame info */ - out_frame->contiguous = false; - out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; - - if (copy_on_sp(pipe) && - pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { - ia_css_frame_info_init( - &out_frame->info, - JPEG_BYTES, - 1, - IA_CSS_FRAME_FORMAT_BINARY_8, - 0); - } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) { - out_frame->info.raw_bit_depth = - ia_css_pipe_util_pipe_input_format_bpp(pipe); - } - - me->num_stages = 1; - me->pipe_id = IA_CSS_PIPE_ID_COPY; - pipe->mode = IA_CSS_PIPE_ID_COPY; - - ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, - IA_CSS_PIPELINE_RAW_COPY, max_input_width); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - NULL); - - ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "create_host_copy_pipeline() leave:\n"); - - return err; -} - -static enum ia_css_err -create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) -{ - struct ia_css_pipeline *me = &pipe->pipeline; - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_pipeline_stage_desc stage_desc; - struct ia_css_frame *out_frame = &me->out_frame[0]; - struct ia_css_pipeline_stage *out_stage = NULL; - unsigned int thread_id; - enum sh_css_queue_id queue_id; - unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "create_host_isyscopy_capture_pipeline() enter:\n"); - ia_css_pipeline_clean(me); - - /* Construct out_frame info */ - err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0); - if (err != IA_CSS_SUCCESS) - return err; - out_frame->contiguous = false; - out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id); - out_frame->dynamic_queue_id = queue_id; - out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; - - me->num_stages = 1; - me->pipe_id = IA_CSS_PIPE_ID_CAPTURE; - pipe->mode = IA_CSS_PIPE_ID_CAPTURE; - ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, - IA_CSS_PIPELINE_ISYS_COPY, max_input_width); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, &out_stage); - if(err != IA_CSS_SUCCESS) - return err; - - ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "create_host_isyscopy_capture_pipeline() leave:\n"); - - return err; -} - -static enum ia_css_err -create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) -{ - struct ia_css_pipeline *me; - enum ia_css_err err = IA_CSS_SUCCESS; - enum ia_css_capture_mode mode; - struct ia_css_pipeline_stage *current_stage = NULL; - struct ia_css_pipeline_stage *yuv_scaler_stage = NULL; - struct ia_css_binary *copy_binary, - *primary_binary[MAX_NUM_PRIMARY_STAGES], - *vf_pp_binary, - *pre_isp_binary, - *anr_gdc_binary, - *post_isp_binary, - *yuv_scaler_binary, - *capture_pp_binary, - *capture_ldc_binary; - bool need_pp = false; - bool raw; - - struct ia_css_frame *in_frame; - struct ia_css_frame *out_frame; - struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; - struct ia_css_frame *vf_frame; - struct ia_css_pipeline_stage_desc stage_desc; - bool need_in_frameinfo_memory = false; -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - bool sensor = false; - bool buffered_sensor = false; - bool online = false; - bool continuous = false; -#endif - unsigned int i, num_yuv_scaler, num_primary_stage; - bool need_yuv_pp = false; - bool *is_output_stage = NULL; - bool need_ldc = false; - - IA_CSS_ENTER_PRIVATE(""); - assert(pipe != NULL); - assert(pipe->stream != NULL); - assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); - - me = &pipe->pipeline; - mode = pipe->config.default_capture_config.mode; - raw = (mode == IA_CSS_CAPTURE_MODE_RAW); - ia_css_pipeline_clean(me); - ia_css_pipe_util_create_output_frames(out_frames); - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - /* When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Continuous Capture - * - Buffered Sensor Mode Continuous Capture - */ - sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); - buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif - if (need_in_frameinfo_memory) { - err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - in_frame = &me->in_frame; - } else { - in_frame = NULL; - } - - err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - out_frame = &me->out_frame[0]; - - /* Construct vf_frame info (only in case we have VF) */ - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { - if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) { - /* These modes don't support viewfinder output */ - vf_frame = NULL; - } else { - init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0); - vf_frame = &me->vf_frame[0]; - } - } else { - vf_frame = NULL; - } - - copy_binary = &pipe->pipe_settings.capture.copy_binary; - num_primary_stage = pipe->pipe_settings.capture.num_primary_stage; - if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - for (i = 0; i < num_primary_stage; i++) { - primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i]; - } - vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary; - pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary; - anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary; - post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary; - capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary; - yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary; - num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler; - is_output_stage = pipe->pipe_settings.capture.is_output_stage; - capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary; - - need_pp = (need_capture_pp(pipe) || pipe->output_stage) && - mode != IA_CSS_CAPTURE_MODE_RAW && - mode != IA_CSS_CAPTURE_MODE_BAYER; - need_yuv_pp = (yuv_scaler_binary != NULL && yuv_scaler_binary->info != NULL); - need_ldc = (capture_ldc_binary != NULL && capture_ldc_binary->info != NULL); - - if (pipe->pipe_settings.capture.copy_binary.info) { - if (raw) { - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); -#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401) - if (!continuous) { - ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, - out_frames, in_frame, NULL); - } else { - in_frame = pipe->stream->last_pipe->continuous_frames[0]; - ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, - out_frames, in_frame, NULL); - } -#else - ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, - out_frames, NULL, NULL); -#endif - } else { - ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, - out_frames, NULL, NULL); - } - - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - ¤t_stage); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } else if (pipe->stream->config.continuous) { - in_frame = pipe->stream->last_pipe->continuous_frames[0]; - } - - if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) { - struct ia_css_frame *local_in_frame = NULL; - struct ia_css_frame *local_out_frame = NULL; - - for (i = 0; i < num_primary_stage; i++) { - if (i == 0) - local_in_frame = in_frame; - else - local_in_frame = NULL; -#ifndef ISP2401 - if (!need_pp && (i == num_primary_stage - 1)) -#else - if (!need_pp && (i == num_primary_stage - 1) && !need_ldc) -#endif - local_out_frame = out_frame; - else - local_out_frame = NULL; - ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame); -/* - * WARNING: The #if def flag has been added below as a - * temporary solution to solve the problem of enabling the - * view finder in a single binary in a capture flow. The - * vf-pp stage has been removed from Skycam in the solution - * provided. The vf-pp stage should be re-introduced when - * required. This * should not be considered as a clean solution. - * Proper investigation should be done to come up with the clean - * solution. - * */ - ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i], - out_frames, local_in_frame, NULL); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - ¤t_stage); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - /* If we use copy iso primary, - the input must be yuv iso raw */ - current_stage->args.copy_vf = - primary_binary[0]->info->sp.pipeline.mode == - IA_CSS_BINARY_MODE_COPY; - current_stage->args.copy_output = current_stage->args.copy_vf; - } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED || - mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, - out_frames, in_frame, NULL); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, NULL); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary, - out_frames, NULL, NULL); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, NULL); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - if(need_pp) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary, - out_frames, NULL, NULL); - } else { - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary, - out_frames, NULL, NULL); - } - - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, ¤t_stage); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) { - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, - out_frames, in_frame, NULL); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - NULL); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - -#ifndef ISP2401 - if (need_pp && current_stage) { - struct ia_css_frame *local_in_frame = NULL; - local_in_frame = current_stage->args.out_frame[0]; - - if(need_ldc) { - ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); - ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, - out_frames, local_in_frame, NULL); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - ¤t_stage); - local_in_frame = current_stage->args.out_frame[0]; - } - err = add_capture_pp_stage(pipe, me, local_in_frame, need_yuv_pp ? NULL : out_frame, -#else - /* ldc and capture_pp not supported in same pipeline */ - if (need_ldc && current_stage) { - in_frame = current_stage->args.out_frame[0]; - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, - out_frames, in_frame, NULL); - err = ia_css_pipeline_create_and_add_stage(me, - &stage_desc, - NULL); - } else if (need_pp && current_stage) { - in_frame = current_stage->args.out_frame[0]; - err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame, -#endif - capture_pp_binary, - ¤t_stage); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - - if (need_yuv_pp && current_stage) { - struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0]; - struct ia_css_frame *tmp_out_frame = NULL; - - for (i = 0; i < num_yuv_scaler; i++) { - if (is_output_stage[i] == true) - tmp_out_frame = out_frame; - else - tmp_out_frame = NULL; - - err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, - NULL, - &yuv_scaler_binary[i], - &yuv_scaler_stage); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - /* we use output port 1 as internal output port */ - tmp_in_frame = yuv_scaler_stage->args.out_frame[1]; - } - } - -/* - * WARNING: The #if def flag has been added below as a - * temporary solution to solve the problem of enabling the - * view finder in a single binary in a capture flow. The vf-pp - * stage has been removed from Skycam in the solution provided. - * The vf-pp stage should be re-introduced when required. This - * should not be considered as a clean solution. Proper - * investigation should be done to come up with the clean solution. - * */ - if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) { - in_frame = current_stage->args.out_vf_frame; - err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary, - ¤t_stage); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "create_host_regular_capture_pipeline() leave:\n"); - - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -create_host_capture_pipeline(struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - - if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) - err = create_host_isyscopy_capture_pipeline(pipe); - else - err = create_host_regular_capture_pipeline(pipe); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - IA_CSS_LEAVE_ERR_PRIVATE(err); - - return err; -} - -static enum ia_css_err capture_start( - struct ia_css_pipe *pipe) -{ - struct ia_css_pipeline *me; - - enum ia_css_err err = IA_CSS_SUCCESS; - enum sh_css_pipe_config_override copy_ovrd; - - IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); - if (pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - me = &pipe->pipeline; - - if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ) && - (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { - if (copy_on_sp(pipe)) { - err = start_copy_on_sp(pipe, &me->out_frame[0]); - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - -#if defined(USE_INPUT_SYSTEM_VERSION_2) - /* old isys: need to send_mipi_frames() in all pipe modes */ - err = send_mipi_frames(pipe); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } -#elif defined(USE_INPUT_SYSTEM_VERSION_2401) - if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) { - err = send_mipi_frames(pipe); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - -#endif - - { - unsigned int thread_id; - - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - copy_ovrd = 1 << thread_id; - - } - start_pipe(pipe, copy_ovrd, pipe->stream->config.mode); - -#if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401) - /* - * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured, - * which is currently done in start_binary(); but COPY pipe contains no binary, - * and does not call start_binary(); so we need to configure the rx here. - */ - if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY && pipe->stream->reconfigure_css_rx) { - ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, pipe->stream->config.mode); - pipe->stream->reconfigure_css_rx = false; - } -#endif - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - -} - -static enum ia_css_err -sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, - struct ia_css_frame_info *info, - unsigned int idx) -{ - assert(pipe != NULL); - assert(info != NULL); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_pipe_get_output_frame_info() enter:\n"); - - *info = pipe->output_info[idx]; - if (copy_on_sp(pipe) && - pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { - ia_css_frame_info_init( - info, - JPEG_BYTES, - 1, - IA_CSS_FRAME_FORMAT_BINARY_8, - 0); - } else if (info->format == IA_CSS_FRAME_FORMAT_RAW || - info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) { - info->raw_bit_depth = - ia_css_pipe_util_pipe_input_format_bpp(pipe); - - } - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_pipe_get_output_frame_info() leave:\n"); - return IA_CSS_SUCCESS; -} - -#if !defined(HAS_NO_INPUT_SYSTEM) -void -ia_css_stream_send_input_frame(const struct ia_css_stream *stream, - const unsigned short *data, - unsigned int width, - unsigned int height) -{ - assert(stream != NULL); - - ia_css_inputfifo_send_input_frame( - data, width, height, - stream->config.channel_id, - stream->config.input_config.format, - stream->config.pixels_per_clock == 2); -} - -void -ia_css_stream_start_input_frame(const struct ia_css_stream *stream) -{ - assert(stream != NULL); - - ia_css_inputfifo_start_frame( - stream->config.channel_id, - stream->config.input_config.format, - stream->config.pixels_per_clock == 2); -} - -void -ia_css_stream_send_input_line(const struct ia_css_stream *stream, - const unsigned short *data, - unsigned int width, - const unsigned short *data2, - unsigned int width2) -{ - assert(stream != NULL); - - ia_css_inputfifo_send_line(stream->config.channel_id, - data, width, data2, width2); -} - -void -ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream, - enum atomisp_input_format format, - const unsigned short *data, - unsigned int width) -{ - assert(stream != NULL); - if (data == NULL || width == 0) - return; - ia_css_inputfifo_send_embedded_line(stream->config.channel_id, - format, data, width); -} - -void -ia_css_stream_end_input_frame(const struct ia_css_stream *stream) -{ - assert(stream != NULL); - - ia_css_inputfifo_end_frame(stream->config.channel_id); -} -#endif - -static void -append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) -{ - IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l , firmware); - if (l == NULL) { - IA_CSS_ERROR("NULL fw_info"); - IA_CSS_LEAVE_PRIVATE(""); - return; - } - while (*l) - l = &(*l)->next; - *l = firmware; - /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */ - IA_CSS_LEAVE_PRIVATE(""); -} - -static void -remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) -{ - assert(*l); - assert(firmware); - (void)l; - (void)firmware; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n"); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n"); - return; /* removing single and multiple firmware is handled in acc_unload_extension() */ -} - -static enum ia_css_err upload_isp_code(struct ia_css_fw_info *firmware) -{ - hrt_vaddress binary; - - if (firmware == NULL) { - IA_CSS_ERROR("NULL input parameter"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - binary = firmware->info.isp.xmem_addr; - - if (!binary) { - unsigned size = firmware->blob.size; - const unsigned char *blob; - const unsigned char *binary_name; - binary_name = - (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME( - firmware)); - blob = binary_name + - strlen((const char *)binary_name) + - 1; - binary = sh_css_load_blob(blob, size); - firmware->info.isp.xmem_addr = binary; - } - - if (!binary) - return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -acc_load_extension(struct ia_css_fw_info *firmware) -{ - enum ia_css_err err; - struct ia_css_fw_info *hd = firmware; - while (hd){ - err = upload_isp_code(hd); - if (err != IA_CSS_SUCCESS) - return err; - hd = hd->next; - } - - if (firmware == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - firmware->loaded = true; - return IA_CSS_SUCCESS; -} - -static void -acc_unload_extension(struct ia_css_fw_info *firmware) -{ - struct ia_css_fw_info *hd = firmware; - struct ia_css_fw_info *hdn = NULL; - - if (firmware == NULL) /* should not happen */ - return; - /* unload and remove multiple firmwares */ - while (hd){ - hdn = (hd->next) ? &(*hd->next) : NULL; - if (hd->info.isp.xmem_addr) { - hmm_free(hd->info.isp.xmem_addr); - hd->info.isp.xmem_addr = mmgr_NULL; - } - hd->isp_code = NULL; - hd->next = NULL; - hd = hdn; - } - - firmware->loaded = false; -} -/* Load firmware for extension */ -static enum ia_css_err -ia_css_pipe_load_extension(struct ia_css_pipe *pipe, - struct ia_css_fw_info *firmware) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); - - if ((firmware == NULL) || (pipe == NULL)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT) { - if (&pipe->output_stage != NULL) - append_firmware(&pipe->output_stage, firmware); - else { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - } - else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER) { - if (&pipe->vf_stage != NULL) - append_firmware(&pipe->vf_stage, firmware); - else { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR); - return IA_CSS_ERR_INTERNAL_ERROR; - } - } - err = acc_load_extension(firmware); - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -/* Unload firmware for extension */ -static void -ia_css_pipe_unload_extension(struct ia_css_pipe *pipe, - struct ia_css_fw_info *firmware) -{ - IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); - - if ((firmware == NULL) || (pipe == NULL)) { - IA_CSS_ERROR("NULL input parameters"); - IA_CSS_LEAVE_PRIVATE(""); - return; - } - - if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT) - remove_firmware(&pipe->output_stage, firmware); - else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER) - remove_firmware(&pipe->vf_stage, firmware); - acc_unload_extension(firmware); - - IA_CSS_LEAVE_PRIVATE(""); -} - -bool -ia_css_pipeline_uses_params(struct ia_css_pipeline *me) -{ - struct ia_css_pipeline_stage *stage; - - assert(me != NULL); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_pipeline_uses_params() enter: me=%p\n", me); - - for (stage = me->stages; stage; stage = stage->next) - if (stage->binary_info && stage->binary_info->enable.params) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_pipeline_uses_params() leave: " - "return_bool=true\n"); - return true; - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_pipeline_uses_params() leave: return_bool=false\n"); - return false; -} - -static enum ia_css_err -sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, - const void *acc_fw) -{ - struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw; - /* In QoS case, load_extension already called, so skipping */ - enum ia_css_err err = IA_CSS_SUCCESS; - if (fw->loaded == false) - err = acc_load_extension(fw); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "sh_css_pipeline_add_acc_stage() enter: pipeline=%p," - " acc_fw=%p\n", pipeline, acc_fw); - - if (err == IA_CSS_SUCCESS) { - struct ia_css_pipeline_stage_desc stage_desc; - ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw); - err = ia_css_pipeline_create_and_add_stage(pipeline, - &stage_desc, - NULL); - } - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n",err); - return err; -} - -/* - * @brief Tag a specific frame in continuous capture. - * Refer to "sh_css_internal.h" for details. - */ -enum ia_css_err ia_css_stream_capture_frame(struct ia_css_stream *stream, - unsigned int exp_id) -{ - struct sh_css_tag_descr tag_descr; - uint32_t encoded_tag_descr; - enum ia_css_err err; - - assert(stream != NULL); - IA_CSS_ENTER("exp_id=%d", exp_id); - - /* Only continuous streams have a tagger */ - if (exp_id == 0 || !stream->config.continuous) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if (!sh_css_sp_is_running()) { - /* SP is not running. The queues are not valid */ - IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE); - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - - /* Create the tag descriptor from the parameters */ - sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr); - /* Encode the tag descriptor into a 32-bit value */ - encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); - /* Enqueue the encoded tag to the host2sp queue. - * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 - * on both host and the SP side. - * It is mainly because it is enough to have only one tag_cmd queue */ - err= ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr); - - IA_CSS_LEAVE_ERR(err); - return err; -} - -/* - * @brief Configure the continuous capture. - * Refer to "sh_css_internal.h" for details. - */ -enum ia_css_err ia_css_stream_capture( - struct ia_css_stream *stream, - int num_captures, - unsigned int skip, - int offset) -{ - struct sh_css_tag_descr tag_descr; - unsigned int encoded_tag_descr; - enum ia_css_err return_err; - - if (stream == NULL) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_stream_capture() enter: num_captures=%d," - " skip=%d, offset=%d\n", num_captures, skip,offset); - - /* Check if the tag descriptor is valid */ - if (num_captures < SH_CSS_MINIMUM_TAG_ID) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_stream_capture() leave: return_err=%d\n", - IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - /* Create the tag descriptor from the parameters */ - sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr); - - - /* Encode the tag descriptor into a 32-bit value */ - encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); - - if (!sh_css_sp_is_running()) { - /* SP is not running. The queues are not valid */ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_stream_capture() leaving:" - "queues unavailable\n"); - return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } - - /* Enqueue the encoded tag to the host2sp queue. - * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 - * on both host and the SP side. - * It is mainly because it is enough to have only one tag_cmd queue */ - return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr); - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_stream_capture() leave: return_err=%d\n", - return_err); - - return return_err; -} - -void ia_css_stream_request_flash(struct ia_css_stream *stream) -{ - (void)stream; - - assert(stream != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_request_flash() enter: void\n"); - -#ifndef ISP2401 - sh_css_write_host2sp_command(host2sp_cmd_start_flash); -#else - if (sh_css_sp_is_running()) { - if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) { - IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); - ia_css_debug_dump_sp_sw_debug_info(); - ia_css_debug_dump_debug_info(NULL); - } - } else - IA_CSS_LOG("SP is not running!"); - -#endif - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_stream_request_flash() leave: return_void\n"); -} - -static void -sh_css_init_host_sp_control_vars(void) -{ - const struct ia_css_fw_info *fw; - unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started; - - unsigned int HIVE_ADDR_host_sp_queues_initialized; - unsigned int HIVE_ADDR_sp_sleep_mode; - unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; -#ifndef ISP2401 - unsigned int HIVE_ADDR_sp_stop_copy_preview; -#endif - unsigned int HIVE_ADDR_host_sp_com; - unsigned int o = offsetof(struct host_sp_communication, host2sp_command) - / sizeof(int); - -#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) - unsigned int i; -#endif - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_init_host_sp_control_vars() enter: void\n"); - - fw = &sh_css_sp_fw; - HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started; - - HIVE_ADDR_host_sp_queues_initialized = - fw->info.sp.host_sp_queues_initialized; - HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode; - HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb; -#ifndef ISP2401 - HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview; -#endif - HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; - - (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */ - - (void)HIVE_ADDR_sp_sleep_mode; - (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; -#ifndef ISP2401 - (void)HIVE_ADDR_sp_stop_copy_preview; -#endif - (void)HIVE_ADDR_host_sp_com; - - sp_dmem_store_uint32(SP0_ID, - (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started), - (uint32_t)(0)); - - sp_dmem_store_uint32(SP0_ID, - (unsigned int)sp_address_of(host_sp_queues_initialized), - (uint32_t)(0)); - sp_dmem_store_uint32(SP0_ID, - (unsigned int)sp_address_of(sp_sleep_mode), - (uint32_t)(0)); - sp_dmem_store_uint32(SP0_ID, - (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb), - (uint32_t)(false)); -#ifndef ISP2401 - sp_dmem_store_uint32(SP0_ID, - (unsigned int)sp_address_of(sp_stop_copy_preview), - my_css.stop_copy_preview?(uint32_t)(1):(uint32_t)(0)); -#endif - store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready); - -#if !defined(HAS_NO_INPUT_SYSTEM) - for (i = 0; i < N_CSI_PORTS; i++) { - sh_css_update_host2sp_num_mipi_frames - (my_css.num_mipi_frames[i]); - } -#endif - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_init_host_sp_control_vars() leave: return_void\n"); -} - -/* - * create the internal structures and fill in the configuration data - */ -void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n"); - *pipe_config = DEFAULT_PIPE_CONFIG; -} - -void -ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config) -{ - if (extra_config == NULL) { - IA_CSS_ERROR("NULL input parameter"); - return; - } - - extra_config->enable_raw_binning = false; - extra_config->enable_yuv_ds = false; - extra_config->enable_high_speed = false; - extra_config->enable_dvs_6axis = false; - extra_config->enable_reduced_pipe = false; - extra_config->disable_vf_pp = false; - extra_config->enable_fractional_ds = false; -} - -void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n"); - assert(stream_config != NULL); - memset(stream_config, 0, sizeof(*stream_config)); - stream_config->online = true; - stream_config->left_padding = -1; - stream_config->pixels_per_clock = 1; - /* temporary default value for backwards compatibility. - * This field used to be hardcoded within CSS but this has now - * been moved to the stream_config struct. */ - stream_config->source.port.rxcount = 0x04040404; -} - -static enum ia_css_err -ia_css_acc_pipe_create(struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - if (pipe == NULL) { - IA_CSS_ERROR("NULL input parameter"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - /* There is not meaning for num_execs = 0 semantically. Run atleast once. */ - if (pipe->config.acc_num_execs == 0) - pipe->config.acc_num_execs = 1; - - if (pipe->config.acc_extension) { - err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension); - } - - return err; -} - -enum ia_css_err -ia_css_pipe_create(const struct ia_css_pipe_config *config, - struct ia_css_pipe **pipe) -{ -#ifndef ISP2401 - if (config == NULL) -#else - enum ia_css_err err = IA_CSS_SUCCESS; - IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe); - - if (config == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); -#endif - return IA_CSS_ERR_INVALID_ARGUMENTS; -#ifndef ISP2401 - if (pipe == NULL) -#else - } - if (pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); -#endif - return IA_CSS_ERR_INVALID_ARGUMENTS; -#ifndef ISP2401 - return ia_css_pipe_create_extra(config, NULL, pipe); -#else - } - - err = ia_css_pipe_create_extra(config, NULL, pipe); - - if(err == IA_CSS_SUCCESS) { - IA_CSS_LOG("pipe created successfully = %p", *pipe); - } - - IA_CSS_LEAVE_ERR_PRIVATE(err); - - return err; -#endif -} - -enum ia_css_err -ia_css_pipe_create_extra(const struct ia_css_pipe_config *config, - const struct ia_css_pipe_extra_config *extra_config, - struct ia_css_pipe **pipe) -{ - enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR; - struct ia_css_pipe *internal_pipe = NULL; - unsigned int i; - - IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe); - - /* do not allow to create more than the maximum limit */ - if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_EXHAUSTED); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if ((pipe == NULL) || (config == NULL)) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - ia_css_debug_dump_pipe_config(config); - ia_css_debug_dump_pipe_extra_config(extra_config); - - err = create_pipe(config->mode, &internal_pipe, false); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - /* now we have a pipe structure to fill */ - internal_pipe->config = *config; - if (extra_config) - internal_pipe->extra_config = *extra_config; - else - ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config); - - if (config->mode == IA_CSS_PIPE_MODE_ACC) { - /* Temporary hack to migrate acceleration to CSS 2.0. - * In the future the code for all pipe types should be - * unified. */ - *pipe = internal_pipe; - if (!internal_pipe->config.acc_extension && - internal_pipe->config.num_acc_stages == 0){ /* if no acc binary and no standalone stage */ - *pipe = NULL; - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; - } - return ia_css_acc_pipe_create(internal_pipe); - } - - /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */ - if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2) - internal_pipe->dvs_frame_delay = 2; - else - internal_pipe->dvs_frame_delay = 1; - - - /* we still keep enable_raw_binning for backward compatibility, for any new - fractional bayer downscaling, we should use bayer_ds_out_res. if both are - specified, bayer_ds_out_res will take precedence.if none is specified, we - set bayer_ds_out_res equal to IF output resolution(IF may do cropping on - sensor output) or use default decimation factor 1. */ - if (internal_pipe->extra_config.enable_raw_binning && - internal_pipe->config.bayer_ds_out_res.width) { - /* fill some code here, if no code is needed, please remove it during integration */ - } - - /* YUV downscaling */ - if ((internal_pipe->config.vf_pp_in_res.width || - internal_pipe->config.capt_pp_in_res.width)) { - enum ia_css_frame_format format; - if (internal_pipe->config.vf_pp_in_res.width) { - format = IA_CSS_FRAME_FORMAT_YUV_LINE; - ia_css_frame_info_init( - &internal_pipe->vf_yuv_ds_input_info, - internal_pipe->config.vf_pp_in_res.width, - internal_pipe->config.vf_pp_in_res.height, - format, 0); - } - if (internal_pipe->config.capt_pp_in_res.width) { - format = IA_CSS_FRAME_FORMAT_YUV420; - ia_css_frame_info_init( - &internal_pipe->out_yuv_ds_input_info, - internal_pipe->config.capt_pp_in_res.width, - internal_pipe->config.capt_pp_in_res.height, - format, 0); - } - } - if (internal_pipe->config.vf_pp_in_res.width && - internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) { - ia_css_frame_info_init( - &internal_pipe->vf_yuv_ds_input_info, - internal_pipe->config.vf_pp_in_res.width, - internal_pipe->config.vf_pp_in_res.height, - IA_CSS_FRAME_FORMAT_YUV_LINE, 0); - } - /* handle bayer downscaling output info */ - if (internal_pipe->config.bayer_ds_out_res.width) { - ia_css_frame_info_init( - &internal_pipe->bds_output_info, - internal_pipe->config.bayer_ds_out_res.width, - internal_pipe->config.bayer_ds_out_res.height, - IA_CSS_FRAME_FORMAT_RAW, 0); - } - - /* handle output info, assume always needed */ - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - if (internal_pipe->config.output_info[i].res.width) { - err = sh_css_pipe_configure_output( - internal_pipe, - internal_pipe->config.output_info[i].res.width, - internal_pipe->config.output_info[i].res.height, - internal_pipe->config.output_info[i].padded_width, - internal_pipe->config.output_info[i].format, - i); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - sh_css_free(internal_pipe); - internal_pipe = NULL; - return err; - } - } - - /* handle vf output info, when configured */ - internal_pipe->enable_viewfinder[i] = (internal_pipe->config.vf_output_info[i].res.width != 0); - if (internal_pipe->config.vf_output_info[i].res.width) { - err = sh_css_pipe_configure_viewfinder( - internal_pipe, - internal_pipe->config.vf_output_info[i].res.width, - internal_pipe->config.vf_output_info[i].res.height, - internal_pipe->config.vf_output_info[i].padded_width, - internal_pipe->config.vf_output_info[i].format, - i); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - sh_css_free(internal_pipe); - internal_pipe = NULL; - return err; - } - } - } - if (internal_pipe->config.acc_extension) { - err = ia_css_pipe_load_extension(internal_pipe, - internal_pipe->config.acc_extension); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - sh_css_free(internal_pipe); - return err; - } - } - /* set all info to zeroes first */ - memset(&internal_pipe->info, 0, sizeof(internal_pipe->info)); - - /* all went well, return the pipe */ - *pipe = internal_pipe; - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - return IA_CSS_SUCCESS; -} - - -enum ia_css_err -ia_css_pipe_get_info(const struct ia_css_pipe *pipe, - struct ia_css_pipe_info *pipe_info) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_pipe_get_info()\n"); - assert(pipe_info != NULL); - if (pipe_info == NULL) { - ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, - "ia_css_pipe_get_info: pipe_info cannot be NULL\n"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - if (pipe == NULL || pipe->stream == NULL) { - ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, - "ia_css_pipe_get_info: ia_css_stream_create needs to" - " be called before ia_css_[stream/pipe]_get_info\n"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - /* we succeeded return the info */ - *pipe_info = pipe->info; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n"); - return IA_CSS_SUCCESS; -} - -bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info) -{ - unsigned int i; - - if (pipe_info != NULL) { - for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) { - if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable) - return true; - } - } - - return false; -} - -#ifdef ISP2401 -enum ia_css_err -ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe, - int pin_index, - enum ia_css_frame_format new_format) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format); - - if (NULL == pipe) { - IA_CSS_ERROR("pipe is not set"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - if (0 != pin_index && 1 != pin_index) { - IA_CSS_ERROR("pin index is not valid"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - if (IA_CSS_FRAME_FORMAT_NV12_TILEY != new_format) { - IA_CSS_ERROR("new format is not valid"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } else { - err = ia_css_pipe_check_format(pipe, new_format); - if (IA_CSS_SUCCESS == err) { - if (pin_index == 0) { - pipe->output_info[0].format = new_format; - } else { - pipe->vf_output_info[0].format = new_format; - } - } - } - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -#endif -#if defined(USE_INPUT_SYSTEM_VERSION_2) -/* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */ -static enum ia_css_err -ia_css_stream_configure_rx(struct ia_css_stream *stream) -{ - struct ia_css_input_port *config; - assert(stream != NULL); - - config = &stream->config.source.port; -/* AM: this code is not reliable, especially for 2400 */ - if (config->num_lanes == 1) - stream->csi_rx_config.mode = MONO_1L_1L_0L; - else if (config->num_lanes == 2) - stream->csi_rx_config.mode = MONO_2L_1L_0L; - else if (config->num_lanes == 3) - stream->csi_rx_config.mode = MONO_3L_1L_0L; - else if (config->num_lanes == 4) - stream->csi_rx_config.mode = MONO_4L_1L_0L; - else if (config->num_lanes != 0) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - if (config->port > MIPI_PORT2_ID) - return IA_CSS_ERR_INVALID_ARGUMENTS; - stream->csi_rx_config.port = - ia_css_isys_port_to_mipi_port(config->port); - stream->csi_rx_config.timeout = config->timeout; - stream->csi_rx_config.initcount = 0; - stream->csi_rx_config.synccount = 0x28282828; - stream->csi_rx_config.rxcount = config->rxcount; - if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE) - stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE; - else { - /* not implemented yet, requires extension of the rx_cfg_t - * struct */ - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2); - stream->reconfigure_css_rx = true; - return IA_CSS_SUCCESS; -} -#endif - -static struct ia_css_pipe * -find_pipe(struct ia_css_pipe *pipes[], - unsigned int num_pipes, - enum ia_css_pipe_mode mode, - bool copy_pipe) -{ - unsigned i; - assert(pipes != NULL); - for (i = 0; i < num_pipes; i++) { - assert(pipes[i] != NULL); - if (pipes[i]->config.mode != mode) - continue; - if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY) - continue; - return pipes[i]; - } - return NULL; -} - -static enum ia_css_err -ia_css_acc_stream_create(struct ia_css_stream *stream) -{ - int i; - enum ia_css_err err = IA_CSS_SUCCESS; - - assert(stream != NULL); - IA_CSS_ENTER_PRIVATE("stream = %p", stream); - - if (stream == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - for (i = 0; i < stream->num_pipes; i++) { - struct ia_css_pipe *pipe = stream->pipes[i]; - assert(pipe != NULL); - if (pipe == NULL) { - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - pipe->stream = stream; - } - - /* Map SP threads before doing anything. */ - err = map_sp_threads(stream, true); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - for (i = 0; i < stream->num_pipes; i++) { - struct ia_css_pipe *pipe = stream->pipes[i]; - assert(pipe != NULL); - ia_css_pipe_map_queue(pipe, true); - } - - err = create_host_pipeline_structure(stream); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - stream->started = false; - - - IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS); - - return IA_CSS_SUCCESS; -} - -static enum ia_css_err -metadata_info_init(const struct ia_css_metadata_config *mdc, - struct ia_css_metadata_info *md) -{ - /* Either both width and height should be set or neither */ - if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0)) - return IA_CSS_ERR_INVALID_ARGUMENTS; - - md->resolution = mdc->resolution; - /* We round up the stride to a multiple of the width - * of the port going to DDR, this is a HW requirements (DMA). */ - md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES); - md->size = mdc->resolution.height * md->stride; - return IA_CSS_SUCCESS; -} - -#ifdef ISP2401 -static enum ia_css_err check_pipe_resolutions(const struct ia_css_pipe *pipe) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER_PRIVATE(""); - - if (!pipe || !pipe->stream) { - IA_CSS_ERROR("null arguments"); - err = IA_CSS_ERR_INTERNAL_ERROR; - goto EXIT; - } - - if (ia_css_util_check_res(pipe->config.input_effective_res.width, - pipe->config.input_effective_res.height) != IA_CSS_SUCCESS) { - IA_CSS_ERROR("effective resolution not supported"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - goto EXIT; - } - if (!ia_css_util_resolution_is_zero(pipe->stream->config.input_config.input_res)) { - if (!ia_css_util_res_leq(pipe->config.input_effective_res, - pipe->stream->config.input_config.input_res)) { - IA_CSS_ERROR("effective resolution is larger than input resolution"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - goto EXIT; - } - } - if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) { - IA_CSS_ERROR("output resolution must be even"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - goto EXIT; - } - if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) { - IA_CSS_ERROR("VF resolution must be even"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - goto EXIT; - } -EXIT: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -#endif - -enum ia_css_err -ia_css_stream_create(const struct ia_css_stream_config *stream_config, - int num_pipes, - struct ia_css_pipe *pipes[], - struct ia_css_stream **stream) -{ - struct ia_css_pipe *curr_pipe; - struct ia_css_stream *curr_stream = NULL; - bool spcopyonly; - bool sensor_binning_changed; - int i, j; - enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR; - struct ia_css_metadata_info md_info; -#ifndef ISP2401 - struct ia_css_resolution effective_res; -#else -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - bool aspect_ratio_crop_enabled = false; -#endif -#endif - - IA_CSS_ENTER("num_pipes=%d", num_pipes); - ia_css_debug_dump_stream_config(stream_config, num_pipes); - - /* some checks */ - if (num_pipes == 0 || - stream == NULL || - pipes == NULL) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR(err); - return err; - } - -#if defined(USE_INPUT_SYSTEM_VERSION_2) - /* We don't support metadata for JPEG stream, since they both use str2mem */ - if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && - stream_config->metadata_config.resolution.height > 0) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR(err); - return err; - } -#endif - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - if (stream_config->online && stream_config->pack_raw_pixels) { - IA_CSS_LOG("online and pack raw is invalid on input system 2401"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR(err); - return err; - } -#endif - -#if !defined(HAS_NO_INPUT_SYSTEM) - ia_css_debug_pipe_graph_dump_stream_config(stream_config); - - /* check if mipi size specified */ - if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - if (!stream_config->online) -#endif - { - unsigned int port = (unsigned int) stream_config->source.port.port; - if (port >= N_MIPI_PORT_ID) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR(err); - return err; - } - - if (my_css.size_mem_words != 0){ - my_css.mipi_frame_size[port] = my_css.size_mem_words; - } else if (stream_config->mipi_buffer_config.size_mem_words != 0) { - my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words; - } else { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_stream_create() exit: error, need to set mipi frame size.\n"); - assert(stream_config->mipi_buffer_config.size_mem_words != 0); - err = IA_CSS_ERR_INTERNAL_ERROR; - IA_CSS_LEAVE_ERR(err); - return err; - } - - if (my_css.size_mem_words != 0) { - my_css.num_mipi_frames[port] = 2; /* Temp change: Default for backwards compatibility. */ - } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) { - my_css.num_mipi_frames[port] = stream_config->mipi_buffer_config.nof_mipi_buffers; - } else { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_stream_create() exit: error, need to set number of mipi frames.\n"); - assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0); - err = IA_CSS_ERR_INTERNAL_ERROR; - IA_CSS_LEAVE_ERR(err); - return err; - } - - } -#endif - - /* Currently we only supported metadata up to a certain size. */ - err = metadata_info_init(&stream_config->metadata_config, &md_info); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } - - /* allocate the stream instance */ - curr_stream = kmalloc(sizeof(struct ia_css_stream), GFP_KERNEL); - if (!curr_stream) { - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - IA_CSS_LEAVE_ERR(err); - return err; - } - /* default all to 0 */ - memset(curr_stream, 0, sizeof(struct ia_css_stream)); - curr_stream->info.metadata_info = md_info; - - /* allocate pipes */ - curr_stream->num_pipes = num_pipes; - curr_stream->pipes = kzalloc(num_pipes * sizeof(struct ia_css_pipe *), GFP_KERNEL); - if (!curr_stream->pipes) { - curr_stream->num_pipes = 0; - kfree(curr_stream); - curr_stream = NULL; - err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; - IA_CSS_LEAVE_ERR(err); - return err; - } - /* store pipes */ - spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY); - for (i = 0; i < num_pipes; i++) - curr_stream->pipes [i] = pipes[i]; - curr_stream->last_pipe = curr_stream->pipes[0]; - /* take over stream config */ - curr_stream->config = *stream_config; - -#if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE) - if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR && - stream_config->online) - curr_stream->config.online = false; -#endif - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - if (curr_stream->config.online) { - curr_stream->config.source.port.num_lanes = stream_config->source.port.num_lanes; - curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; - } -#endif - /* in case driver doesn't configure init number of raw buffers, configure it here */ - if (curr_stream->config.target_num_cont_raw_buf == 0) - curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES; - if (curr_stream->config.init_num_cont_raw_buf == 0) - curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf; - - /* Enable locking & unlocking of buffers in RAW buffer pool */ - if (curr_stream->config.ia_css_enable_raw_buffer_locking) - sh_css_sp_configure_enable_raw_pool_locking( - curr_stream->config.lock_all); - - /* copy mode specific stuff */ - switch (curr_stream->config.mode) { - case IA_CSS_INPUT_MODE_SENSOR: - case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: -#if defined(USE_INPUT_SYSTEM_VERSION_2) - ia_css_stream_configure_rx(curr_stream); -#endif - break; - case IA_CSS_INPUT_MODE_TPG: -#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) - IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d", - curr_stream->config.source.tpg.x_mask, - curr_stream->config.source.tpg.y_mask, - curr_stream->config.source.tpg.x_delta, - curr_stream->config.source.tpg.y_delta, - curr_stream->config.source.tpg.xy_mask); - - sh_css_sp_configure_tpg( - curr_stream->config.source.tpg.x_mask, - curr_stream->config.source.tpg.y_mask, - curr_stream->config.source.tpg.x_delta, - curr_stream->config.source.tpg.y_delta, - curr_stream->config.source.tpg.xy_mask); -#endif - break; - case IA_CSS_INPUT_MODE_PRBS: -#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) - IA_CSS_LOG("mode prbs"); - sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed); -#endif - break; - case IA_CSS_INPUT_MODE_MEMORY: - IA_CSS_LOG("mode memory"); - curr_stream->reconfigure_css_rx = false; - break; - default: - IA_CSS_LOG("mode sensor/default"); - } - -#ifdef ISP2401 -#ifdef USE_INPUT_SYSTEM_VERSION_2401 - err = aspect_ratio_crop_init(curr_stream, - pipes, - &aspect_ratio_crop_enabled); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } -#endif - -#endif - for (i = 0; i < num_pipes; i++) { -#ifdef ISP2401 - struct ia_css_resolution effective_res; -#endif - curr_pipe = pipes[i]; - /* set current stream */ - curr_pipe->stream = curr_stream; - /* take over effective info */ - - effective_res = curr_pipe->config.input_effective_res; - if (effective_res.height == 0 || effective_res.width == 0) { - effective_res = curr_pipe->stream->config.input_config.effective_res; -#ifdef ISP2401 - -#if defined(USE_INPUT_SYSTEM_VERSION_2401) - /* The aspect ratio cropping is currently only - * supported on the new input system. */ - if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) { - - struct ia_css_resolution crop_res; - - err = aspect_ratio_crop(curr_pipe, &crop_res); - if (err == IA_CSS_SUCCESS) { - effective_res = crop_res; - } else { - /* in case of error fallback to default - * effective resolution from driver. */ - IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err); - } - } -#endif -#endif - curr_pipe->config.input_effective_res = effective_res; - } - IA_CSS_LOG("effective_res=%dx%d", - effective_res.width, - effective_res.height); - } - -#ifdef ISP2401 - for (i = 0; i < num_pipes; i++) { - if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC && - pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) { - err = check_pipe_resolutions(pipes[i]); - if (err != IA_CSS_SUCCESS) { - goto ERR; - } - } - } - -#endif - err = ia_css_stream_isp_parameters_init(curr_stream); - if (err != IA_CSS_SUCCESS) - goto ERR; - IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs); - - if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) { - *stream = curr_stream; - err = ia_css_acc_stream_create(curr_stream); - goto ERR; - } - /* sensor binning */ - if (!spcopyonly){ - sensor_binning_changed = - sh_css_params_set_binning_factor(curr_stream, curr_stream->config.sensor_binning_factor); - } else { - sensor_binning_changed = false; - } - - IA_CSS_LOG("sensor_binning=%d, changed=%d", - curr_stream->config.sensor_binning_factor, sensor_binning_changed); - /* loop over pipes */ - IA_CSS_LOG("num_pipes=%d", num_pipes); - curr_stream->cont_capt = false; - /* Temporary hack: we give the preview pipe a reference to the capture - * pipe in continuous capture mode. */ - if (curr_stream->config.continuous) { - /* Search for the preview pipe and create the copy pipe */ - struct ia_css_pipe *preview_pipe; - struct ia_css_pipe *video_pipe; - struct ia_css_pipe *acc_pipe; - struct ia_css_pipe *capture_pipe = NULL; - struct ia_css_pipe *copy_pipe = NULL; - - if (num_pipes >= 2) { - curr_stream->cont_capt = true; - curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder; -#ifndef ISP2401 - curr_stream->stop_copy_preview = my_css.stop_copy_preview; -#endif - } - - /* Create copy pipe here, since it may not be exposed to the driver */ - preview_pipe = find_pipe(pipes, num_pipes, - IA_CSS_PIPE_MODE_PREVIEW, false); - video_pipe = find_pipe(pipes, num_pipes, - IA_CSS_PIPE_MODE_VIDEO, false); - acc_pipe = find_pipe(pipes, num_pipes, - IA_CSS_PIPE_MODE_ACC, false); - if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true) - curr_stream->cont_capt = false; /* preview + QoS case will not need cont_capt switch */ - if (curr_stream->cont_capt == true) { - capture_pipe = find_pipe(pipes, num_pipes, - IA_CSS_PIPE_MODE_CAPTURE, false); - if (capture_pipe == NULL) { - err = IA_CSS_ERR_INTERNAL_ERROR; - goto ERR; - } - } - /* We do not support preview and video pipe at the same time */ - if (preview_pipe && video_pipe) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - goto ERR; - } - - if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) { - err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); - if (err != IA_CSS_SUCCESS) - goto ERR; - ia_css_pipe_config_defaults(©_pipe->config); - preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe; - copy_pipe->stream = curr_stream; - } - if (preview_pipe && (curr_stream->cont_capt == true)) { - preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe; - } - if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) { - err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); - if (err != IA_CSS_SUCCESS) - goto ERR; - ia_css_pipe_config_defaults(©_pipe->config); - video_pipe->pipe_settings.video.copy_pipe = copy_pipe; - copy_pipe->stream = curr_stream; - } - if (video_pipe && (curr_stream->cont_capt == true)) { - video_pipe->pipe_settings.video.capture_pipe = capture_pipe; - } - if (preview_pipe && acc_pipe) { - preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe; - } - } - for (i = 0; i < num_pipes; i++) { - curr_pipe = pipes[i]; - /* set current stream */ - curr_pipe->stream = curr_stream; -#ifndef ISP2401 - /* take over effective info */ - - effective_res = curr_pipe->config.input_effective_res; - err = ia_css_util_check_res( - effective_res.width, - effective_res.height); - if (err != IA_CSS_SUCCESS) - goto ERR; -#endif - /* sensor binning per pipe */ - if (sensor_binning_changed) - sh_css_pipe_free_shading_table(curr_pipe); - } - - /* now pipes have been configured, info should be available */ - for (i = 0; i < num_pipes; i++) { - struct ia_css_pipe_info *pipe_info = NULL; - curr_pipe = pipes[i]; - - err = sh_css_pipe_load_binaries(curr_pipe); - if (err != IA_CSS_SUCCESS) - goto ERR; - - /* handle each pipe */ - pipe_info = &curr_pipe->info; - for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { - err = sh_css_pipe_get_output_frame_info(curr_pipe, - &pipe_info->output_info[j], j); - if (err != IA_CSS_SUCCESS) - goto ERR; - } -#ifdef ISP2401 - pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res; -#endif - if (!spcopyonly){ - err = sh_css_pipe_get_shading_info(curr_pipe, -#ifndef ISP2401 - &pipe_info->shading_info); -#else - &pipe_info->shading_info, &curr_pipe->config); -#endif - if (err != IA_CSS_SUCCESS) - goto ERR; - err = sh_css_pipe_get_grid_info(curr_pipe, - &pipe_info->grid_info); - if (err != IA_CSS_SUCCESS) - goto ERR; - for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { - sh_css_pipe_get_viewfinder_frame_info(curr_pipe, - &pipe_info->vf_output_info[j], j); - if (err != IA_CSS_SUCCESS) - goto ERR; - } - } - - my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe; - } - - curr_stream->started = false; - - /* Map SP threads before doing anything. */ - err = map_sp_threads(curr_stream, true); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LOG("map_sp_threads: return_err=%d", err); - goto ERR; - } - - for (i = 0; i < num_pipes; i++) { - curr_pipe = pipes[i]; - ia_css_pipe_map_queue(curr_pipe, true); - } - - /* Create host side pipeline objects without stages */ - err = create_host_pipeline_structure(curr_stream); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err); - goto ERR; - } - - /* assign curr_stream */ - *stream = curr_stream; - -ERR: -#ifndef ISP2401 - if (err == IA_CSS_SUCCESS) - { - /* working mode: enter into the seed list */ - if (my_css_save.mode == sh_css_mode_working) { - for (i = 0; i < MAX_ACTIVE_STREAMS; i++) - if (!my_css_save.stream_seeds[i].stream) { - IA_CSS_LOG("entered stream into loc=%d", i); - my_css_save.stream_seeds[i].orig_stream = stream; - my_css_save.stream_seeds[i].stream = curr_stream; - my_css_save.stream_seeds[i].num_pipes = num_pipes; - my_css_save.stream_seeds[i].stream_config = *stream_config; - for (j = 0; j < num_pipes; j++) { - my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config; - my_css_save.stream_seeds[i].pipes[j] = pipes[j]; - my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j]; - } - break; - } - } -#else - if (err == IA_CSS_SUCCESS) { - err = ia_css_save_stream(curr_stream); -#endif - } else { - ia_css_stream_destroy(curr_stream); - } -#ifndef ISP2401 - IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode); -#else - IA_CSS_LEAVE("return_err=%d", err); -#endif - return err; -} - -enum ia_css_err -ia_css_stream_destroy(struct ia_css_stream *stream) -{ - int i; - enum ia_css_err err = IA_CSS_SUCCESS; -#ifdef ISP2401 - enum ia_css_err err1 = IA_CSS_SUCCESS; - enum ia_css_err err2 = IA_CSS_SUCCESS; -#endif - - IA_CSS_ENTER_PRIVATE("stream = %p", stream); - if (stream == NULL) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - ia_css_stream_isp_parameters_uninit(stream); - - if ((stream->last_pipe != NULL) && - ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) { -#if defined(USE_INPUT_SYSTEM_VERSION_2401) - for (i = 0; i < stream->num_pipes; i++) { - struct ia_css_pipe *entry = stream->pipes[i]; - unsigned int sp_thread_id; - struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal; - - assert(entry != NULL); - if (entry != NULL) { - /* get the SP thread id */ - if (ia_css_pipeline_get_sp_thread_id( - ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true) - return IA_CSS_ERR_INTERNAL_ERROR; - /* get the target input terminal */ - sp_pipeline_input_terminal = - &(sh_css_sp_group.pipe_io[sp_thread_id].input); - - for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) { - ia_css_isys_stream_h isys_stream = - &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]); - if (stream->config.isys_config[i].valid && isys_stream->valid) - ia_css_isys_stream_destroy(isys_stream); - } - } - } -#ifndef ISP2401 - if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { -#else - if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR || - stream->config.mode == IA_CSS_INPUT_MODE_TPG || - stream->config.mode == IA_CSS_INPUT_MODE_PRBS) { -#endif - for (i = 0; i < stream->num_pipes; i++) { - struct ia_css_pipe *entry = stream->pipes[i]; - /* free any mipi frames that are remaining: - * some test stream create-destroy cycles do not generate output frames - * and the mipi buffer is not freed in the deque function - */ - if (entry != NULL) - free_mipi_frames(entry); - } - } - stream_unregister_with_csi_rx(stream); -#endif - - for (i = 0; i < stream->num_pipes; i++) { - struct ia_css_pipe *curr_pipe = stream->pipes[i]; - assert(curr_pipe != NULL); - ia_css_pipe_map_queue(curr_pipe, false); - } - - err = map_sp_threads(stream, false); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - } - - /* remove references from pipes to stream */ - for (i = 0; i < stream->num_pipes; i++) { - struct ia_css_pipe *entry = stream->pipes[i]; - assert(entry != NULL); - if (entry != NULL) { - /* clear reference to stream */ - entry->stream = NULL; - /* check internal copy pipe */ - if (entry->mode == IA_CSS_PIPE_ID_PREVIEW && - entry->pipe_settings.preview.copy_pipe) { - IA_CSS_LOG("clearing stream on internal preview copy pipe"); - entry->pipe_settings.preview.copy_pipe->stream = NULL; - } - if (entry->mode == IA_CSS_PIPE_ID_VIDEO && - entry->pipe_settings.video.copy_pipe) { - IA_CSS_LOG("clearing stream on internal video copy pipe"); - entry->pipe_settings.video.copy_pipe->stream = NULL; - } - err = sh_css_pipe_unload_binaries(entry); - } - } - /* free associated memory of stream struct */ - kfree(stream->pipes); - stream->pipes = NULL; - stream->num_pipes = 0; -#ifndef ISP2401 - /* working mode: take out of the seed list */ - if (my_css_save.mode == sh_css_mode_working) - for(i=0;i<MAX_ACTIVE_STREAMS;i++) - if (my_css_save.stream_seeds[i].stream == stream) - { - IA_CSS_LOG("took out stream %d", i); - my_css_save.stream_seeds[i].stream = NULL; - break; - } -#else - err2 = ia_css_save_restore_remove_stream(stream); - - err1 = (err != IA_CSS_SUCCESS) ? err : err2; -#endif - kfree(stream); -#ifndef ISP2401 - IA_CSS_LEAVE_ERR(err); -#else - IA_CSS_LEAVE_ERR(err1); -#endif - -#ifndef ISP2401 - return err; -#else - return err1; -#endif -} - -enum ia_css_err -ia_css_stream_get_info(const struct ia_css_stream *stream, - struct ia_css_stream_info *stream_info) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n"); - assert(stream != NULL); - assert(stream_info != NULL); - - *stream_info = stream->info; - return IA_CSS_SUCCESS; -} - -/* - * Rebuild a stream, including allocating structs, setting configuration and - * building the required pipes. - * The data is taken from the css_save struct updated upon stream creation. - * The stream handle is used to identify the correct entry in the css_save struct - */ -enum ia_css_err -ia_css_stream_load(struct ia_css_stream *stream) -{ -#ifndef ISP2401 - int i; - enum ia_css_err err; - assert(stream != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter, \n"); - for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { - if (my_css_save.stream_seeds[i].stream == stream) { - int j; - for ( j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) { - if ((err = ia_css_pipe_create(&(my_css_save.stream_seeds[i].pipe_config[j]), &my_css_save.stream_seeds[i].pipes[j])) != IA_CSS_SUCCESS) { - if (j) { - int k; - for(k=0;k<j;k++) - ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]); - } - return err; - } - } - err = ia_css_stream_create(&(my_css_save.stream_seeds[i].stream_config), - my_css_save.stream_seeds[i].num_pipes, - my_css_save.stream_seeds[i].pipes, - &(my_css_save.stream_seeds[i].stream)); - if (err != IA_CSS_SUCCESS) { - ia_css_stream_destroy(stream); - for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) - ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]); - return err; - } - break; - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit, \n"); - return IA_CSS_SUCCESS; -#else - /* TODO remove function - DEPRECATED */ - (void)stream; - return IA_CSS_ERR_NOT_SUPPORTED; -#endif -} - -enum ia_css_err -ia_css_stream_start(struct ia_css_stream *stream) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - IA_CSS_ENTER("stream = %p", stream); - if ((stream == NULL) || (stream->last_pipe == NULL)) { - IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - IA_CSS_LOG("starting %d", stream->last_pipe->mode); - - sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf); - - /* Create host side pipeline. */ - err = create_host_pipeline(stream); - if (err != IA_CSS_SUCCESS) { - IA_CSS_LEAVE_ERR(err); - return err; - } - -#if !defined(HAS_NO_INPUT_SYSTEM) -#if defined(USE_INPUT_SYSTEM_VERSION_2401) - if((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) || - (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)) - stream_register_with_csi_rx(stream); -#endif -#endif - -#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) - /* Initialize mipi size checks */ - if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) - { - unsigned int idx; - unsigned int port = (unsigned int) (stream->config.source.port.port) ; - - for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) { - sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = sh_css_get_mipi_sizes_for_check(port, idx); - } - } -#endif - -#if !defined(HAS_NO_INPUT_SYSTEM) - if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) { - err = sh_css_config_input_network(stream); - if (err != IA_CSS_SUCCESS) - return err; - } -#endif /* !HAS_NO_INPUT_SYSTEM */ - - err = sh_css_pipe_start(stream); - IA_CSS_LEAVE_ERR(err); - return err; -} - -enum ia_css_err -ia_css_stream_stop(struct ia_css_stream *stream) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n"); - assert(stream != NULL); - assert(stream->last_pipe != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n", - stream->last_pipe->mode); - -#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) - /* De-initialize mipi size checks */ - if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) - { - unsigned int idx; - unsigned int port = (unsigned int) (stream->config.source.port.port) ; - - for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) { - sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0; - } - } -#endif -#ifndef ISP2401 - err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline); -#else - - err = sh_css_pipes_stop(stream); -#endif - if (err != IA_CSS_SUCCESS) - return err; - - /* Ideally, unmapping should happen after pipeline_stop, but current - * semantics do not allow that. */ - /* err = map_sp_threads(stream, false); */ - - return err; -} - -bool -ia_css_stream_has_stopped(struct ia_css_stream *stream) -{ - bool stopped; - assert(stream != NULL); - -#ifndef ISP2401 - stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline); -#else - stopped = sh_css_pipes_have_stopped(stream); -#endif - - return stopped; -} - -#ifndef ISP2401 -/* - * Destroy the stream and all the pipes related to it. - * The stream handle is used to identify the correct entry in the css_save struct - */ -enum ia_css_err -ia_css_stream_unload(struct ia_css_stream *stream) -{ - int i; - assert(stream != NULL); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter, \n"); - /* some checks */ - assert (stream != NULL); - for(i=0;i<MAX_ACTIVE_STREAMS;i++) - if (my_css_save.stream_seeds[i].stream == stream) - { - int j; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload(): unloading %d (%p)\n", i, my_css_save.stream_seeds[i].stream); - ia_css_stream_destroy(stream); - for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++) - ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload(): after unloading %d (%p)\n", i, my_css_save.stream_seeds[i].stream); - break; - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit, \n"); - return IA_CSS_SUCCESS; -} - -#endif -enum ia_css_err -ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, enum ia_css_pipe_id *pipe_id) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n"); - if (pipe != NULL) - *pipe_id = pipe->mode; - else - *pipe_id = IA_CSS_PIPE_ID_COPY; - - return IA_CSS_SUCCESS; -} - -enum atomisp_input_format -ia_css_stream_get_format(const struct ia_css_stream *stream) -{ - return stream->config.input_config.format; -} - -bool -ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) -{ - return (stream->config.pixels_per_clock == 2); -} - -struct ia_css_binary * -ia_css_stream_get_shading_correction_binary(const struct ia_css_stream *stream) -{ - struct ia_css_pipe *pipe; - - assert(stream != NULL); - - pipe = stream->pipes[0]; - - if (stream->num_pipes == 2) { - assert(stream->pipes[1] != NULL); - if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO || - stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW) - pipe = stream->pipes[1]; - } - - return ia_css_pipe_get_shading_correction_binary(pipe); -} - -struct ia_css_binary * -ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) -{ - int i; - struct ia_css_pipe *video_pipe = NULL; - - /* First we find the video pipe */ - for (i=0; i<stream->num_pipes; i++) { - struct ia_css_pipe *pipe = stream->pipes[i]; - if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) { - video_pipe = pipe; - break; - } - } - if (video_pipe) - return &video_pipe->pipe_settings.video.video_binary; - return NULL; -} - -struct ia_css_binary * -ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) -{ - struct ia_css_pipe *pipe; - struct ia_css_binary *s3a_binary = NULL; - - assert(stream != NULL); - - pipe = stream->pipes[0]; - - if (stream->num_pipes == 2) { - assert(stream->pipes[1] != NULL); - if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO || - stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW) - pipe = stream->pipes[1]; - } - - s3a_binary = ia_css_pipe_get_s3a_binary(pipe); - - return s3a_binary; -} - - -enum ia_css_err -ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, unsigned int output_padded_width) -{ - struct ia_css_pipe *pipe; - - assert(stream != NULL); - - pipe = stream->last_pipe; - - assert(pipe != NULL); - - /* set the config also just in case (redundant info? why do we save config in pipe?) */ - pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width; - pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width; - - return IA_CSS_SUCCESS; -} - -static struct ia_css_binary * -ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) -{ - struct ia_css_binary *binary = NULL; - - assert(pipe != NULL); - - switch (pipe->config.mode) { - case IA_CSS_PIPE_MODE_PREVIEW: - binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary; - break; - case IA_CSS_PIPE_MODE_VIDEO: - binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary; - break; - case IA_CSS_PIPE_MODE_CAPTURE: - if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { - unsigned int i; - - for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { - if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) { - binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i]; - break; - } - } - } - else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) - binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; - else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED || - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { - if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) - binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; - else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2) - binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary; - } - break; - default: - break; - } - - if (binary && binary->info->sp.enable.sc) - return binary; - - return NULL; -} - -static struct ia_css_binary * -ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) -{ - struct ia_css_binary *binary = NULL; - - assert(pipe != NULL); - - switch (pipe->config.mode) { - case IA_CSS_PIPE_MODE_PREVIEW: - binary = (struct ia_css_binary*)&pipe->pipe_settings.preview.preview_binary; - break; - case IA_CSS_PIPE_MODE_VIDEO: - binary = (struct ia_css_binary*)&pipe->pipe_settings.video.video_binary; - break; - case IA_CSS_PIPE_MODE_CAPTURE: - if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { - unsigned int i; - for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { - if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) { - binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i]; - break; - } - } - } - else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) - binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; - else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED || - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { - if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) - binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; - else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2) - binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary; - else - assert(0); - } - break; - default: - break; - } - - if (binary && !binary->info->sp.enable.s3a) - binary = NULL; - - return binary; -} - -static struct ia_css_binary * -ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) -{ - struct ia_css_binary *binary = NULL; - - assert(pipe != NULL); - - switch (pipe->config.mode) { - case IA_CSS_PIPE_MODE_VIDEO: - binary = (struct ia_css_binary*)&pipe->pipe_settings.video.video_binary; - break; - default: - break; - } - - if (binary && !binary->info->sp.enable.dis) - binary = NULL; - - return binary; -} - -struct ia_css_pipeline * -ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) -{ - assert(pipe != NULL); - - return (struct ia_css_pipeline*)&pipe->pipeline; -} - -unsigned int -ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) -{ - assert(pipe != NULL); - - /* KW was not sure this function was not returning a value - that was out of range; so added an assert, and, for the - case when asserts are not enabled, clip to the largest - value; pipe_num is unsigned so the value cannot be too small - */ - assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX); - - if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX) - return (IA_CSS_PIPELINE_NUM_MAX - 1); - - return pipe->pipe_num; -} - - -unsigned int -ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) -{ - assert(pipe != NULL); - - return (unsigned int)pipe->config.isp_pipe_version; -} - -#define SP_START_TIMEOUT_US 30000000 - -enum ia_css_err -ia_css_start_sp(void) -{ - unsigned long timeout; - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER(""); - sh_css_sp_start_isp(); - - /* waiting for the SP is completely started */ - timeout = SP_START_TIMEOUT_US; - while((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) { - timeout--; - hrt_sleep(); - } - if (timeout == 0) { - IA_CSS_ERROR("timeout during SP initialization"); - return IA_CSS_ERR_INTERNAL_ERROR; - } - - /* Workaround, in order to run two streams in parallel. See TASK 4271*/ - /* TODO: Fix this. */ - - sh_css_init_host_sp_control_vars(); - - /* buffers should be initialized only when sp is started */ - /* AM: At the moment it will be done only when there is no stream active. */ - - sh_css_setup_queues(); - ia_css_bufq_dump_queue_info(); - -#ifdef ISP2401 - if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */ - ia_css_set_system_mode(IA_CSS_SYS_MODE_WORKING); - } -#endif - IA_CSS_LEAVE_ERR(err); - return err; -} - -/* - * Time to wait SP for termincate. Only condition when this can happen - * is a fatal hw failure, but we must be able to detect this and emit - * a proper error trace. - */ -#define SP_SHUTDOWN_TIMEOUT_US 200000 - -enum ia_css_err -ia_css_stop_sp(void) -{ - unsigned long timeout; - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER("void"); - - if (!sh_css_sp_is_running()) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE("SP already stopped : return_err=%d", err); - - /* Return an error - stop SP should not have been called by driver */ - return err; - } - - /* For now, stop whole SP */ -#ifndef ISP2401 - sh_css_write_host2sp_command(host2sp_cmd_terminate); -#else - if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) { - IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); - ia_css_debug_dump_sp_sw_debug_info(); - ia_css_debug_dump_debug_info(NULL); - } -#endif - sh_css_sp_set_sp_running(false); - - timeout = SP_SHUTDOWN_TIMEOUT_US; - while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) { - timeout--; - hrt_sleep(); - } - if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED)) - IA_CSS_WARNING("SP has not terminated (SW)"); - - if (timeout == 0) { - IA_CSS_WARNING("SP is not idle"); - ia_css_debug_dump_sp_sw_debug_info(); - } - timeout = SP_SHUTDOWN_TIMEOUT_US; - while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) { - timeout--; - hrt_sleep(); - } - if (timeout == 0) { - IA_CSS_WARNING("ISP is not idle"); - ia_css_debug_dump_sp_sw_debug_info(); - } - - sh_css_hmm_buffer_record_uninit(); - -#ifndef ISP2401 - /* clear pending param sets from refcount */ - sh_css_param_clear_param_sets(); -#else - if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */ - /* clear pending param sets from refcount */ - sh_css_param_clear_param_sets(); - ia_css_set_system_mode(IA_CSS_SYS_MODE_INIT); /* System is initialized but not 'running' */ - } -#endif - - IA_CSS_LEAVE_ERR(err); - return err; -} - -enum ia_css_err -ia_css_update_continuous_frames(struct ia_css_stream *stream) -{ - struct ia_css_pipe *pipe; - unsigned int i; - - ia_css_debug_dtrace( - IA_CSS_DEBUG_TRACE, - "sh_css_update_continuous_frames() enter:\n"); - - if (stream == NULL) { - ia_css_debug_dtrace( - IA_CSS_DEBUG_TRACE, - "sh_css_update_continuous_frames() leave: invalid stream, return_void\n"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - pipe = stream->continuous_pipe; - - for (i = stream->config.init_num_cont_raw_buf; - i < stream->config.target_num_cont_raw_buf; i++) { - sh_css_update_host2sp_offline_frame(i, - pipe->continuous_frames[i], pipe->cont_md_buffers[i]); - } - sh_css_update_host2sp_cont_num_raw_frames - (stream->config.target_num_cont_raw_buf, true); - ia_css_debug_dtrace( - IA_CSS_DEBUG_TRACE, - "sh_css_update_continuous_frames() leave: return_void\n"); - - return IA_CSS_SUCCESS; -} - -void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) -{ - unsigned int thread_id; - enum ia_css_pipe_id pipe_id; - unsigned int pipe_num; - bool need_input_queue; - - IA_CSS_ENTER(""); - assert(pipe != NULL); - - pipe_id = pipe->mode; - pipe_num = pipe->pipe_num; - - ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); - -#if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401) - need_input_queue = true; -#else - need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif - - /* map required buffer queues to resources */ - /* TODO: to be improved */ - if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) { - if (need_input_queue) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif - if (pipe->pipe_settings.preview.preview_binary.info && - pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); - } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) { - unsigned int i; - - if (need_input_queue) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif - if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { - for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { - if (pipe->pipe_settings.capture.primary_binary[i].info && - pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) { - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); - break; - } - } - } else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED || - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT || - pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) { - if (pipe->pipe_settings.capture.pre_isp_binary.info && - pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); - } - } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) { - if (need_input_queue) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); - if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif - if (pipe->pipe_settings.video.video_binary.info && - pipe->pipe_settings.video.video_binary.info->sp.enable.s3a) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); - if (pipe->pipe_settings.video.video_binary.info && - (pipe->pipe_settings.video.video_binary.info->sp.enable.dis - )) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map); - } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) { - if (need_input_queue) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); - if (!pipe->stream->config.continuous) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); -#if defined SH_CSS_ENABLE_METADATA - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif - } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) { - if (need_input_queue) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif - } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) { - unsigned int idx; - for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) { - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map); - if (pipe->enable_viewfinder[idx]) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map); - } - if (need_input_queue) - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA - ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif - } - IA_CSS_LEAVE(""); -} - -#if CONFIG_ON_FRAME_ENQUEUE() -static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info *info, struct frame_data_wrapper *frame) -{ - frame->config_on_frame_enqueue.padded_width = 0; - - /* currently we support configuration on frame enqueue only on YUV formats */ - /* on other formats the padded_width is zeroed for no configuration override */ - switch (info->format) { - case IA_CSS_FRAME_FORMAT_YUV420: - case IA_CSS_FRAME_FORMAT_NV12: - if (info->padded_width > info->res.width) - { - frame->config_on_frame_enqueue.padded_width = info->padded_width; - } - else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) - { - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - /* nothing to do if width == padded width or padded width is zeroed (the same) */ - break; - default: - break; - } - - return IA_CSS_SUCCESS; -} -#endif - -enum ia_css_err -ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) -{ - enum ia_css_err ret; - - IA_CSS_ENTER(""); - - /* Only continuous streams have a tagger to which we can send the - * unlock message. */ - if (stream == NULL || !stream->config.continuous) { - IA_CSS_ERROR("invalid stream pointer"); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID || - exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) { - IA_CSS_ERROR("invalid expsure ID: %d\n", exp_id); - return IA_CSS_ERR_INVALID_ARGUMENTS; - } - - /* Send the event. Since we verified that the exp_id is valid, - * we can safely assign it to an 8-bit argument here. */ - ret = ia_css_bufq_enqueue_psys_event( - IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0); - - IA_CSS_LEAVE_ERR(ret); - return ret; -} - -/* @brief Set the state (Enable or Disable) of the Extension stage in the - * given pipe. - */ -enum ia_css_err -ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool enable) -{ - unsigned int thread_id; - struct ia_css_pipeline_stage *stage; - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER(""); - - /* Parameter Check */ - if (pipe == NULL || pipe->stream == NULL) { - IA_CSS_ERROR("Invalid Pipe."); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } else if (!(pipe->config.acc_extension)) { - IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)"); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } else if (!sh_css_sp_is_running()) { - IA_CSS_ERROR("Leaving: queue unavailable."); - err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } else { - /* Query the threadid and stage_num for the Extension firmware*/ - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - err = ia_css_pipeline_get_stage_from_fw(&(pipe->pipeline), fw_handle, &stage); - if (err == IA_CSS_SUCCESS) { - /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/ - err = ia_css_bufq_enqueue_psys_event( - (uint8_t) IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE, - (uint8_t) thread_id, - (uint8_t) stage->stage_num, - enable ? 1 : 0); - if (err == IA_CSS_SUCCESS) { - if(enable) - SH_CSS_QOS_STAGE_ENABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num); - else - SH_CSS_QOS_STAGE_DISABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num); - } - } - } - IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable); - return err; -} - -/* @brief Get the state (Enable or Disable) of the Extension stage in the - * given pipe. - */ -enum ia_css_err -ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool *enable) -{ - struct ia_css_pipeline_stage *stage; - unsigned int thread_id; - enum ia_css_err err = IA_CSS_SUCCESS; - - IA_CSS_ENTER(""); - - /* Parameter Check */ - if (pipe == NULL || pipe->stream == NULL) { - IA_CSS_ERROR("Invalid Pipe."); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } else if (!(pipe->config.acc_extension)) { - IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } else if (!sh_css_sp_is_running()) { - IA_CSS_ERROR("Leaving: queue unavailable."); - err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } else { - /* Query the threadid and stage_num corresponding to the Extension firmware*/ - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); - - if (err == IA_CSS_SUCCESS) { - /* Get the Extension State */ - *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num)) ? true : false; - } - } - IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable); - return err; -} - -#ifdef ISP2401 -enum ia_css_err -ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, uint32_t fw_handle, - struct ia_css_isp_param_css_segments *css_seg, struct ia_css_isp_param_isp_segments *isp_seg) -{ - unsigned int HIVE_ADDR_sp_group; - static struct sh_css_sp_group sp_group; - static struct sh_css_sp_stage sp_stage; - static struct sh_css_isp_stage isp_stage; - const struct ia_css_fw_info *fw; - unsigned int thread_id; - struct ia_css_pipeline_stage *stage; - enum ia_css_err err = IA_CSS_SUCCESS; - int stage_num = 0; - enum ia_css_isp_memories mem; - bool enabled; - - IA_CSS_ENTER(""); - - fw = &sh_css_sp_fw; - - /* Parameter Check */ - if (pipe == NULL || pipe->stream == NULL) { - IA_CSS_ERROR("Invalid Pipe."); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } else if (!(pipe->config.acc_extension)) { - IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); - err = IA_CSS_ERR_INVALID_ARGUMENTS; - } else if (!sh_css_sp_is_running()) { - IA_CSS_ERROR("Leaving: queue unavailable."); - err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } else { - /* Query the thread_id and stage_num corresponding to the Extension firmware */ - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - err = ia_css_pipeline_get_stage_from_fw(&(pipe->pipeline), fw_handle, &stage); - if (err == IA_CSS_SUCCESS) { - /* Get the Extension State */ - enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group.pipe[thread_id]), stage->stage_num)) ? true : false; - /* Update mapped arg only when extension stage is not enabled */ - if (enabled) { - IA_CSS_ERROR("Leaving: cannot update when stage is enabled."); - err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; - } else { - stage_num = stage->stage_num; - - HIVE_ADDR_sp_group = fw->info.sp.group; - sp_dmem_load(SP0_ID, - (unsigned int)sp_address_of(sp_group), - &sp_group, sizeof(struct sh_css_sp_group)); - mmgr_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num], - &sp_stage, sizeof(struct sh_css_sp_stage)); - - mmgr_load(sp_stage.isp_stage_addr, - &isp_stage, sizeof(struct sh_css_isp_stage)); - - for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) { - isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address = - css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address; - isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size = - css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size; - isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address = - isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address; - isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size = - isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size; - } - - mmgr_store(sp_stage.isp_stage_addr, - &isp_stage, sizeof(struct sh_css_isp_stage)); - } - } - } - IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle); - return err; -} - -#ifdef USE_INPUT_SYSTEM_VERSION_2401 -static enum ia_css_err -aspect_ratio_crop_init(struct ia_css_stream *curr_stream, - struct ia_css_pipe *pipes[], - bool *do_crop_status) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - int i; - struct ia_css_pipe *curr_pipe; - uint32_t pipe_mask = 0; - - if ((curr_stream == NULL) || - (curr_stream->num_pipes == 0) || - (pipes == NULL) || - (do_crop_status == NULL)) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR(err); - return err; - } - - for (i = 0; i < curr_stream->num_pipes; i++) { - curr_pipe = pipes[i]; - pipe_mask |= (1 << curr_pipe->config.mode); - } - - *do_crop_status = - (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) || - (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) && - (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) && - curr_stream->config.continuous); - return IA_CSS_SUCCESS; -} - -static bool -aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) -{ - bool status = false; - - if ((curr_pipe != NULL) && enabled) { - if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) || - (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) || - (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE)) - status = true; - } - - return status; -} - -static enum ia_css_err -aspect_ratio_crop(struct ia_css_pipe *curr_pipe, - struct ia_css_resolution *effective_res) -{ - enum ia_css_err err = IA_CSS_SUCCESS; - struct ia_css_resolution crop_res; - struct ia_css_resolution *in_res = NULL; - struct ia_css_resolution *out_res = NULL; - bool use_bds_output_info = false; - bool use_vf_pp_in_res = false; - bool use_capt_pp_in_res = false; - - if ((curr_pipe == NULL) || - (effective_res == NULL)) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR(err); - return err; - } - - if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) && - (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) && - (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) { - err = IA_CSS_ERR_INVALID_ARGUMENTS; - IA_CSS_LEAVE_ERR(err); - return err; - } - - use_bds_output_info = - ((curr_pipe->bds_output_info.res.width != 0) && - (curr_pipe->bds_output_info.res.height != 0)); - - use_vf_pp_in_res = - ((curr_pipe->config.vf_pp_in_res.width != 0) && - (curr_pipe->config.vf_pp_in_res.height != 0)); - - use_capt_pp_in_res = - ((curr_pipe->config.capt_pp_in_res.width != 0) && - (curr_pipe->config.capt_pp_in_res.height != 0)); - - in_res = &curr_pipe->stream->config.input_config.effective_res; - out_res = &curr_pipe->output_info[0].res; - - switch (curr_pipe->config.mode) { - case IA_CSS_PIPE_MODE_PREVIEW: - if (use_bds_output_info) - out_res = &curr_pipe->bds_output_info.res; - else if (use_vf_pp_in_res) - out_res = &curr_pipe->config.vf_pp_in_res; - break; - case IA_CSS_PIPE_MODE_VIDEO: - if (use_bds_output_info) - out_res = &curr_pipe->bds_output_info.res; - break; - case IA_CSS_PIPE_MODE_CAPTURE: - if (use_capt_pp_in_res) - out_res = &curr_pipe->config.capt_pp_in_res; - break; - case IA_CSS_PIPE_MODE_ACC: - case IA_CSS_PIPE_MODE_COPY: - case IA_CSS_PIPE_MODE_YUVPP: - default: - IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n", - curr_pipe->config.mode); - assert(0); - break; - } - - err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res); - if (err == IA_CSS_SUCCESS) { - *effective_res = crop_res; - } else { - /* in case of error fallback to default - * effective resolution from driver. */ - IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err); - } - return err; -} -#endif - -#endif -static void -sh_css_hmm_buffer_record_init(void) -{ - int i; - -#ifndef ISP2401 - for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { - sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]); -#else - if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */ - for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { - sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]); - } -#endif - } -} - -static void -sh_css_hmm_buffer_record_uninit(void) -{ - int i; - struct sh_css_hmm_buffer_record *buffer_record = NULL; - -#ifndef ISP2401 - buffer_record = &hmm_buffer_record[0]; - for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { - if (buffer_record->in_use) { - if (buffer_record->h_vbuf != NULL) - ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf); - sh_css_hmm_buffer_record_reset(buffer_record); -#else - if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */ - buffer_record = &hmm_buffer_record[0]; - for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { - if (buffer_record->in_use) { - if (buffer_record->h_vbuf != NULL) - ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf); - sh_css_hmm_buffer_record_reset(buffer_record); - } - buffer_record++; -#endif - } -#ifndef ISP2401 - buffer_record++; -#endif - } -} - -static void -sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) -{ - assert(buffer_record != NULL); - buffer_record->in_use = false; - buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID; - buffer_record->h_vbuf = NULL; - buffer_record->kernel_ptr = 0; -} - -static struct sh_css_hmm_buffer_record -*sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf, - enum ia_css_buffer_type type, - hrt_address kernel_ptr) -{ - int i; - struct sh_css_hmm_buffer_record *buffer_record = NULL; - struct sh_css_hmm_buffer_record *out_buffer_record = NULL; - - assert(h_vbuf != NULL); - assert((type > IA_CSS_BUFFER_TYPE_INVALID) && (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE)); - assert(kernel_ptr != 0); - - buffer_record = &hmm_buffer_record[0]; - for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { - if (!buffer_record->in_use) { - buffer_record->in_use = true; - buffer_record->type = type; - buffer_record->h_vbuf = h_vbuf; - buffer_record->kernel_ptr = kernel_ptr; - out_buffer_record = buffer_record; - break; - } - buffer_record++; - } - - return out_buffer_record; -} - -static struct sh_css_hmm_buffer_record -*sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr, - enum ia_css_buffer_type type) -{ - int i; - struct sh_css_hmm_buffer_record *buffer_record = NULL; - bool found_record = false; - - buffer_record = &hmm_buffer_record[0]; - for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) { - if ((buffer_record->in_use) && - (buffer_record->type == type) && - (buffer_record->h_vbuf != NULL) && - (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) { - found_record = true; - break; - } - buffer_record++; - } - - if (found_record) - return buffer_record; - else - return NULL; -} |