diff options
Diffstat (limited to 'drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c')
-rw-r--r-- | drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c | 4704 |
1 files changed, 0 insertions, 4704 deletions
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c deleted file mode 100644 index df88d9d..0000000 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c +++ /dev/null @@ -1,4704 +0,0 @@ -/* - * Support for Clovertrail PNW Camera Imaging ISP subsystem. - * - * Copyright (c) 2013 Intel Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that 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. - * - * - */ - -#include <media/videobuf-vmalloc.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-event.h> - -#include "mmu/isp_mmu.h" -#include "mmu/sh_mmu_mrfld.h" -#include "hmm/hmm_bo.h" -#include "hmm/hmm.h" - -#include "atomisp_compat.h" -#include "atomisp_internal.h" -#include "atomisp_cmd.h" -#include "atomisp-regs.h" -#include "atomisp_fops.h" -#include "atomisp_ioctl.h" -#include "atomisp_acc.h" - -#include "hrt/hive_isp_css_mm_hrt.h" - -#include <asm/intel-mid.h> - -#include "ia_css_debug.h" -#include "ia_css_isp_param.h" -#include "sh_css_hrt.h" -#include "ia_css_isys.h" - -#include <linux/pm_runtime.h> - -/* Assume max number of ACC stages */ -#define MAX_ACC_STAGES 20 - -/* Ideally, this should come from CSS headers */ -#define NO_LINK -1 - -/* - * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting - * #4684168, if concurrency access happened, system may hard hang. - */ -static DEFINE_SPINLOCK(mmio_lock); - -enum frame_info_type { - ATOMISP_CSS_VF_FRAME, - ATOMISP_CSS_SECOND_VF_FRAME, - ATOMISP_CSS_OUTPUT_FRAME, - ATOMISP_CSS_SECOND_OUTPUT_FRAME, - ATOMISP_CSS_RAW_FRAME, -}; - -struct bayer_ds_factor { - unsigned int numerator; - unsigned int denominator; -}; - -void atomisp_css_debug_dump_sp_sw_debug_info(void) -{ - ia_css_debug_dump_sp_sw_debug_info(); -} - -void atomisp_css_debug_dump_debug_info(const char *context) -{ - ia_css_debug_dump_debug_info(context); -} - -void atomisp_css_debug_set_dtrace_level(const unsigned int trace_level) -{ - ia_css_debug_set_dtrace_level(trace_level); -} - -unsigned int atomisp_css_debug_get_dtrace_level(void) -{ - return ia_css_debug_trace_level; -} - -static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data) -{ - unsigned long flags; - - spin_lock_irqsave(&mmio_lock, flags); - _hrt_master_port_store_8(addr, data); - spin_unlock_irqrestore(&mmio_lock, flags); -} - -static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data) -{ - unsigned long flags; - - spin_lock_irqsave(&mmio_lock, flags); - _hrt_master_port_store_16(addr, data); - spin_unlock_irqrestore(&mmio_lock, flags); -} - -static void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data) -{ - unsigned long flags; - - spin_lock_irqsave(&mmio_lock, flags); - _hrt_master_port_store_32(addr, data); - spin_unlock_irqrestore(&mmio_lock, flags); -} - -static uint8_t atomisp_css2_hw_load_8(hrt_address addr) -{ - unsigned long flags; - uint8_t ret; - - spin_lock_irqsave(&mmio_lock, flags); - ret = _hrt_master_port_load_8(addr); - spin_unlock_irqrestore(&mmio_lock, flags); - return ret; -} - -static uint16_t atomisp_css2_hw_load_16(hrt_address addr) -{ - unsigned long flags; - uint16_t ret; - - spin_lock_irqsave(&mmio_lock, flags); - ret = _hrt_master_port_load_16(addr); - spin_unlock_irqrestore(&mmio_lock, flags); - return ret; -} - -static uint32_t atomisp_css2_hw_load_32(hrt_address addr) -{ - unsigned long flags; - uint32_t ret; - - spin_lock_irqsave(&mmio_lock, flags); - ret = _hrt_master_port_load_32(addr); - spin_unlock_irqrestore(&mmio_lock, flags); - return ret; -} - -static void atomisp_css2_hw_store(hrt_address addr, - const void *from, uint32_t n) -{ - unsigned long flags; - unsigned int i; - unsigned int _to = (unsigned int)addr; - const char *_from = (const char *)from; - - spin_lock_irqsave(&mmio_lock, flags); - for (i = 0; i < n; i++, _to++, _from++) - _hrt_master_port_store_8(_to , *_from); - spin_unlock_irqrestore(&mmio_lock, flags); -} - -static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n) -{ - unsigned long flags; - unsigned int i; - char *_to = (char *)to; - unsigned int _from = (unsigned int)addr; - - spin_lock_irqsave(&mmio_lock, flags); - for (i = 0; i < n; i++, _to++, _from++) - *_to = _hrt_master_port_load_8(_from); - spin_unlock_irqrestore(&mmio_lock, flags); -} - -static int atomisp_css2_dbg_print(const char *fmt, va_list args) -{ - vprintk(fmt, args); - return 0; -} - -static int atomisp_css2_dbg_ftrace_print(const char *fmt, va_list args) -{ - ftrace_vprintk(fmt, args); - return 0; -} - -static int atomisp_css2_err_print(const char *fmt, va_list args) -{ - vprintk(fmt, args); - return 0; -} - -void atomisp_store_uint32(hrt_address addr, uint32_t data) -{ - atomisp_css2_hw_store_32(addr, data); -} - -void atomisp_load_uint32(hrt_address addr, uint32_t *data) -{ - *data = atomisp_css2_hw_load_32(addr); -} -static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr) -{ - if (sh_mmu_mrfld.get_pd_base == NULL) { - dev_err(atomisp_dev, "get mmu base address failed.\n"); - return -EINVAL; - } - - *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu, - bo_device.mmu.base_address); - return 0; -} - -static void atomisp_isp_parameters_clean_up( - struct atomisp_css_isp_config *config) -{ - /* - * Set NULL to configs pointer to avoid they are set into isp again when - * some configs are changed and need to be updated later. - */ - memset(config, 0, sizeof(*config)); -} - -static void __dump_pipe_config(struct atomisp_sub_device *asd, - struct atomisp_stream_env *stream_env, - unsigned int pipe_id) -{ - struct atomisp_device *isp = asd->isp; - - if (stream_env->pipes[pipe_id]) { - struct ia_css_pipe_config *p_config; - struct ia_css_pipe_extra_config *pe_config; - - p_config = &stream_env->pipe_configs[pipe_id]; - pe_config = &stream_env->pipe_extra_configs[pipe_id]; - dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id); - dev_dbg(isp->dev, - "pipe_config.pipe_mode:%d.\n", p_config->mode); - dev_dbg(isp->dev, - "pipe_config.output_info[0] w=%d, h=%d.\n", - p_config->output_info[0].res.width, - p_config->output_info[0].res.height); - dev_dbg(isp->dev, - "pipe_config.vf_pp_in_res w=%d, h=%d.\n", - p_config->vf_pp_in_res.width, - p_config->vf_pp_in_res.height); - dev_dbg(isp->dev, - "pipe_config.capt_pp_in_res w=%d, h=%d.\n", - p_config->capt_pp_in_res.width, - p_config->capt_pp_in_res.height); - dev_dbg(isp->dev, - "pipe_config.output.padded w=%d.\n", - p_config->output_info[0].padded_width); - dev_dbg(isp->dev, - "pipe_config.vf_output_info[0] w=%d, h=%d.\n", - p_config->vf_output_info[0].res.width, - p_config->vf_output_info[0].res.height); - dev_dbg(isp->dev, - "pipe_config.bayer_ds_out_res w=%d, h=%d.\n", - p_config->bayer_ds_out_res.width, - p_config->bayer_ds_out_res.height); - dev_dbg(isp->dev, - "pipe_config.envelope w=%d, h=%d.\n", - p_config->dvs_envelope.width, - p_config->dvs_envelope.height); - dev_dbg(isp->dev, - "pipe_config.dvs_frame_delay=%d.\n", - p_config->dvs_frame_delay); - dev_dbg(isp->dev, - "pipe_config.isp_pipe_version:%d.\n", - p_config->isp_pipe_version); - dev_dbg(isp->dev, - "pipe_config.acc_extension=%p.\n", - p_config->acc_extension); - dev_dbg(isp->dev, - "pipe_config.acc_stages=%p.\n", - p_config->acc_stages); - dev_dbg(isp->dev, - "pipe_config.num_acc_stages=%d.\n", - p_config->num_acc_stages); - dev_dbg(isp->dev, - "pipe_config.acc_num_execs=%d.\n", - p_config->acc_num_execs); - dev_dbg(isp->dev, - "pipe_config.default_capture_config.capture_mode=%d.\n", - p_config->default_capture_config.mode); - dev_dbg(isp->dev, - "pipe_config.enable_dz=%d.\n", - p_config->enable_dz); - dev_dbg(isp->dev, - "pipe_config.default_capture_config.enable_xnr=%d.\n", - p_config->default_capture_config.enable_xnr); - dev_dbg(isp->dev, - "dumping pipe[%d] extra config:\n", pipe_id); - dev_dbg(isp->dev, - "pipe_extra_config.enable_raw_binning:%d.\n", - pe_config->enable_raw_binning); - dev_dbg(isp->dev, - "pipe_extra_config.enable_yuv_ds:%d.\n", - pe_config->enable_yuv_ds); - dev_dbg(isp->dev, - "pipe_extra_config.enable_high_speed:%d.\n", - pe_config->enable_high_speed); - dev_dbg(isp->dev, - "pipe_extra_config.enable_dvs_6axis:%d.\n", - pe_config->enable_dvs_6axis); - dev_dbg(isp->dev, - "pipe_extra_config.enable_reduced_pipe:%d.\n", - pe_config->enable_reduced_pipe); - dev_dbg(isp->dev, - "pipe_(extra_)config.enable_dz:%d.\n", - p_config->enable_dz); - dev_dbg(isp->dev, - "pipe_extra_config.disable_vf_pp:%d.\n", - pe_config->disable_vf_pp); - } -} - -static void __dump_stream_config(struct atomisp_sub_device *asd, - struct atomisp_stream_env *stream_env) -{ - struct atomisp_device *isp = asd->isp; - struct ia_css_stream_config *s_config; - int j; - bool valid_stream = false; - - for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { - if (stream_env->pipes[j]) { - __dump_pipe_config(asd, stream_env, j); - valid_stream = true; - } - } - if (!valid_stream) - return; - s_config = &stream_env->stream_config; - dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode); - - if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR || - s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { - dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n", - s_config->source.port.port); - dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n", - s_config->source.port.num_lanes); - dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n", - s_config->source.port.timeout); - dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n", - s_config->source.port.rxcount); - dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n", - s_config->source.port.compression.type); - dev_dbg(isp->dev, "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n", - s_config->source.port.compression. - compressed_bits_per_pixel); - dev_dbg(isp->dev, "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n", - s_config->source.port.compression. - uncompressed_bits_per_pixel); - } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) { - dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n", - s_config->source.tpg.id); - dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n", - s_config->source.tpg.mode); - dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n", - s_config->source.tpg.x_mask); - dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n", - s_config->source.tpg.x_delta); - dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n", - s_config->source.tpg.y_mask); - dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n", - s_config->source.tpg.y_delta); - dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n", - s_config->source.tpg.xy_mask); - } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) { - dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n", - s_config->source.prbs.id); - dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n", - s_config->source.prbs.h_blank); - dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n", - s_config->source.prbs.v_blank); - dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n", - s_config->source.prbs.seed); - dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n", - s_config->source.prbs.seed1); - } - - for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) { - dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n", - j, - s_config->isys_config[j].input_res.width, - s_config->isys_config[j].input_res.height); - - dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n", - j, - s_config->isys_config[j].linked_isys_stream_id); - - dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n", - j, - s_config->isys_config[j].format); - - dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n", - j, - s_config->isys_config[j].valid); - } - - dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n", - s_config->input_config.input_res.width, - s_config->input_config.input_res.height); - - dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n", - s_config->input_config.effective_res.width, - s_config->input_config.effective_res.height); - - dev_dbg(isp->dev, "stream_config.input_config.format=%d\n", - s_config->input_config.format); - - dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n", - s_config->input_config.bayer_order); - - dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n", - s_config->pixels_per_clock); - dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online); - dev_dbg(isp->dev, "stream_config.continuous=%d.\n", - s_config->continuous); - dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n", - s_config->disable_cont_viewfinder); - dev_dbg(isp->dev, "stream_config.channel_id=%d.\n", - s_config->channel_id); - dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n", - s_config->init_num_cont_raw_buf); - dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n", - s_config->target_num_cont_raw_buf); - dev_dbg(isp->dev, "stream_config.left_padding=%d.\n", - s_config->left_padding); - dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n", - s_config->sensor_binning_factor); - dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n", - s_config->pixels_per_clock); - dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n", - s_config->pack_raw_pixels); - dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n", - s_config->flash_gpio_pin); - dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n", - s_config->mipi_buffer_config.size_mem_words); - dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n", - s_config->mipi_buffer_config.contiguous); - dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n", - s_config->metadata_config.data_type); - dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n", - s_config->metadata_config.resolution.width, - s_config->metadata_config.resolution.height); -} - -static int __destroy_stream(struct atomisp_sub_device *asd, - struct atomisp_stream_env *stream_env, bool force) -{ - struct atomisp_device *isp = asd->isp; - int i; - unsigned long timeout; - - if (!stream_env->stream) - return 0; - - if (!force) { - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - if (stream_env->update_pipe[i]) - break; - - if (i == IA_CSS_PIPE_ID_NUM) - return 0; - } - - if (stream_env->stream_state == CSS_STREAM_STARTED - && ia_css_stream_stop(stream_env->stream) != IA_CSS_SUCCESS) { - dev_err(isp->dev, "stop stream failed.\n"); - return -EINVAL; - } - - if (stream_env->stream_state == CSS_STREAM_STARTED) { - timeout = jiffies + msecs_to_jiffies(40); - while (1) { - if (ia_css_stream_has_stopped(stream_env->stream)) - break; - - if (time_after(jiffies, timeout)) { - dev_warn(isp->dev, "stop stream timeout.\n"); - break; - } - - usleep_range(100, 200); - } - } - - stream_env->stream_state = CSS_STREAM_STOPPED; - - if (ia_css_stream_destroy(stream_env->stream) != IA_CSS_SUCCESS) { - dev_err(isp->dev, "destroy stream failed.\n"); - return -EINVAL; - } - stream_env->stream_state = CSS_STREAM_UNINIT; - stream_env->stream = NULL; - - return 0; -} - -static int __destroy_streams(struct atomisp_sub_device *asd, bool force) -{ - int ret, i; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - ret = __destroy_stream(asd, &asd->stream_env[i], force); - if (ret) - return ret; - } - asd->stream_prepared = false; - return 0; -} -static int __create_stream(struct atomisp_sub_device *asd, - struct atomisp_stream_env *stream_env) -{ - int pipe_index = 0, i; - struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM]; - - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { - if (stream_env->pipes[i]) - multi_pipes[pipe_index++] = stream_env->pipes[i]; - } - if (pipe_index == 0) - return 0; - - stream_env->stream_config.target_num_cont_raw_buf = - asd->continuous_raw_buffer_size->val; - stream_env->stream_config.channel_id = stream_env->ch_id; - stream_env->stream_config.ia_css_enable_raw_buffer_locking = - asd->enable_raw_buffer_lock->val; - - __dump_stream_config(asd, stream_env); - if (ia_css_stream_create(&stream_env->stream_config, - pipe_index, multi_pipes, &stream_env->stream) != IA_CSS_SUCCESS) - return -EINVAL; - if (ia_css_stream_get_info(stream_env->stream, - &stream_env->stream_info) != IA_CSS_SUCCESS) { - ia_css_stream_destroy(stream_env->stream); - stream_env->stream = NULL; - return -EINVAL; - } - - stream_env->stream_state = CSS_STREAM_CREATED; - return 0; -} - -static int __create_streams(struct atomisp_sub_device *asd) -{ - int ret, i; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - ret = __create_stream(asd, &asd->stream_env[i]); - if (ret) - goto rollback; - } - asd->stream_prepared = true; - return 0; -rollback: - for (i--; i >= 0; i--) - __destroy_stream(asd, &asd->stream_env[i], true); - return ret; -} - -static int __destroy_stream_pipes(struct atomisp_sub_device *asd, - struct atomisp_stream_env *stream_env, - bool force) -{ - struct atomisp_device *isp = asd->isp; - int ret = 0; - int i; - - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { - if (!stream_env->pipes[i] || - !(force || stream_env->update_pipe[i])) - continue; - if (ia_css_pipe_destroy(stream_env->pipes[i]) - != IA_CSS_SUCCESS) { - dev_err(isp->dev, - "destroy pipe[%d]failed.cannot recover.\n", i); - ret = -EINVAL; - } - stream_env->pipes[i] = NULL; - stream_env->update_pipe[i] = false; - } - return ret; -} - -static int __destroy_pipes(struct atomisp_sub_device *asd, bool force) -{ - struct atomisp_device *isp = asd->isp; - int i; - int ret = 0; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - if (asd->stream_env[i].stream) { - - dev_err(isp->dev, - "cannot destroy css pipes for stream[%d].\n", - i); - continue; - } - - ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force); - if (ret) - return ret; - } - - return 0; -} - -void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd) -{ - __destroy_streams(asd, true); - __destroy_pipes(asd, true); -} - -static void __apply_additional_pipe_config( - struct atomisp_sub_device *asd, - struct atomisp_stream_env *stream_env, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - - if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) { - dev_err(isp->dev, - "wrong pipe_id for additional pipe config.\n"); - return; - } - - /* apply default pipe config */ - stream_env->pipe_configs[pipe_id].isp_pipe_version = 2; - stream_env->pipe_configs[pipe_id].enable_dz = - asd->disable_dz->val ? false : true; - /* apply isp 2.2 specific config for baytrail*/ - switch (pipe_id) { - case IA_CSS_PIPE_ID_CAPTURE: - /* enable capture pp/dz manually or digital zoom would - * fail*/ - if (stream_env->pipe_configs[pipe_id]. - default_capture_config.mode == CSS_CAPTURE_MODE_RAW) - stream_env->pipe_configs[pipe_id].enable_dz = false; -#ifdef ISP2401 - - /* the isp default to use ISP2.2 and the camera hal will - * control whether use isp2.7 */ - if (asd->select_isp_version->val == - ATOMISP_CSS_ISP_PIPE_VERSION_2_7) - stream_env->pipe_configs[pipe_id].isp_pipe_version = - SH_CSS_ISP_PIPE_VERSION_2_7; - else - stream_env->pipe_configs[pipe_id].isp_pipe_version = - SH_CSS_ISP_PIPE_VERSION_2_2; -#endif - break; - case IA_CSS_PIPE_ID_VIDEO: - /* enable reduced pipe to have binary - * video_dz_2_min selected*/ - stream_env->pipe_extra_configs[pipe_id] - .enable_reduced_pipe = true; - stream_env->pipe_configs[pipe_id] - .enable_dz = false; - if (ATOMISP_SOC_CAMERA(asd)) - stream_env->pipe_configs[pipe_id].enable_dz = true; - - if (asd->params.video_dis_en) { - stream_env->pipe_extra_configs[pipe_id] - .enable_dvs_6axis = true; - stream_env->pipe_configs[pipe_id] - .dvs_frame_delay = - ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; - } - break; - case IA_CSS_PIPE_ID_PREVIEW: - break; - case IA_CSS_PIPE_ID_YUVPP: - case IA_CSS_PIPE_ID_COPY: - if (ATOMISP_SOC_CAMERA(asd)) - stream_env->pipe_configs[pipe_id].enable_dz = true; - else - stream_env->pipe_configs[pipe_id].enable_dz = false; - break; - case IA_CSS_PIPE_ID_ACC: - stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC; - stream_env->pipe_configs[pipe_id].enable_dz = false; - break; - default: - break; - } -} - -static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id) -{ - if (!asd) - return false; - - if (pipe_id == CSS_PIPE_ID_ACC || pipe_id == CSS_PIPE_ID_YUVPP) - return true; - - if (asd->vfpp) { - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { - if (pipe_id == IA_CSS_PIPE_ID_VIDEO) - return true; - else - return false; - } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { - if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) - return true; - else - return false; - } - } - - if (!asd->run_mode) - return false; - - if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY) - return true; - - switch (asd->run_mode->val) { - case ATOMISP_RUN_MODE_STILL_CAPTURE: - if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) - return true; - else - return false; - case ATOMISP_RUN_MODE_PREVIEW: - if (!asd->continuous_mode->val) { - if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) - return true; - else - return false; - } - /* fall through to ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE */ - case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE: - if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || - pipe_id == IA_CSS_PIPE_ID_PREVIEW) - return true; - else - return false; - case ATOMISP_RUN_MODE_VIDEO: - if (!asd->continuous_mode->val) { - if (pipe_id == IA_CSS_PIPE_ID_VIDEO || - pipe_id == IA_CSS_PIPE_ID_YUVPP) - return true; - else - return false; - } - /* fall through to ATOMISP_RUN_MODE_SDV */ - case ATOMISP_RUN_MODE_SDV: - if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || - pipe_id == IA_CSS_PIPE_ID_VIDEO) - return true; - else - return false; - } - - return false; -} - -static int __create_pipe(struct atomisp_sub_device *asd, - struct atomisp_stream_env *stream_env, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - struct ia_css_pipe_extra_config extra_config; - enum ia_css_err ret; - - if (pipe_id >= IA_CSS_PIPE_ID_NUM) - return -EINVAL; - - if (pipe_id != CSS_PIPE_ID_ACC && - !stream_env->pipe_configs[pipe_id].output_info[0].res.width) - return 0; - - if (pipe_id == CSS_PIPE_ID_ACC && - !stream_env->pipe_configs[pipe_id].acc_extension) - return 0; - - if (!is_pipe_valid_to_current_run_mode(asd, pipe_id)) - return 0; - - ia_css_pipe_extra_config_defaults(&extra_config); - - __apply_additional_pipe_config(asd, stream_env, pipe_id); - if (!memcmp(&extra_config, - &stream_env->pipe_extra_configs[pipe_id], - sizeof(extra_config))) - ret = ia_css_pipe_create( - &stream_env->pipe_configs[pipe_id], - &stream_env->pipes[pipe_id]); - else - ret = ia_css_pipe_create_extra( - &stream_env->pipe_configs[pipe_id], - &stream_env->pipe_extra_configs[pipe_id], - &stream_env->pipes[pipe_id]); - if (ret != IA_CSS_SUCCESS) - dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id); - return ret; -} - -static int __create_pipes(struct atomisp_sub_device *asd) -{ - enum ia_css_err ret; - int i, j; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { - ret = __create_pipe(asd, &asd->stream_env[i], j); - if (ret != IA_CSS_SUCCESS) - break; - } - if (j < IA_CSS_PIPE_ID_NUM) - goto pipe_err; - } - return 0; -pipe_err: - for (; i >= 0; i--) { - for (j--; j >= 0; j--) { - if (asd->stream_env[i].pipes[j]) { - ia_css_pipe_destroy(asd->stream_env[i].pipes[j]); - asd->stream_env[i].pipes[j] = NULL; - } - } - j = IA_CSS_PIPE_ID_NUM; - } - return -EINVAL; -} - -void atomisp_create_pipes_stream(struct atomisp_sub_device *asd) -{ - __create_pipes(asd); - __create_streams(asd); -} - -int atomisp_css_update_stream(struct atomisp_sub_device *asd) -{ - int ret; - struct atomisp_device *isp = asd->isp; - - if (__destroy_streams(asd, true) != IA_CSS_SUCCESS) - dev_warn(isp->dev, "destroy stream failed.\n"); - - if (__destroy_pipes(asd, true) != IA_CSS_SUCCESS) - dev_warn(isp->dev, "destroy pipe failed.\n"); - - ret = __create_pipes(asd); - if (ret != IA_CSS_SUCCESS) { - dev_err(isp->dev, "create pipe failed %d.\n", ret); - return -EIO; - } - - ret = __create_streams(asd); - if (ret != IA_CSS_SUCCESS) { - dev_warn(isp->dev, "create stream failed %d.\n", ret); - __destroy_pipes(asd, true); - return -EIO; - } - - return 0; -} - -int atomisp_css_init(struct atomisp_device *isp) -{ - unsigned int mmu_base_addr; - int ret; - enum ia_css_err err; - - ret = hmm_get_mmu_base_addr(&mmu_base_addr); - if (ret) - return ret; - - /* Init ISP */ - err = ia_css_init(&isp->css_env.isp_css_env, NULL, - (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE); - if (err != IA_CSS_SUCCESS) { - dev_err(isp->dev, "css init failed --- bad firmware?\n"); - return -EINVAL; - } - ia_css_enable_isys_event_queue(true); - - isp->css_initialized = true; - dev_dbg(isp->dev, "sh_css_init success\n"); - - return 0; -} - -static inline int __set_css_print_env(struct atomisp_device *isp, int opt) -{ - int ret = 0; - - if (opt == 0) - isp->css_env.isp_css_env.print_env.debug_print = NULL; - else if (opt == 1) - isp->css_env.isp_css_env.print_env.debug_print = - atomisp_css2_dbg_ftrace_print; - else if (opt == 2) - isp->css_env.isp_css_env.print_env.debug_print = - atomisp_css2_dbg_print; - else - ret = -EINVAL; - - return ret; -} - -int atomisp_css_check_firmware_version(struct atomisp_device *isp) -{ - if (!sh_css_check_firmware_version((void *)isp->firmware->data)) { - dev_err(isp->dev, "Fw version check failed.\n"); - return -EINVAL; - } - return 0; -} - -int atomisp_css_load_firmware(struct atomisp_device *isp) -{ - enum ia_css_err err; - - /* set css env */ - isp->css_env.isp_css_fw.data = (void *)isp->firmware->data; - isp->css_env.isp_css_fw.bytes = isp->firmware->size; - - isp->css_env.isp_css_env.hw_access_env.store_8 = - atomisp_css2_hw_store_8; - isp->css_env.isp_css_env.hw_access_env.store_16 = - atomisp_css2_hw_store_16; - isp->css_env.isp_css_env.hw_access_env.store_32 = - atomisp_css2_hw_store_32; - - isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8; - isp->css_env.isp_css_env.hw_access_env.load_16 = - atomisp_css2_hw_load_16; - isp->css_env.isp_css_env.hw_access_env.load_32 = - atomisp_css2_hw_load_32; - - isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load; - isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store; - - __set_css_print_env(isp, dbg_func); - - isp->css_env.isp_css_env.print_env.error_print = atomisp_css2_err_print; - - /* load isp fw into ISP memory */ - err = ia_css_load_firmware(&isp->css_env.isp_css_env, - &isp->css_env.isp_css_fw); - if (err != IA_CSS_SUCCESS) { - dev_err(isp->dev, "css load fw failed.\n"); - return -EINVAL; - } - - return 0; -} - -void atomisp_css_unload_firmware(struct atomisp_device *isp) -{ - ia_css_unload_firmware(); -} - -void atomisp_css_uninit(struct atomisp_device *isp) -{ - struct atomisp_sub_device *asd; - unsigned int i; - - for (i = 0; i < isp->num_of_streams; i++) { - asd = &isp->asd[i]; - atomisp_isp_parameters_clean_up(&asd->params.config); - asd->params.css_update_params_needed = false; - } - - isp->css_initialized = false; - ia_css_uninit(); -} - -void atomisp_css_suspend(struct atomisp_device *isp) -{ - isp->css_initialized = false; - ia_css_uninit(); -} - -int atomisp_css_resume(struct atomisp_device *isp) -{ - unsigned int mmu_base_addr; - int ret; - - ret = hmm_get_mmu_base_addr(&mmu_base_addr); - if (ret) { - dev_err(isp->dev, "get base address error.\n"); - return -EINVAL; - } - - ret = ia_css_init(&isp->css_env.isp_css_env, NULL, - mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE); - if (ret) { - dev_err(isp->dev, "re-init css failed.\n"); - return -EINVAL; - } - ia_css_enable_isys_event_queue(true); - - isp->css_initialized = true; - return 0; -} - -int atomisp_css_irq_translate(struct atomisp_device *isp, - unsigned int *infos) -{ - int err; - - err = ia_css_irq_translate(infos); - if (err != IA_CSS_SUCCESS) { - dev_warn(isp->dev, - "%s:failed to translate irq (err = %d,infos = %d)\n", - __func__, err, *infos); - return -EINVAL; - } - - return 0; -} - -void atomisp_css_rx_get_irq_info(enum mipi_port_id port, - unsigned int *infos) -{ -#ifndef ISP2401_NEW_INPUT_SYSTEM - ia_css_isys_rx_get_irq_info(port, infos); -#else - *infos = 0; -#endif -} - -void atomisp_css_rx_clear_irq_info(enum mipi_port_id port, - unsigned int infos) -{ -#ifndef ISP2401_NEW_INPUT_SYSTEM - ia_css_isys_rx_clear_irq_info(port, infos); -#endif -} - -int atomisp_css_irq_enable(struct atomisp_device *isp, - enum atomisp_css_irq_info info, bool enable) -{ - if (ia_css_irq_enable(info, enable) != IA_CSS_SUCCESS) { - dev_warn(isp->dev, "%s:Invalid irq info.\n", __func__); - return -EINVAL; - } - - return 0; -} - -void atomisp_css_init_struct(struct atomisp_sub_device *asd) -{ - int i, j; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - asd->stream_env[i].stream = NULL; - for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) { - asd->stream_env[i].pipes[j] = NULL; - asd->stream_env[i].update_pipe[j] = false; - ia_css_pipe_config_defaults( - &asd->stream_env[i].pipe_configs[j]); - ia_css_pipe_extra_config_defaults( - &asd->stream_env[i].pipe_extra_configs[j]); - } - ia_css_stream_config_defaults(&asd->stream_env[i].stream_config); - } -} - -int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd, - struct videobuf_vmalloc_memory *vm_mem, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_buffer_type css_buf_type, - enum atomisp_css_pipe_id css_pipe_id) -{ - struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; - struct ia_css_buffer css_buf = {0}; - enum ia_css_err err; - - css_buf.type = css_buf_type; - css_buf.data.frame = vm_mem->vaddr; - - err = ia_css_pipe_enqueue_buffer( - stream_env->pipes[css_pipe_id], &css_buf); - if (err != IA_CSS_SUCCESS) - return -EINVAL; - - return 0; -} - -int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd, - struct atomisp_metadata_buf *metadata_buf, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_pipe_id css_pipe_id) -{ - struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; - struct ia_css_buffer buffer = {0}; - struct atomisp_device *isp = asd->isp; - - buffer.type = IA_CSS_BUFFER_TYPE_METADATA; - buffer.data.metadata = metadata_buf->metadata; - if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id], - &buffer)) { - dev_err(isp->dev, "failed to q meta data buffer\n"); - return -EINVAL; - } - - return 0; -} - -int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd, - struct atomisp_s3a_buf *s3a_buf, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_pipe_id css_pipe_id) -{ - struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; - struct ia_css_buffer buffer = {0}; - struct atomisp_device *isp = asd->isp; - - buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS; - buffer.data.stats_3a = s3a_buf->s3a_data; - if (ia_css_pipe_enqueue_buffer( - stream_env->pipes[css_pipe_id], - &buffer)) { - dev_dbg(isp->dev, "failed to q s3a stat buffer\n"); - return -EINVAL; - } - - return 0; -} - -int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, - struct atomisp_dis_buf *dis_buf, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_pipe_id css_pipe_id) -{ - struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; - struct ia_css_buffer buffer = {0}; - struct atomisp_device *isp = asd->isp; - - buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS; - buffer.data.stats_dvs = dis_buf->dis_data; - if (ia_css_pipe_enqueue_buffer( - stream_env->pipes[css_pipe_id], - &buffer)) { - dev_dbg(isp->dev, "failed to q dvs stat buffer\n"); - return -EINVAL; - } - - return 0; -} - -void atomisp_css_mmu_invalidate_cache(void) -{ - ia_css_mmu_invalidate_cache(); -} - -void atomisp_css_mmu_invalidate_tlb(void) -{ - ia_css_mmu_invalidate_cache(); -} - -int atomisp_css_start(struct atomisp_sub_device *asd, - enum atomisp_css_pipe_id pipe_id, bool in_reset) -{ - struct atomisp_device *isp = asd->isp; - bool sp_is_started = false; - int ret = 0, i = 0; - - if (in_reset) { - if (__destroy_streams(asd, true)) - dev_warn(isp->dev, "destroy stream failed.\n"); - - if (__destroy_pipes(asd, true)) - dev_warn(isp->dev, "destroy pipe failed.\n"); - - if (__create_pipes(asd)) { - dev_err(isp->dev, "create pipe error.\n"); - return -EINVAL; - } - if (__create_streams(asd)) { - dev_err(isp->dev, "create stream error.\n"); - ret = -EINVAL; - goto stream_err; - } - /* in_reset == true, extension firmwares are reloaded after the recovery */ - atomisp_acc_load_extensions(asd); - } - - /* - * For dual steam case, it is possible that: - * 1: for this stream, it is at the stage that: - * - after set_fmt is called - * - before stream on is called - * 2: for the other stream, the stream off is called which css reset - * has been done. - * - * Thus the stream created in set_fmt get destroyed and need to be - * recreated in the next stream on. - */ - if (asd->stream_prepared == false) { - if (__create_pipes(asd)) { - dev_err(isp->dev, "create pipe error.\n"); - return -EINVAL; - } - if (__create_streams(asd)) { - dev_err(isp->dev, "create stream error.\n"); - ret = -EINVAL; - goto stream_err; - } - } - /* - * SP can only be started one time - * if atomisp_subdev_streaming_count() tell there already has some - * subdev at streamming, then SP should already be started previously, - * so need to skip start sp procedure - */ - if (atomisp_streaming_count(isp)) { - dev_dbg(isp->dev, "skip start sp\n"); - } else { - if (!sh_css_hrt_system_is_idle()) - dev_err(isp->dev, "CSS HW not idle before starting SP\n"); - if (ia_css_start_sp() != IA_CSS_SUCCESS) { - dev_err(isp->dev, "start sp error.\n"); - ret = -EINVAL; - goto start_err; - } else { - sp_is_started = true; - } - } - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - if (asd->stream_env[i].stream) { - if (ia_css_stream_start(asd->stream_env[i] - .stream) != IA_CSS_SUCCESS) { - dev_err(isp->dev, "stream[%d] start error.\n", i); - ret = -EINVAL; - goto start_err; - } else { - asd->stream_env[i].stream_state = CSS_STREAM_STARTED; - dev_dbg(isp->dev, "stream[%d] started.\n", i); - } - } - } - - return 0; - -start_err: - __destroy_streams(asd, true); -stream_err: - __destroy_pipes(asd, true); - - /* css 2.0 API limitation: ia_css_stop_sp() could be only called after - * destroy all pipes - */ - /* - * SP can not be stop if other streams are in use - */ - if ((atomisp_streaming_count(isp) == 0) && sp_is_started) - ia_css_stop_sp(); - - return ret; -} - -void atomisp_css_update_isp_params(struct atomisp_sub_device *asd) -{ - /* - * FIXME! - * for ISP2401 new input system, this api is under development. - * Calling it would cause kernel panic. - * - * VIED BZ: 1458 - * - * Check if it is Cherry Trail and also new input system - */ - if (asd->copy_mode) { - dev_warn(asd->isp->dev, - "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n", - __func__); - return; - } - - ia_css_stream_set_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &asd->params.config); - atomisp_isp_parameters_clean_up(&asd->params.config); -} - - -void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd, - struct ia_css_pipe *pipe) -{ - enum ia_css_err ret; - - if (!pipe) { - atomisp_css_update_isp_params(asd); - return; - } - - dev_dbg(asd->isp->dev, "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n", - __func__, asd->params.config.output_frame, - asd->params.config.isp_config_id, pipe); - - ret = ia_css_stream_set_isp_config_on_pipe( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &asd->params.config, pipe); - if (ret != IA_CSS_SUCCESS) - dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n", - __func__, ret); - atomisp_isp_parameters_clean_up(&asd->params.config); -} - -int atomisp_css_queue_buffer(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_pipe_id pipe_id, - enum atomisp_css_buffer_type buf_type, - struct atomisp_css_buffer *isp_css_buffer) -{ - if (ia_css_pipe_enqueue_buffer( - asd->stream_env[stream_id].pipes[pipe_id], - &isp_css_buffer->css_buffer) - != IA_CSS_SUCCESS) - return -EINVAL; - - return 0; -} - -int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_pipe_id pipe_id, - enum atomisp_css_buffer_type buf_type, - struct atomisp_css_buffer *isp_css_buffer) -{ - struct atomisp_device *isp = asd->isp; - enum ia_css_err err; - - err = ia_css_pipe_dequeue_buffer( - asd->stream_env[stream_id].pipes[pipe_id], - &isp_css_buffer->css_buffer); - if (err != IA_CSS_SUCCESS) { - dev_err(isp->dev, - "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err); - return -EINVAL; - } - - return 0; -} - -int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd, - uint16_t stream_id, - struct atomisp_s3a_buf *s3a_buf, - struct atomisp_dis_buf *dis_buf, - struct atomisp_metadata_buf *md_buf) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_css_dvs_grid_info *dvs_grid_info = - atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); - - if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) { - void *s3a_ptr; - - s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate( - &asd->params.curr_grid_info.s3a_grid); - if (!s3a_buf->s3a_data) { - dev_err(isp->dev, "3a buf allocation failed.\n"); - return -EINVAL; - } - - s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true); - s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate( - s3a_buf->s3a_data, s3a_ptr); - } - - if (dis_buf && dvs_grid_info && dvs_grid_info->enable) { - void *dvs_ptr; - - dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate( - dvs_grid_info); - if (!dis_buf->dis_data) { - dev_err(isp->dev, "dvs buf allocation failed.\n"); - if (s3a_buf) - ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); - return -EINVAL; - } - - dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true); - dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate( - dis_buf->dis_data, dvs_ptr); - } - - if (asd->stream_env[stream_id].stream_info. - metadata_info.size && md_buf) { - md_buf->metadata = ia_css_metadata_allocate( - &asd->stream_env[stream_id].stream_info.metadata_info); - if (!md_buf->metadata) { - if (s3a_buf) - ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); - if (dis_buf) - ia_css_isp_dvs2_statistics_free(dis_buf->dis_data); - dev_err(isp->dev, "metadata buf allocation failed.\n"); - return -EINVAL; - } - md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false); - } - - return 0; -} - -void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf) -{ - if (s3a_buf->s3a_data) - hmm_vunmap(s3a_buf->s3a_data->data_ptr); - - ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map); - s3a_buf->s3a_map = NULL; - ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); -} - -void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf) -{ - if (dis_buf->dis_data) - hmm_vunmap(dis_buf->dis_data->data_ptr); - - ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map); - dis_buf->dvs_map = NULL; - ia_css_isp_dvs2_statistics_free(dis_buf->dis_data); -} - -void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf) -{ - if (metadata_buf->md_vptr) { - hmm_vunmap(metadata_buf->metadata->address); - metadata_buf->md_vptr = NULL; - } - ia_css_metadata_free(metadata_buf->metadata); -} - -void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd) -{ - struct atomisp_s3a_buf *s3a_buf, *_s3a_buf; - struct atomisp_dis_buf *dis_buf, *_dis_buf; - struct atomisp_metadata_buf *md_buf, *_md_buf; - struct atomisp_css_dvs_grid_info *dvs_grid_info = - atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); - unsigned int i; - - /* 3A statistics use vmalloc, DIS use kmalloc */ - if (dvs_grid_info && dvs_grid_info->enable) { - ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff); - ia_css_dvs2_statistics_free(asd->params.dvs_stat); - asd->params.css_param.dvs2_coeff = NULL; - asd->params.dvs_stat = NULL; - asd->params.dvs_hor_proj_bytes = 0; - asd->params.dvs_ver_proj_bytes = 0; - asd->params.dvs_hor_coef_bytes = 0; - asd->params.dvs_ver_coef_bytes = 0; - asd->params.dis_proj_data_valid = false; - list_for_each_entry_safe(dis_buf, _dis_buf, - &asd->dis_stats, list) { - atomisp_css_free_dis_buffer(dis_buf); - list_del(&dis_buf->list); - kfree(dis_buf); - } - list_for_each_entry_safe(dis_buf, _dis_buf, - &asd->dis_stats_in_css, list) { - atomisp_css_free_dis_buffer(dis_buf); - list_del(&dis_buf->list); - kfree(dis_buf); - } - } - if (asd->params.curr_grid_info.s3a_grid.enable) { - ia_css_3a_statistics_free(asd->params.s3a_user_stat); - asd->params.s3a_user_stat = NULL; - asd->params.s3a_output_bytes = 0; - list_for_each_entry_safe(s3a_buf, _s3a_buf, - &asd->s3a_stats, list) { - atomisp_css_free_3a_buffer(s3a_buf); - list_del(&s3a_buf->list); - kfree(s3a_buf); - } - list_for_each_entry_safe(s3a_buf, _s3a_buf, - &asd->s3a_stats_in_css, list) { - atomisp_css_free_3a_buffer(s3a_buf); - list_del(&s3a_buf->list); - kfree(s3a_buf); - } - list_for_each_entry_safe(s3a_buf, _s3a_buf, - &asd->s3a_stats_ready, list) { - atomisp_css_free_3a_buffer(s3a_buf); - list_del(&s3a_buf->list); - kfree(s3a_buf); - } - } - - if (asd->params.css_param.dvs_6axis) { - ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis); - asd->params.css_param.dvs_6axis = NULL; - } - - for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { - list_for_each_entry_safe(md_buf, _md_buf, - &asd->metadata[i], list) { - atomisp_css_free_metadata_buffer(md_buf); - list_del(&md_buf->list); - kfree(md_buf); - } - list_for_each_entry_safe(md_buf, _md_buf, - &asd->metadata_in_css[i], list) { - atomisp_css_free_metadata_buffer(md_buf); - list_del(&md_buf->list); - kfree(md_buf); - } - list_for_each_entry_safe(md_buf, _md_buf, - &asd->metadata_ready[i], list) { - atomisp_css_free_metadata_buffer(md_buf); - list_del(&md_buf->list); - kfree(md_buf); - } - } - asd->params.metadata_width_size = 0; - atomisp_free_metadata_output_buf(asd); -} - -int atomisp_css_get_grid_info(struct atomisp_sub_device *asd, - enum atomisp_css_pipe_id pipe_id, - int source_pad) -{ - struct ia_css_pipe_info p_info; - struct ia_css_grid_info old_info; - struct atomisp_device *isp = asd->isp; - int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); - int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. - stream_config.metadata_config.resolution.width; - - memset(&p_info, 0, sizeof(struct ia_css_pipe_info)); - memset(&old_info, 0, sizeof(struct ia_css_grid_info)); - - if (ia_css_pipe_get_info( - asd->stream_env[stream_index].pipes[pipe_id], - &p_info) != IA_CSS_SUCCESS) { - dev_err(isp->dev, "ia_css_pipe_get_info failed\n"); - return -EINVAL; - } - - memcpy(&old_info, &asd->params.curr_grid_info, - sizeof(struct ia_css_grid_info)); - memcpy(&asd->params.curr_grid_info, &p_info.grid_info, - sizeof(struct ia_css_grid_info)); - /* - * Record which css pipe enables s3a_grid. - * Currently would have one css pipe that need it - */ - if (asd->params.curr_grid_info.s3a_grid.enable) { - if (asd->params.s3a_enabled_pipe != CSS_PIPE_ID_NUM) - dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n", - asd->params.s3a_enabled_pipe, pipe_id); - asd->params.s3a_enabled_pipe = pipe_id; - } - - /* If the grid info has not changed and the buffers for 3A and - * DIS statistics buffers are allocated or buffer size would be zero - * then no need to do anything. */ - if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info)) - && asd->params.s3a_user_stat && asd->params.dvs_stat) - || asd->params.curr_grid_info.s3a_grid.width == 0 - || asd->params.curr_grid_info.s3a_grid.height == 0) - && asd->params.metadata_width_size == md_width) { - dev_dbg(isp->dev, - "grid info change escape. memcmp=%d, s3a_user_stat=%d," - "dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n", - !memcmp(&old_info, &asd->params.curr_grid_info, - sizeof(old_info)), - !!asd->params.s3a_user_stat, !!asd->params.dvs_stat, - asd->params.curr_grid_info.s3a_grid.width, - asd->params.curr_grid_info.s3a_grid.height, - asd->params.metadata_width_size); - return -EINVAL; - } - asd->params.metadata_width_size = md_width; - - return 0; -} - -int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd) -{ - if (!asd->params.curr_grid_info.s3a_grid.width || - !asd->params.curr_grid_info.s3a_grid.height) - return 0; - - asd->params.s3a_user_stat = ia_css_3a_statistics_allocate( - &asd->params.curr_grid_info.s3a_grid); - if (!asd->params.s3a_user_stat) - return -ENOMEM; - /* 3A statistics. These can be big, so we use vmalloc. */ - asd->params.s3a_output_bytes = - asd->params.curr_grid_info.s3a_grid.width * - asd->params.curr_grid_info.s3a_grid.height * - sizeof(*asd->params.s3a_user_stat->data); - - return 0; -} - -int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd) -{ - struct atomisp_css_dvs_grid_info *dvs_grid = - atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); - - if (!dvs_grid) - return 0; - - if (!dvs_grid->enable) { - dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__); - return 0; - } - - /* DIS coefficients. */ - asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate( - dvs_grid); - if (!asd->params.css_param.dvs2_coeff) - return -ENOMEM; - - asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs * - sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real); - - asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs * - sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real); - - /* DIS projections. */ - asd->params.dis_proj_data_valid = false; - asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid); - if (!asd->params.dvs_stat) - return -ENOMEM; - - asd->params.dvs_hor_proj_bytes = - dvs_grid->aligned_height * dvs_grid->aligned_width * - sizeof(*asd->params.dvs_stat->hor_prod.odd_real); - - asd->params.dvs_ver_proj_bytes = - dvs_grid->aligned_height * dvs_grid->aligned_width * - sizeof(*asd->params.dvs_stat->ver_prod.odd_real); - - return 0; -} - -int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd) -{ - int i; - - /* We allocate the cpu-side buffer used for communication with user - * space */ - for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { - asd->params.metadata_user[i] = kvmalloc( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. - stream_info.metadata_info.size, GFP_KERNEL); - if (!asd->params.metadata_user[i]) { - while (--i >= 0) { - kvfree(asd->params.metadata_user[i]); - asd->params.metadata_user[i] = NULL; - } - return -ENOMEM; - } - } - - return 0; -} - -void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd) -{ - unsigned int i; - - for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { - if (asd->params.metadata_user[i]) { - kvfree(asd->params.metadata_user[i]); - asd->params.metadata_user[i] = NULL; - } - } -} - -void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd, - struct atomisp_css_buffer *isp_css_buffer, - struct ia_css_isp_dvs_statistics_map *dvs_map) -{ - if (asd->params.dvs_stat) { - if (dvs_map) - ia_css_translate_dvs2_statistics( - asd->params.dvs_stat, dvs_map); - else - ia_css_get_dvs2_statistics(asd->params.dvs_stat, - isp_css_buffer->css_buffer.data.stats_dvs); - - } -} - -int atomisp_css_dequeue_event(struct atomisp_css_event *current_event) -{ - if (ia_css_dequeue_event(¤t_event->event) != IA_CSS_SUCCESS) - return -EINVAL; - - return 0; -} - -void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd, - struct atomisp_css_event *current_event) -{ - /* - * FIXME! - * Pipe ID reported in CSS event is not correct for new system's - * copy pipe. - * VIED BZ: 1463 - */ - ia_css_temp_pipe_to_pipe_id(current_event->event.pipe, - ¤t_event->pipe); - if (asd && asd->copy_mode && - current_event->pipe == IA_CSS_PIPE_ID_CAPTURE) - current_event->pipe = IA_CSS_PIPE_ID_COPY; -} - -int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - struct v4l2_mbus_framefmt *ffmt, - int isys_stream) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH) - return -EINVAL; - - s_config->isys_config[isys_stream].input_res.width = ffmt->width; - s_config->isys_config[isys_stream].input_res.height = ffmt->height; - return 0; -} - -int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - struct v4l2_mbus_framefmt *ffmt) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->input_config.input_res.width = ffmt->width; - s_config->input_config.input_res.height = ffmt->height; - return 0; -} - -void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - unsigned int bin_factor) -{ - asd->stream_env[stream_id] - .stream_config.sensor_binning_factor = bin_factor; -} - -void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_css_bayer_order bayer_order) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - s_config->input_config.bayer_order = bayer_order; -} - -void atomisp_css_isys_set_link(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - int link, - int isys_stream) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->isys_config[isys_stream].linked_isys_stream_id = link; -} - -void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - bool valid, - int isys_stream) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->isys_config[isys_stream].valid = valid; -} - -void atomisp_css_isys_set_format(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format format, - int isys_stream) -{ - - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->isys_config[isys_stream].format = format; -} - -void atomisp_css_input_set_format(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format format) -{ - - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->input_config.format = format; -} - -int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - struct v4l2_mbus_framefmt *ffmt) -{ - int i; - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - /* - * Set all isys configs to not valid. - * Currently we support only one stream per channel - */ - for (i = IA_CSS_STREAM_ISYS_STREAM_0; - i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) - s_config->isys_config[i].valid = false; - - atomisp_css_isys_set_resolution(asd, stream_id, ffmt, - IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); - atomisp_css_isys_set_format(asd, stream_id, - s_config->input_config.format, - IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); - atomisp_css_isys_set_link(asd, stream_id, NO_LINK, - IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); - atomisp_css_isys_set_valid(asd, stream_id, true, - IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); - - return 0; -} - -int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format input_format) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width = - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height = - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id - = IA_CSS_STREAM_ISYS_STREAM_0; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format = - ATOMISP_INPUT_FORMAT_USER_DEF1; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format = - ATOMISP_INPUT_FORMAT_USER_DEF2; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true; - return 0; -} - -void atomisp_css_isys_two_stream_cfg_update_stream1( - struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format input_format, - unsigned int width, unsigned int height) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width = - width; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height = - height; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format = - input_format; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true; -} - -void atomisp_css_isys_two_stream_cfg_update_stream2( - struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format input_format, - unsigned int width, unsigned int height) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width = - width; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height = - height; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id - = IA_CSS_STREAM_ISYS_STREAM_0; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format = - input_format; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true; -} - -int atomisp_css_input_set_effective_resolution( - struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - unsigned int width, unsigned int height) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - s_config->input_config.effective_res.width = width; - s_config->input_config.effective_res.height = height; - return 0; -} - -void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd, - unsigned int dvs_w, unsigned int dvs_h) -{ - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w; - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h; -} - -void atomisp_css_input_set_two_pixels_per_clock( - struct atomisp_sub_device *asd, - bool two_ppc) -{ - int i; - - if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .stream_config.pixels_per_clock == (two_ppc ? 2 : 1)) - return; - - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .stream_config.pixels_per_clock = (two_ppc ? 2 : 1); - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .update_pipe[i] = true; -} - -void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - unsigned int pipe; - - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) - pipe = IA_CSS_PIPE_ID_VIDEO; - else - pipe = IA_CSS_PIPE_ID_PREVIEW; - - stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable; - stream_env->update_pipe[pipe] = true; - if (enable) - stream_env->pipe_configs[pipe].output_info[0].padded_width = - stream_env->stream_config.input_config.effective_res.width; -} - -void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable) -{ - int i; - - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipe_configs[i].enable_dz = enable; -} - -void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd, - enum atomisp_css_capture_mode mode) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - - if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE] - .default_capture_config.mode == mode) - return; - - stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. - default_capture_config.mode = mode; - stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; -} - -void atomisp_css_input_set_mode(struct atomisp_sub_device *asd, - enum atomisp_css_input_mode mode) -{ - int i; - struct atomisp_device *isp = asd->isp; - unsigned int size_mem_words; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) - asd->stream_env[i].stream_config.mode = mode; - - if (isp->inputs[asd->input_curr].type == TEST_PATTERN) { - struct ia_css_stream_config *s_config = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config; - s_config->mode = IA_CSS_INPUT_MODE_TPG; - s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD; - s_config->source.tpg.x_mask = (1 << 4) - 1; - s_config->source.tpg.x_delta = -2; - s_config->source.tpg.y_mask = (1 << 4) - 1; - s_config->source.tpg.y_delta = 3; - s_config->source.tpg.xy_mask = (1 << 8) - 1; - return; - } - - if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) - return; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - /* - * TODO: sensor needs to export the embedded_data_size_words - * information to atomisp for each setting. - * Here using a large safe value. - */ - struct ia_css_stream_config *s_config = - &asd->stream_env[i].stream_config; - - if (s_config->input_config.input_res.width == 0) - continue; - - if (ia_css_mipi_frame_calculate_size( - s_config->input_config.input_res.width, - s_config->input_config.input_res.height, - s_config->input_config.format, - true, - 0x13000, - &size_mem_words) != IA_CSS_SUCCESS) { - if (intel_mid_identify_cpu() == - INTEL_MID_CPU_CHIP_TANGIER) - size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2; - else - size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1; - dev_warn(asd->isp->dev, - "ia_css_mipi_frame_calculate_size failed," - "applying pre-defined MIPI buffer size %u.\n", - size_mem_words); - } - s_config->mipi_buffer_config.size_mem_words = size_mem_words; - s_config->mipi_buffer_config.nof_mipi_buffers = 2; - } -} - -void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd, - unsigned short stream_index, bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[stream_index]; - - if (stream_env->stream_config.online == !!enable) - return; - - stream_env->stream_config.online = !!enable; - stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; -} - -void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd, - unsigned short stream_index, bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[stream_index]; - int i; - - if (stream_env->stream_config.online != !!enable) { - stream_env->stream_config.online = !!enable; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - -void atomisp_css_video_enable_online(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO]; - int i; - - if (stream_env->stream_config.online != enable) { - stream_env->stream_config.online = enable; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - -void atomisp_css_enable_continuous(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - int i; - - /* - * To SOC camera, there is only one YUVPP pipe in any case - * including ZSL/SDV/continuous viewfinder, so always set - * stream_config.continuous to 0. - */ - if (ATOMISP_USE_YUVPP(asd)) { - stream_env->stream_config.continuous = 0; - stream_env->stream_config.online = 1; - return; - } - - if (stream_env->stream_config.continuous != !!enable) { - stream_env->stream_config.continuous = !!enable; - stream_env->stream_config.pack_raw_pixels = true; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - -void atomisp_css_enable_cvf(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - int i; - - if (stream_env->stream_config.disable_cont_viewfinder != !enable) { - stream_env->stream_config.disable_cont_viewfinder = !enable; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - -int atomisp_css_input_configure_port( - struct atomisp_sub_device *asd, - enum mipi_port_id port, - unsigned int num_lanes, - unsigned int timeout, - unsigned int mipi_freq, - enum atomisp_input_format metadata_format, - unsigned int metadata_width, - unsigned int metadata_height) -{ - int i; - struct atomisp_stream_env *stream_env; - /* - * Calculate rx_count as follows: - * Input: mipi_freq : CSI-2 bus frequency in Hz - * UI = 1 / (2 * mipi_freq) : period of one bit on the bus - * min = 85e-9 + 6 * UI : Limits for rx_count in seconds - * max = 145e-9 + 10 * UI - * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks - * rxcount = rxcount0 - 2 : adjust for better results - * The formula below is simplified version of the above with - * 10-bit fixed points for improved accuracy. - */ - const unsigned int rxcount = - min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - stream_env = &asd->stream_env[i]; - stream_env->stream_config.source.port.port = port; - stream_env->stream_config.source.port.num_lanes = num_lanes; - stream_env->stream_config.source.port.timeout = timeout; - if (mipi_freq) - stream_env->stream_config.source.port.rxcount = rxcount; - stream_env->stream_config. - metadata_config.data_type = metadata_format; - stream_env->stream_config. - metadata_config.resolution.width = metadata_width; - stream_env->stream_config. - metadata_config.resolution.height = metadata_height; - } - - return 0; -} - -int atomisp_css_frame_allocate(struct atomisp_css_frame **frame, - unsigned int width, unsigned int height, - enum atomisp_css_frame_format format, - unsigned int padded_width, - unsigned int raw_bit_depth) -{ - if (ia_css_frame_allocate(frame, width, height, format, - padded_width, raw_bit_depth) != IA_CSS_SUCCESS) - return -ENOMEM; - - return 0; -} - -int atomisp_css_frame_allocate_from_info(struct atomisp_css_frame **frame, - const struct atomisp_css_frame_info *info) -{ - if (ia_css_frame_allocate_from_info(frame, info) != IA_CSS_SUCCESS) - return -ENOMEM; - - return 0; -} - -void atomisp_css_frame_free(struct atomisp_css_frame *frame) -{ - ia_css_frame_free(frame); -} - -int atomisp_css_frame_map(struct atomisp_css_frame **frame, - const struct atomisp_css_frame_info *info, - const void __user *data, uint16_t attribute, - void *context) -{ - if (ia_css_frame_map(frame, info, data, attribute, context) - != IA_CSS_SUCCESS) - return -ENOMEM; - - return 0; -} - -int atomisp_css_set_black_frame(struct atomisp_sub_device *asd, - const struct atomisp_css_frame *raw_black_frame) -{ - if (sh_css_set_black_frame( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - raw_black_frame) != IA_CSS_SUCCESS) - return -ENOMEM; - - return 0; -} - -int atomisp_css_allocate_continuous_frames(bool init_time, - struct atomisp_sub_device *asd) -{ - if (ia_css_alloc_continuous_frame_remain( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) - != IA_CSS_SUCCESS) - return -EINVAL; - return 0; -} - -void atomisp_css_update_continuous_frames(struct atomisp_sub_device *asd) -{ - ia_css_update_continuous_frames( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream); -} - -int atomisp_css_stop(struct atomisp_sub_device *asd, - enum atomisp_css_pipe_id pipe_id, bool in_reset) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_s3a_buf *s3a_buf; - struct atomisp_dis_buf *dis_buf; - struct atomisp_metadata_buf *md_buf; - unsigned long irqflags; - unsigned int i; - - /* if is called in atomisp_reset(), force destroy stream */ - if (__destroy_streams(asd, true)) - dev_err(isp->dev, "destroy stream failed.\n"); - - /* if is called in atomisp_reset(), force destroy all pipes */ - if (__destroy_pipes(asd, true)) - dev_err(isp->dev, "destroy pipes failed.\n"); - - atomisp_init_raw_buffer_bitmap(asd); - - /* - * SP can not be stop if other streams are in use - */ - if (atomisp_streaming_count(isp) == 0) - ia_css_stop_sp(); - - if (!in_reset) { - struct atomisp_stream_env *stream_env; - int i, j; - - for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { - stream_env = &asd->stream_env[i]; - for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { - ia_css_pipe_config_defaults( - &stream_env->pipe_configs[j]); - ia_css_pipe_extra_config_defaults( - &stream_env->pipe_extra_configs[j]); - } - ia_css_stream_config_defaults( - &stream_env->stream_config); - } - atomisp_isp_parameters_clean_up(&asd->params.config); - asd->params.css_update_params_needed = false; - } - - /* move stats buffers to free queue list */ - while (!list_empty(&asd->s3a_stats_in_css)) { - s3a_buf = list_entry(asd->s3a_stats_in_css.next, - struct atomisp_s3a_buf, list); - list_del(&s3a_buf->list); - list_add_tail(&s3a_buf->list, &asd->s3a_stats); - } - while (!list_empty(&asd->s3a_stats_ready)) { - s3a_buf = list_entry(asd->s3a_stats_ready.next, - struct atomisp_s3a_buf, list); - list_del(&s3a_buf->list); - list_add_tail(&s3a_buf->list, &asd->s3a_stats); - } - - spin_lock_irqsave(&asd->dis_stats_lock, irqflags); - while (!list_empty(&asd->dis_stats_in_css)) { - dis_buf = list_entry(asd->dis_stats_in_css.next, - struct atomisp_dis_buf, list); - list_del(&dis_buf->list); - list_add_tail(&dis_buf->list, &asd->dis_stats); - } - asd->params.dis_proj_data_valid = false; - spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags); - - for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { - while (!list_empty(&asd->metadata_in_css[i])) { - md_buf = list_entry(asd->metadata_in_css[i].next, - struct atomisp_metadata_buf, list); - list_del(&md_buf->list); - list_add_tail(&md_buf->list, &asd->metadata[i]); - } - while (!list_empty(&asd->metadata_ready[i])) { - md_buf = list_entry(asd->metadata_ready[i].next, - struct atomisp_metadata_buf, list); - list_del(&md_buf->list); - list_add_tail(&md_buf->list, &asd->metadata[i]); - } - } - - atomisp_flush_params_queue(&asd->video_out_capture); - atomisp_flush_params_queue(&asd->video_out_vf); - atomisp_flush_params_queue(&asd->video_out_preview); - atomisp_flush_params_queue(&asd->video_out_video_capture); - atomisp_free_css_parameters(&asd->params.css_param); - memset(&asd->params.css_param, 0, sizeof(asd->params.css_param)); - return 0; -} - -int atomisp_css_continuous_set_num_raw_frames( - struct atomisp_sub_device *asd, - int num_frames) -{ - if (asd->enable_raw_buffer_lock->val) { - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .stream_config.init_num_cont_raw_buf = - ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && - asd->params.video_dis_en) - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .stream_config.init_num_cont_raw_buf += - ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; - } else { - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .stream_config.init_num_cont_raw_buf = - ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES; - } - - if (asd->params.video_dis_en) - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .stream_config.init_num_cont_raw_buf += - ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; - - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .stream_config.target_num_cont_raw_buf = num_frames; - return 0; -} - -void atomisp_css_disable_vf_pp(struct atomisp_sub_device *asd, - bool disable) -{ - int i; - - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipe_extra_configs[i].disable_vf_pp = !!disable; -} - -static enum ia_css_pipe_mode __pipe_id_to_pipe_mode( - struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); - - switch (pipe_id) { - case IA_CSS_PIPE_ID_COPY: - /* Currently only YUVPP mode supports YUV420_Legacy format. - * Revert this when other pipe modes can support - * YUV420_Legacy format. - */ - if (mipi_info && mipi_info->input_format == - ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) - return IA_CSS_PIPE_MODE_YUVPP; - return IA_CSS_PIPE_MODE_COPY; - case IA_CSS_PIPE_ID_PREVIEW: - return IA_CSS_PIPE_MODE_PREVIEW; - case IA_CSS_PIPE_ID_CAPTURE: - return IA_CSS_PIPE_MODE_CAPTURE; - case IA_CSS_PIPE_ID_VIDEO: - return IA_CSS_PIPE_MODE_VIDEO; - case IA_CSS_PIPE_ID_ACC: - return IA_CSS_PIPE_MODE_ACC; - case IA_CSS_PIPE_ID_YUVPP: - return IA_CSS_PIPE_MODE_YUVPP; - default: - WARN_ON(1); - return IA_CSS_PIPE_MODE_PREVIEW; - } - -} - -static void __configure_output(struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int min_width, - enum ia_css_frame_format format, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_stream_env *stream_env = - &asd->stream_env[stream_index]; - struct ia_css_stream_config *s_config = &stream_env->stream_config; - - stream_env->pipe_configs[pipe_id].mode = - __pipe_id_to_pipe_mode(asd, pipe_id); - stream_env->update_pipe[pipe_id] = true; - - stream_env->pipe_configs[pipe_id].output_info[0].res.width = width; - stream_env->pipe_configs[pipe_id].output_info[0].res.height = height; - stream_env->pipe_configs[pipe_id].output_info[0].format = format; - stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width; - - /* isp binary 2.2 specific setting*/ - if (width > s_config->input_config.effective_res.width || - height > s_config->input_config.effective_res.height) { - s_config->input_config.effective_res.width = width; - s_config->input_config.effective_res.height = height; - } - - dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n", - pipe_id, width, height, format); -} - -static void __configure_video_preview_output(struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int min_width, - enum ia_css_frame_format format, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_stream_env *stream_env = - &asd->stream_env[stream_index]; - struct ia_css_frame_info *css_output_info; - struct ia_css_stream_config *stream_config = &stream_env->stream_config; - - stream_env->pipe_configs[pipe_id].mode = - __pipe_id_to_pipe_mode(asd, pipe_id); - stream_env->update_pipe[pipe_id] = true; - - /* - * second_output will be as video main output in SDV mode - * with SOC camera. output will be as video main output in - * normal video mode. - */ - if (asd->continuous_mode->val) - css_output_info = &stream_env->pipe_configs[pipe_id]. - output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; - else - css_output_info = &stream_env->pipe_configs[pipe_id]. - output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - - css_output_info->res.width = width; - css_output_info->res.height = height; - css_output_info->format = format; - css_output_info->padded_width = min_width; - - /* isp binary 2.2 specific setting*/ - if (width > stream_config->input_config.effective_res.width || - height > stream_config->input_config.effective_res.height) { - stream_config->input_config.effective_res.width = width; - stream_config->input_config.effective_res.height = height; - } - - dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n", - pipe_id, width, height, format); -} - -/* - * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv - * downscaling input resolution. - */ -static void __configure_capture_pp_input(struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - struct ia_css_stream_config *stream_config = &stream_env->stream_config; - struct ia_css_pipe_config *pipe_configs = - &stream_env->pipe_configs[pipe_id]; - struct ia_css_pipe_extra_config *pipe_extra_configs = - &stream_env->pipe_extra_configs[pipe_id]; - unsigned int hor_ds_factor = 0, ver_ds_factor = 0; - - if (width == 0 && height == 0) - return; - - if (width * 9 / 10 < pipe_configs->output_info[0].res.width || - height * 9 / 10 < pipe_configs->output_info[0].res.height) - return; - /* here just copy the calculation in css */ - hor_ds_factor = CEIL_DIV(width >> 1, - pipe_configs->output_info[0].res.width); - ver_ds_factor = CEIL_DIV(height >> 1, - pipe_configs->output_info[0].res.height); - - if ((asd->isp->media_dev.hw_revision < - (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) || - IS_CHT) && hor_ds_factor != ver_ds_factor) { - dev_warn(asd->isp->dev, - "Cropping for capture due to FW limitation"); - return; - } - - pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); - stream_env->update_pipe[pipe_id] = true; - - pipe_extra_configs->enable_yuv_ds = true; - - pipe_configs->capt_pp_in_res.width = - stream_config->input_config.effective_res.width; - pipe_configs->capt_pp_in_res.height = - stream_config->input_config.effective_res.height; - - dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n", - pipe_id, width, height); -} - -/* - * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and - * yuv downscaling, which needs addtional configurations. - */ -static void __configure_preview_pp_input(struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height; - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - struct ia_css_stream_config *stream_config = &stream_env->stream_config; - struct ia_css_pipe_config *pipe_configs = - &stream_env->pipe_configs[pipe_id]; - struct ia_css_pipe_extra_config *pipe_extra_configs = - &stream_env->pipe_extra_configs[pipe_id]; - struct ia_css_resolution *bayer_ds_out_res = - &pipe_configs->bayer_ds_out_res; - struct ia_css_resolution *vf_pp_in_res = - &pipe_configs->vf_pp_in_res; - struct ia_css_resolution *effective_res = - &stream_config->input_config.effective_res; - - const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} }; - /* - * BZ201033: YUV decimation factor of 4 causes couple of rightmost - * columns to be shaded. Remove this factor to work around the CSS bug. - * const unsigned int yuv_dec_fct[] = {4, 2}; - */ - const unsigned int yuv_dec_fct[] = { 2 }; - unsigned int i; - - if (width == 0 && height == 0) - return; - - pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); - stream_env->update_pipe[pipe_id] = true; - - out_width = pipe_configs->output_info[0].res.width; - out_height = pipe_configs->output_info[0].res.height; - - /* - * The ISP could do bayer downscaling, yuv decimation and yuv - * downscaling: - * 1: Bayer Downscaling: between effective resolution and - * bayer_ds_res_out; - * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res; - * 3: YUV Downscaling: between vf_pp_in_res and final vf output - * - * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25 - * Rule for YUV Decimation: support factor 2, 4 - * Rule for YUV Downscaling: arbitary value below 2 - * - * General rule of factor distribution among these stages: - * 1: try to do Bayer downscaling first if not in online mode. - * 2: try to do maximum of 2 for YUV downscaling - * 3: the remainling for YUV decimation - * - * Note: - * Do not configure bayer_ds_out_res if: - * online == 1 or continuous == 0 or raw_binning = 0 - */ - if (stream_config->online || !stream_config->continuous || - !pipe_extra_configs->enable_raw_binning) { - bayer_ds_out_res->width = 0; - bayer_ds_out_res->height = 0; - } else { - bayer_ds_out_res->width = effective_res->width; - bayer_ds_out_res->height = effective_res->height; - - for (i = 0; i < ARRAY_SIZE(bds_fct); i++) { - if (effective_res->width >= out_width * - bds_fct[i].numerator / bds_fct[i].denominator && - effective_res->height >= out_height * - bds_fct[i].numerator / bds_fct[i].denominator) { - bayer_ds_out_res->width = - effective_res->width * - bds_fct[i].denominator / - bds_fct[i].numerator; - bayer_ds_out_res->height = - effective_res->height * - bds_fct[i].denominator / - bds_fct[i].numerator; - break; - } - } - } - /* - * calculate YUV Decimation, YUV downscaling facor: - * YUV Downscaling factor must not exceed 2. - * YUV Decimation factor could be 2, 4. - */ - /* first decide the yuv_ds input resolution */ - if (bayer_ds_out_res->width == 0) { - yuv_ds_in_width = effective_res->width; - yuv_ds_in_height = effective_res->height; - } else { - yuv_ds_in_width = bayer_ds_out_res->width; - yuv_ds_in_height = bayer_ds_out_res->height; - } - - vf_pp_in_res->width = yuv_ds_in_width; - vf_pp_in_res->height = yuv_ds_in_height; - - /* find out the yuv decimation factor */ - for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) { - if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] && - yuv_ds_in_height >= out_height * yuv_dec_fct[i]) { - vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i]; - vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i]; - break; - } - } - - if (vf_pp_in_res->width == out_width && - vf_pp_in_res->height == out_height) { - pipe_extra_configs->enable_yuv_ds = false; - vf_pp_in_res->width = 0; - vf_pp_in_res->height = 0; - } else { - pipe_extra_configs->enable_yuv_ds = true; - } - - dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n", - pipe_id, width, height); -} - -/* - * For CSS2.1, offline video pipe could support bayer decimation, and - * yuv downscaling, which needs addtional configurations. - */ -static void __configure_video_pp_input(struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - int out_width, out_height; - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - struct ia_css_stream_config *stream_config = &stream_env->stream_config; - struct ia_css_pipe_config *pipe_configs = - &stream_env->pipe_configs[pipe_id]; - struct ia_css_pipe_extra_config *pipe_extra_configs = - &stream_env->pipe_extra_configs[pipe_id]; - struct ia_css_resolution *bayer_ds_out_res = - &pipe_configs->bayer_ds_out_res; - struct ia_css_resolution *effective_res = - &stream_config->input_config.effective_res; - - const struct bayer_ds_factor bds_factors[] = { - {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2} }; - unsigned int i; - - if (width == 0 && height == 0) - return; - - pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); - stream_env->update_pipe[pipe_id] = true; - - pipe_extra_configs->enable_yuv_ds = false; - - /* - * If DVS is enabled, video binary will take care the dvs envelope - * and usually the bayer_ds_out_res should be larger than 120% of - * destination resolution, the extra 20% will be cropped as DVS - * envelope. But, if the bayer_ds_out_res is less than 120% of the - * destination. The ISP can still work, but DVS quality is not good. - */ - /* taking at least 10% as envelope */ - if (asd->params.video_dis_en) { - out_width = pipe_configs->output_info[0].res.width * 110 / 100; - out_height = pipe_configs->output_info[0].res.height * 110 / 100; - } else { - out_width = pipe_configs->output_info[0].res.width; - out_height = pipe_configs->output_info[0].res.height; - } - - /* - * calculate bayer decimate factor: - * 1: only 1.5, 2, 4 and 8 get supported - * 2: Do not configure bayer_ds_out_res if: - * online == 1 or continuous == 0 or raw_binning = 0 - */ - if (stream_config->online || !stream_config->continuous) { - bayer_ds_out_res->width = 0; - bayer_ds_out_res->height = 0; - goto done; - } - - pipe_extra_configs->enable_raw_binning = true; - bayer_ds_out_res->width = effective_res->width; - bayer_ds_out_res->height = effective_res->height; - - for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor); - i++) { - if (effective_res->width >= out_width * - bds_factors[i].numerator / bds_factors[i].denominator && - effective_res->height >= out_height * - bds_factors[i].numerator / bds_factors[i].denominator) { - bayer_ds_out_res->width = effective_res->width * - bds_factors[i].denominator / - bds_factors[i].numerator; - bayer_ds_out_res->height = effective_res->height * - bds_factors[i].denominator / - bds_factors[i].numerator; - break; - } - } - - /* - * DVS is cropped from BDS output, so we do not really need to set the - * envelope to 20% of output resolution here. always set it to 12x12 - * per firmware requirement. - */ - pipe_configs->dvs_envelope.width = 12; - pipe_configs->dvs_envelope.height = 12; - -done: - if (pipe_id == IA_CSS_PIPE_ID_YUVPP) - stream_config->left_padding = -1; - else - stream_config->left_padding = 12; - dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n", - pipe_id, width, height); -} - -static void __configure_vf_output(struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - unsigned int min_width, - enum atomisp_css_frame_format format, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - stream_env->pipe_configs[pipe_id].mode = - __pipe_id_to_pipe_mode(asd, pipe_id); - stream_env->update_pipe[pipe_id] = true; - - stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width; - stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height; - stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format; - stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width = - min_width; - dev_dbg(isp->dev, - "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n", - pipe_id, width, height, format); -} - -static void __configure_video_vf_output(struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - unsigned int min_width, - enum atomisp_css_frame_format format, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - struct ia_css_frame_info *css_output_info; - - stream_env->pipe_configs[pipe_id].mode = - __pipe_id_to_pipe_mode(asd, pipe_id); - stream_env->update_pipe[pipe_id] = true; - - /* - * second_vf_output will be as video viewfinder in SDV mode - * with SOC camera. vf_output will be as video viewfinder in - * normal video mode. - */ - if (asd->continuous_mode->val) - css_output_info = &stream_env->pipe_configs[pipe_id]. - vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; - else - css_output_info = &stream_env->pipe_configs[pipe_id]. - vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - - css_output_info->res.width = width; - css_output_info->res.height = height; - css_output_info->format = format; - css_output_info->padded_width = min_width; - dev_dbg(isp->dev, - "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n", - pipe_id, width, height, format); -} - -static int __get_frame_info(struct atomisp_sub_device *asd, - unsigned int stream_index, - struct atomisp_css_frame_info *info, - enum frame_info_type type, - enum ia_css_pipe_id pipe_id) -{ - struct atomisp_device *isp = asd->isp; - enum ia_css_err ret; - struct ia_css_pipe_info p_info; - - /* FIXME! No need to destroy/recreate all streams */ - if (__destroy_streams(asd, true)) - dev_warn(isp->dev, "destroy stream failed.\n"); - - if (__destroy_pipes(asd, true)) - dev_warn(isp->dev, "destroy pipe failed.\n"); - - if (__create_pipes(asd)) - return -EINVAL; - - if (__create_streams(asd)) - goto stream_err; - - ret = ia_css_pipe_get_info( - asd->stream_env[stream_index] - .pipes[pipe_id], &p_info); - if (ret == IA_CSS_SUCCESS) { - switch (type) { - case ATOMISP_CSS_VF_FRAME: - *info = p_info.vf_output_info[0]; - dev_dbg(isp->dev, "getting vf frame info.\n"); - break; - case ATOMISP_CSS_SECOND_VF_FRAME: - *info = p_info.vf_output_info[1]; - dev_dbg(isp->dev, "getting second vf frame info.\n"); - break; - case ATOMISP_CSS_OUTPUT_FRAME: - *info = p_info.output_info[0]; - dev_dbg(isp->dev, "getting main frame info.\n"); - break; - case ATOMISP_CSS_SECOND_OUTPUT_FRAME: - *info = p_info.output_info[1]; - dev_dbg(isp->dev, "getting second main frame info.\n"); - break; - case ATOMISP_CSS_RAW_FRAME: - *info = p_info.raw_output_info; - dev_dbg(isp->dev, "getting raw frame info.\n"); - } - dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n", - info->res.width, info->res.height, p_info.num_invalid_frames); - return 0; - } - -stream_err: - __destroy_pipes(asd, true); - return -EINVAL; -} - -static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd, - uint16_t source_pad) -{ - struct atomisp_device *isp = asd->isp; - /* - * to SOC camera, use yuvpp pipe. - */ - if (ATOMISP_USE_YUVPP(asd)) - return IA_CSS_PIPE_ID_YUVPP; - - switch (source_pad) { - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: - if (asd->yuvpp_mode) - return IA_CSS_PIPE_ID_YUVPP; - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO - || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) - return IA_CSS_PIPE_ID_VIDEO; - else - return IA_CSS_PIPE_ID_CAPTURE; - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - return IA_CSS_PIPE_ID_CAPTURE; - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - if (!atomisp_is_mbuscode_raw( - asd->fmt[asd->capture_pad].fmt.code)) - return IA_CSS_PIPE_ID_CAPTURE; - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: - if (asd->yuvpp_mode) - return IA_CSS_PIPE_ID_YUVPP; - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) - return IA_CSS_PIPE_ID_VIDEO; - else - return IA_CSS_PIPE_ID_PREVIEW; - } - dev_warn(isp->dev, - "invalid source pad:%d, return default preview pipe index.\n", - source_pad); - return IA_CSS_PIPE_ID_PREVIEW; -} - -int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, - uint16_t source_pad, - struct atomisp_css_frame_info *frame_info) -{ - struct ia_css_pipe_info info; - int pipe_index = atomisp_get_pipe_index(asd, source_pad); - int stream_index; - struct atomisp_device *isp = asd->isp; - - if (ATOMISP_SOC_CAMERA(asd)) - stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); - else { - stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ? - ATOMISP_INPUT_STREAM_VIDEO : - atomisp_source_pad_to_stream_id(asd, source_pad); - } - - if (IA_CSS_SUCCESS != ia_css_pipe_get_info(asd->stream_env[stream_index] - .pipes[pipe_index], &info)) { - dev_err(isp->dev, "ia_css_pipe_get_info FAILED"); - return -EINVAL; - } - - switch (source_pad) { - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - *frame_info = info.output_info[0]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: - if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val) - *frame_info = info. - output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; - else - *frame_info = info. - output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW) - *frame_info = info.output_info[0]; - else - *frame_info = info.vf_output_info[0]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && - (pipe_index == IA_CSS_PIPE_ID_VIDEO || - pipe_index == IA_CSS_PIPE_ID_YUVPP)) - if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val) - *frame_info = info. - vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; - else - *frame_info = info. - vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val) - *frame_info = - info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; - else - *frame_info = - info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - - break; - default: - frame_info = NULL; - break; - } - return frame_info ? 0 : -EINVAL; -} - -int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int padded_width, - enum atomisp_css_frame_format format) -{ - asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY]. - default_capture_config.mode = - CSS_CAPTURE_MODE_RAW; - - __configure_output(asd, stream_index, width, height, padded_width, - format, IA_CSS_PIPE_ID_COPY); - return 0; -} - -int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int padded_width, - enum atomisp_css_frame_format format) -{ - asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP]. - default_capture_config.mode = - CSS_CAPTURE_MODE_RAW; - - __configure_output(asd, stream_index, width, height, padded_width, - format, IA_CSS_PIPE_ID_YUVPP); - return 0; -} - -int atomisp_css_yuvpp_configure_viewfinder( - struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int min_width, - enum atomisp_css_frame_format format) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[stream_index]; - enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP; - - stream_env->pipe_configs[pipe_id].mode = - __pipe_id_to_pipe_mode(asd, pipe_id); - stream_env->update_pipe[pipe_id] = true; - - stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width; - stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height; - stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format; - stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width = - min_width; - return 0; -} - -int atomisp_css_yuvpp_get_output_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct atomisp_css_frame_info *info) -{ - return __get_frame_info(asd, stream_index, info, - ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP); -} - -int atomisp_css_yuvpp_get_viewfinder_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct atomisp_css_frame_info *info) -{ - return __get_frame_info(asd, stream_index, info, - ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP); -} - -int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - unsigned int min_width, - enum atomisp_css_frame_format format) -{ - /* - * to SOC camera, use yuvpp pipe. - */ - if (ATOMISP_USE_YUVPP(asd)) - __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, - min_width, format, IA_CSS_PIPE_ID_YUVPP); - else - __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, - min_width, format, IA_CSS_PIPE_ID_PREVIEW); - return 0; -} - -int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - unsigned int min_width, - enum atomisp_css_frame_format format) -{ - enum ia_css_pipe_id pipe_id; - - /* - * to SOC camera, use yuvpp pipe. - */ - if (ATOMISP_USE_YUVPP(asd)) - pipe_id = IA_CSS_PIPE_ID_YUVPP; - else - pipe_id = IA_CSS_PIPE_ID_CAPTURE; - - __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, - min_width, format, pipe_id); - return 0; -} - -int atomisp_css_video_configure_output(struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - unsigned int min_width, - enum atomisp_css_frame_format format) -{ - /* - * to SOC camera, use yuvpp pipe. - */ - if (ATOMISP_USE_YUVPP(asd)) - __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, - min_width, format, IA_CSS_PIPE_ID_YUVPP); - else - __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, - min_width, format, IA_CSS_PIPE_ID_VIDEO); - return 0; -} - -int atomisp_css_video_configure_viewfinder( - struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - unsigned int min_width, - enum atomisp_css_frame_format format) -{ - /* - * to SOC camera, video will use yuvpp pipe. - */ - if (ATOMISP_USE_YUVPP(asd)) - __configure_video_vf_output(asd, width, height, min_width, format, - IA_CSS_PIPE_ID_YUVPP); - else - __configure_vf_output(asd, width, height, min_width, format, - IA_CSS_PIPE_ID_VIDEO); - return 0; -} - -int atomisp_css_capture_configure_viewfinder( - struct atomisp_sub_device *asd, - unsigned int width, unsigned int height, - unsigned int min_width, - enum atomisp_css_frame_format format) -{ - enum ia_css_pipe_id pipe_id; - - /* - * to SOC camera, video will use yuvpp pipe. - */ - if (ATOMISP_USE_YUVPP(asd)) - pipe_id = IA_CSS_PIPE_ID_YUVPP; - else - pipe_id = IA_CSS_PIPE_ID_CAPTURE; - - __configure_vf_output(asd, width, height, min_width, format, - pipe_id); - return 0; -} - -int atomisp_css_video_get_viewfinder_frame_info( - struct atomisp_sub_device *asd, - struct atomisp_css_frame_info *info) -{ - enum ia_css_pipe_id pipe_id; - enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME; - - if (ATOMISP_USE_YUVPP(asd)) { - pipe_id = IA_CSS_PIPE_ID_YUVPP; - if (asd->continuous_mode->val) - frame_type = ATOMISP_CSS_SECOND_VF_FRAME; - } else { - pipe_id = IA_CSS_PIPE_ID_VIDEO; - } - - return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, - frame_type, pipe_id); -} - -int atomisp_css_capture_get_viewfinder_frame_info( - struct atomisp_sub_device *asd, - struct atomisp_css_frame_info *info) -{ - enum ia_css_pipe_id pipe_id; - - if (ATOMISP_USE_YUVPP(asd)) - pipe_id = IA_CSS_PIPE_ID_YUVPP; - else - pipe_id = IA_CSS_PIPE_ID_CAPTURE; - - return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, - ATOMISP_CSS_VF_FRAME, pipe_id); -} - -int atomisp_css_capture_get_output_raw_frame_info( - struct atomisp_sub_device *asd, - struct atomisp_css_frame_info *info) -{ - if (ATOMISP_USE_YUVPP(asd)) - return 0; - - return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, - ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE); -} - -int atomisp_css_copy_get_output_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct atomisp_css_frame_info *info) -{ - return __get_frame_info(asd, stream_index, info, - ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY); -} - -int atomisp_css_preview_get_output_frame_info( - struct atomisp_sub_device *asd, - struct atomisp_css_frame_info *info) -{ - enum ia_css_pipe_id pipe_id; - enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME; - - if (ATOMISP_USE_YUVPP(asd)) { - pipe_id = IA_CSS_PIPE_ID_YUVPP; - if (asd->continuous_mode->val) - frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME; - } else { - pipe_id = IA_CSS_PIPE_ID_PREVIEW; - } - - return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, - frame_type, pipe_id); -} - -int atomisp_css_capture_get_output_frame_info( - struct atomisp_sub_device *asd, - struct atomisp_css_frame_info *info) -{ - enum ia_css_pipe_id pipe_id; - - if (ATOMISP_USE_YUVPP(asd)) - pipe_id = IA_CSS_PIPE_ID_YUVPP; - else - pipe_id = IA_CSS_PIPE_ID_CAPTURE; - - return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, - ATOMISP_CSS_OUTPUT_FRAME, pipe_id); -} - -int atomisp_css_video_get_output_frame_info( - struct atomisp_sub_device *asd, - struct atomisp_css_frame_info *info) -{ - enum ia_css_pipe_id pipe_id; - enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME; - - if (ATOMISP_USE_YUVPP(asd)) { - pipe_id = IA_CSS_PIPE_ID_YUVPP; - if (asd->continuous_mode->val) - frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME; - } else { - pipe_id = IA_CSS_PIPE_ID_VIDEO; - } - - return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, - frame_type, pipe_id); -} - -int atomisp_css_preview_configure_pp_input( - struct atomisp_sub_device *asd, - unsigned int width, unsigned int height) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - __configure_preview_pp_input(asd, width, height, - ATOMISP_USE_YUVPP(asd) ? - IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW); - - if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. - capt_pp_in_res.width) - __configure_capture_pp_input(asd, width, height, - ATOMISP_USE_YUVPP(asd) ? - IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE); - return 0; -} - -int atomisp_css_capture_configure_pp_input( - struct atomisp_sub_device *asd, - unsigned int width, unsigned int height) -{ - __configure_capture_pp_input(asd, width, height, - ATOMISP_USE_YUVPP(asd) ? - IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE); - return 0; -} - -int atomisp_css_video_configure_pp_input( - struct atomisp_sub_device *asd, - unsigned int width, unsigned int height) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - - __configure_video_pp_input(asd, width, height, - ATOMISP_USE_YUVPP(asd) ? - IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO); - - if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. - capt_pp_in_res.width) - __configure_capture_pp_input(asd, width, height, - ATOMISP_USE_YUVPP(asd) ? - IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE); - return 0; -} - -int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd, - int num_captures, unsigned int skip, int offset) -{ - enum ia_css_err ret; - -#ifdef ISP2401 - dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n", - __func__, num_captures, skip, offset); -#endif - ret = ia_css_stream_capture( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - num_captures, skip, offset); - if (ret != IA_CSS_SUCCESS) - return -EINVAL; - - return 0; -} - -int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id) -{ - enum ia_css_err ret; - - ret = ia_css_stream_capture_frame( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - exp_id); - if (ret == IA_CSS_ERR_QUEUE_IS_FULL) { - /* capture cmd queue is full */ - return -EBUSY; - } else if (ret != IA_CSS_SUCCESS) { - return -EIO; - } - - return 0; -} - -int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id) -{ - enum ia_css_err ret; - - ret = ia_css_unlock_raw_frame( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - exp_id); - if (ret == IA_CSS_ERR_QUEUE_IS_FULL) - return -EAGAIN; - else if (ret != IA_CSS_SUCCESS) - return -EIO; - - return 0; -} - -int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd, - bool enable) -{ - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipe_configs[IA_CSS_PIPE_ID_CAPTURE] - .default_capture_config.enable_xnr = enable; - asd->params.capture_config.enable_xnr = enable; - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; - - return 0; -} - -void atomisp_css_send_input_frame(struct atomisp_sub_device *asd, - unsigned short *data, unsigned int width, - unsigned int height) -{ - ia_css_stream_send_input_frame( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - data, width, height); -} - -bool atomisp_css_isp_has_started(void) -{ - return ia_css_isp_has_started(); -} - -void atomisp_css_request_flash(struct atomisp_sub_device *asd) -{ - ia_css_stream_request_flash( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream); -} - -void atomisp_css_set_wb_config(struct atomisp_sub_device *asd, - struct atomisp_css_wb_config *wb_config) -{ - asd->params.config.wb_config = wb_config; -} - -void atomisp_css_set_ob_config(struct atomisp_sub_device *asd, - struct atomisp_css_ob_config *ob_config) -{ - asd->params.config.ob_config = ob_config; -} - -void atomisp_css_set_dp_config(struct atomisp_sub_device *asd, - struct atomisp_css_dp_config *dp_config) -{ - asd->params.config.dp_config = dp_config; -} - -void atomisp_css_set_de_config(struct atomisp_sub_device *asd, - struct atomisp_css_de_config *de_config) -{ - asd->params.config.de_config = de_config; -} - -void atomisp_css_set_dz_config(struct atomisp_sub_device *asd, - struct atomisp_css_dz_config *dz_config) -{ - asd->params.config.dz_config = dz_config; -} - -void atomisp_css_set_default_de_config(struct atomisp_sub_device *asd) -{ - asd->params.config.de_config = NULL; -} - -void atomisp_css_set_ce_config(struct atomisp_sub_device *asd, - struct atomisp_css_ce_config *ce_config) -{ - asd->params.config.ce_config = ce_config; -} - -void atomisp_css_set_nr_config(struct atomisp_sub_device *asd, - struct atomisp_css_nr_config *nr_config) -{ - asd->params.config.nr_config = nr_config; -} - -void atomisp_css_set_ee_config(struct atomisp_sub_device *asd, - struct atomisp_css_ee_config *ee_config) -{ - asd->params.config.ee_config = ee_config; -} - -void atomisp_css_set_tnr_config(struct atomisp_sub_device *asd, - struct atomisp_css_tnr_config *tnr_config) -{ - asd->params.config.tnr_config = tnr_config; -} - -void atomisp_css_set_cc_config(struct atomisp_sub_device *asd, - struct atomisp_css_cc_config *cc_config) -{ - asd->params.config.cc_config = cc_config; -} - -void atomisp_css_set_macc_table(struct atomisp_sub_device *asd, - struct atomisp_css_macc_table *macc_table) -{ - asd->params.config.macc_table = macc_table; -} - -void atomisp_css_set_macc_config(struct atomisp_sub_device *asd, - struct atomisp_css_macc_config *macc_config) -{ - asd->params.config.macc_config = macc_config; -} - -void atomisp_css_set_ecd_config(struct atomisp_sub_device *asd, - struct atomisp_css_ecd_config *ecd_config) -{ - asd->params.config.ecd_config = ecd_config; -} - -void atomisp_css_set_ynr_config(struct atomisp_sub_device *asd, - struct atomisp_css_ynr_config *ynr_config) -{ - asd->params.config.ynr_config = ynr_config; -} - -void atomisp_css_set_fc_config(struct atomisp_sub_device *asd, - struct atomisp_css_fc_config *fc_config) -{ - asd->params.config.fc_config = fc_config; -} - -void atomisp_css_set_ctc_config(struct atomisp_sub_device *asd, - struct atomisp_css_ctc_config *ctc_config) -{ - asd->params.config.ctc_config = ctc_config; -} - -void atomisp_css_set_cnr_config(struct atomisp_sub_device *asd, - struct atomisp_css_cnr_config *cnr_config) -{ - asd->params.config.cnr_config = cnr_config; -} - -void atomisp_css_set_aa_config(struct atomisp_sub_device *asd, - struct atomisp_css_aa_config *aa_config) -{ - asd->params.config.aa_config = aa_config; -} - -void atomisp_css_set_baa_config(struct atomisp_sub_device *asd, - struct atomisp_css_baa_config *baa_config) -{ - asd->params.config.baa_config = baa_config; -} - -void atomisp_css_set_anr_config(struct atomisp_sub_device *asd, - struct atomisp_css_anr_config *anr_config) -{ - asd->params.config.anr_config = anr_config; -} - -void atomisp_css_set_xnr_config(struct atomisp_sub_device *asd, - struct atomisp_css_xnr_config *xnr_config) -{ - asd->params.config.xnr_config = xnr_config; -} - -void atomisp_css_set_yuv2rgb_cc_config(struct atomisp_sub_device *asd, - struct atomisp_css_cc_config *yuv2rgb_cc_config) -{ - asd->params.config.yuv2rgb_cc_config = yuv2rgb_cc_config; -} - -void atomisp_css_set_rgb2yuv_cc_config(struct atomisp_sub_device *asd, - struct atomisp_css_cc_config *rgb2yuv_cc_config) -{ - asd->params.config.rgb2yuv_cc_config = rgb2yuv_cc_config; -} - -void atomisp_css_set_xnr_table(struct atomisp_sub_device *asd, - struct atomisp_css_xnr_table *xnr_table) -{ - asd->params.config.xnr_table = xnr_table; -} - -void atomisp_css_set_r_gamma_table(struct atomisp_sub_device *asd, - struct atomisp_css_rgb_gamma_table *r_gamma_table) -{ - asd->params.config.r_gamma_table = r_gamma_table; -} - -void atomisp_css_set_g_gamma_table(struct atomisp_sub_device *asd, - struct atomisp_css_rgb_gamma_table *g_gamma_table) -{ - asd->params.config.g_gamma_table = g_gamma_table; -} - -void atomisp_css_set_b_gamma_table(struct atomisp_sub_device *asd, - struct atomisp_css_rgb_gamma_table *b_gamma_table) -{ - asd->params.config.b_gamma_table = b_gamma_table; -} - -void atomisp_css_set_gamma_table(struct atomisp_sub_device *asd, - struct atomisp_css_gamma_table *gamma_table) -{ - asd->params.config.gamma_table = gamma_table; -} - -void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd, - struct atomisp_css_ctc_table *ctc_table) -{ - int i; - uint16_t *vamem_ptr = ctc_table->data.vamem_1; - int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE; - bool valid = false; - - /* workaround: if ctc_table is all 0, do not apply it */ - if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) { - vamem_ptr = ctc_table->data.vamem_2; - data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE; - } - - for (i = 0; i < data_size; i++) { - if (*(vamem_ptr + i)) { - valid = true; - break; - } - } - - if (valid) - asd->params.config.ctc_table = ctc_table; - else - dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n"); -} - -void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd, - struct atomisp_css_anr_thres *anr_thres) -{ - asd->params.config.anr_thres = anr_thres; -} - -void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd, - struct atomisp_css_dvs_6axis *dvs_6axis) -{ - asd->params.config.dvs_6axis_config = dvs_6axis; -} - -void atomisp_css_set_gc_config(struct atomisp_sub_device *asd, - struct atomisp_css_gc_config *gc_config) -{ - asd->params.config.gc_config = gc_config; -} - -void atomisp_css_set_3a_config(struct atomisp_sub_device *asd, - struct atomisp_css_3a_config *s3a_config) -{ - asd->params.config.s3a_config = s3a_config; -} - -void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd, - struct atomisp_dis_vector *vector) -{ - if (!asd->params.config.motion_vector) - asd->params.config.motion_vector = &asd->params.css_param.motion_vector; - - memset(asd->params.config.motion_vector, - 0, sizeof(struct ia_css_vector)); - asd->params.css_param.motion_vector.x = vector->x; - asd->params.css_param.motion_vector.y = vector->y; -} - -static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd, - struct atomisp_dvs_grid_info *atomgrid) -{ - struct atomisp_css_dvs_grid_info *cur = - atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); - - if (!cur) { - dev_err(asd->isp->dev, "dvs grid not available!\n"); - return -EINVAL; - } - - if (sizeof(*cur) != sizeof(*atomgrid)) { - dev_err(asd->isp->dev, "dvs grid mis-match!\n"); - return -EINVAL; - } - - if (!cur->enable) { - dev_err(asd->isp->dev, "dvs not enabled!\n"); - return -EINVAL; - } - - return memcmp(atomgrid, cur, sizeof(*cur)); -} - -void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd, - struct ia_css_dvs2_coefficients *coefs) -{ - asd->params.config.dvs2_coefs = coefs; -} - -int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd, - struct atomisp_dis_coefficients *coefs) -{ - if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0) - /* If the grid info in the argument differs from the current - grid info, we tell the caller to reset the grid size and - try again. */ - return -EAGAIN; - - if (coefs->hor_coefs.odd_real == NULL || - coefs->hor_coefs.odd_imag == NULL || - coefs->hor_coefs.even_real == NULL || - coefs->hor_coefs.even_imag == NULL || - coefs->ver_coefs.odd_real == NULL || - coefs->ver_coefs.odd_imag == NULL || - coefs->ver_coefs.even_real == NULL || - coefs->ver_coefs.even_imag == NULL || - asd->params.css_param.dvs2_coeff->hor_coefs.odd_real == NULL || - asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag == NULL || - asd->params.css_param.dvs2_coeff->hor_coefs.even_real == NULL || - asd->params.css_param.dvs2_coeff->hor_coefs.even_imag == NULL || - asd->params.css_param.dvs2_coeff->ver_coefs.odd_real == NULL || - asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag == NULL || - asd->params.css_param.dvs2_coeff->ver_coefs.even_real == NULL || - asd->params.css_param.dvs2_coeff->ver_coefs.even_imag == NULL) - return -EINVAL; - - if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real, - coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes)) - return -EFAULT; - if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag, - coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes)) - return -EFAULT; - if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real, - coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes)) - return -EFAULT; - if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag, - coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes)) - return -EFAULT; - - if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real, - coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes)) - return -EFAULT; - if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag, - coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes)) - return -EFAULT; - if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real, - coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes)) - return -EFAULT; - if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag, - coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes)) - return -EFAULT; - - asd->params.css_param.update_flag.dvs2_coefs = - (struct atomisp_dvs2_coefficients *) - asd->params.css_param.dvs2_coeff; - /* FIXME! */ -/* asd->params.dis_proj_data_valid = false; */ - asd->params.css_update_params_needed = true; - - return 0; -} - -void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd, - unsigned int zoom) -{ - struct atomisp_device *isp = asd->isp; - - if (zoom == asd->params.css_param.dz_config.dx && - zoom == asd->params.css_param.dz_config.dy) { - dev_dbg(isp->dev, "same zoom scale. skipped.\n"); - return; - } - - memset(&asd->params.css_param.dz_config, 0, - sizeof(struct ia_css_dz_config)); - asd->params.css_param.dz_config.dx = zoom; - asd->params.css_param.dz_config.dy = zoom; - - asd->params.css_param.update_flag.dz_config = - (struct atomisp_dz_config *) &asd->params.css_param.dz_config; - asd->params.css_update_params_needed = true; -} - -void atomisp_css_set_formats_config(struct atomisp_sub_device *asd, - struct atomisp_css_formats_config *formats_config) -{ - asd->params.config.formats_config = formats_config; -} - -int atomisp_css_get_wb_config(struct atomisp_sub_device *asd, - struct atomisp_wb_config *config) -{ - struct atomisp_css_wb_config wb_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&wb_config, 0, sizeof(struct atomisp_css_wb_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.wb_config = &wb_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, &wb_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_ob_config(struct atomisp_sub_device *asd, - struct atomisp_ob_config *config) -{ - struct atomisp_css_ob_config ob_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&ob_config, 0, sizeof(struct atomisp_css_ob_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.ob_config = &ob_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, &ob_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_dp_config(struct atomisp_sub_device *asd, - struct atomisp_dp_config *config) -{ - struct atomisp_css_dp_config dp_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&dp_config, 0, sizeof(struct atomisp_css_dp_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.dp_config = &dp_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, &dp_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_de_config(struct atomisp_sub_device *asd, - struct atomisp_de_config *config) -{ - struct atomisp_css_de_config de_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&de_config, 0, sizeof(struct atomisp_css_de_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.de_config = &de_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, &de_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_nr_config(struct atomisp_sub_device *asd, - struct atomisp_nr_config *config) -{ - struct atomisp_css_nr_config nr_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&nr_config, 0, sizeof(struct atomisp_css_nr_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - - isp_config.nr_config = &nr_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, &nr_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_ee_config(struct atomisp_sub_device *asd, - struct atomisp_ee_config *config) -{ - struct atomisp_css_ee_config ee_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&ee_config, 0, sizeof(struct atomisp_css_ee_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.ee_config = &ee_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, &ee_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd, - struct atomisp_tnr_config *config) -{ - struct atomisp_css_tnr_config tnr_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&tnr_config, 0, sizeof(struct atomisp_css_tnr_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.tnr_config = &tnr_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, &tnr_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd, - struct atomisp_ctc_table *config) -{ - struct atomisp_css_ctc_table *tab; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - - tab = vzalloc(sizeof(struct atomisp_css_ctc_table)); - if (!tab) - return -ENOMEM; - - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.ctc_table = tab; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, tab, sizeof(*tab)); - vfree(tab); - - return 0; -} - -int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd, - struct atomisp_gamma_table *config) -{ - struct atomisp_css_gamma_table *tab; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - - tab = vzalloc(sizeof(struct atomisp_css_gamma_table)); - if (!tab) - return -ENOMEM; - - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.gamma_table = tab; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - memcpy(config, tab, sizeof(*tab)); - vfree(tab); - - return 0; -} - -int atomisp_css_get_gc_config(struct atomisp_sub_device *asd, - struct atomisp_gc_config *config) -{ - struct atomisp_css_gc_config gc_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&gc_config, 0, sizeof(struct atomisp_css_gc_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.gc_config = &gc_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - /* Get gamma correction params from current setup */ - memcpy(config, &gc_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_3a_config(struct atomisp_sub_device *asd, - struct atomisp_3a_config *config) -{ - struct atomisp_css_3a_config s3a_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&s3a_config, 0, sizeof(struct atomisp_css_3a_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.s3a_config = &s3a_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - /* Get white balance from current setup */ - memcpy(config, &s3a_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_formats_config(struct atomisp_sub_device *asd, - struct atomisp_formats_config *config) -{ - struct atomisp_css_formats_config formats_config; - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&formats_config, 0, sizeof(formats_config)); - memset(&isp_config, 0, sizeof(isp_config)); - isp_config.formats_config = &formats_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - /* Get narrow gamma from current setup */ - memcpy(config, &formats_config, sizeof(*config)); - - return 0; -} - -int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd, - unsigned int *zoom) -{ - struct ia_css_dz_config dz_config; /** Digital Zoom */ - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, "%s called after streamoff, skipping.\n", - __func__); - return -EINVAL; - } - memset(&dz_config, 0, sizeof(struct ia_css_dz_config)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.dz_config = &dz_config; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); - *zoom = dz_config.dx; - - return 0; -} - - -/* - * Function to set/get image stablization statistics - */ -int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd, - struct atomisp_dis_statistics *stats) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_dis_buf *dis_buf; - unsigned long flags; - - if (asd->params.dvs_stat->hor_prod.odd_real == NULL || - asd->params.dvs_stat->hor_prod.odd_imag == NULL || - asd->params.dvs_stat->hor_prod.even_real == NULL || - asd->params.dvs_stat->hor_prod.even_imag == NULL || - asd->params.dvs_stat->ver_prod.odd_real == NULL || - asd->params.dvs_stat->ver_prod.odd_imag == NULL || - asd->params.dvs_stat->ver_prod.even_real == NULL || - asd->params.dvs_stat->ver_prod.even_imag == NULL) - return -EINVAL; - - /* isp needs to be streaming to get DIS statistics */ - spin_lock_irqsave(&isp->lock, flags); - if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) { - spin_unlock_irqrestore(&isp->lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&isp->lock, flags); - - if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0) - /* If the grid info in the argument differs from the current - grid info, we tell the caller to reset the grid size and - try again. */ - return -EAGAIN; - - spin_lock_irqsave(&asd->dis_stats_lock, flags); - if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) { - spin_unlock_irqrestore(&asd->dis_stats_lock, flags); - dev_err(isp->dev, "dis statistics is not valid.\n"); - return -EAGAIN; - } - - dis_buf = list_entry(asd->dis_stats.next, - struct atomisp_dis_buf, list); - list_del_init(&dis_buf->list); - spin_unlock_irqrestore(&asd->dis_stats_lock, flags); - - if (dis_buf->dvs_map) - ia_css_translate_dvs2_statistics( - asd->params.dvs_stat, dis_buf->dvs_map); - else - ia_css_get_dvs2_statistics(asd->params.dvs_stat, - dis_buf->dis_data); - stats->exp_id = dis_buf->dis_data->exp_id; - - spin_lock_irqsave(&asd->dis_stats_lock, flags); - list_add_tail(&dis_buf->list, &asd->dis_stats); - spin_unlock_irqrestore(&asd->dis_stats_lock, flags); - - if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real, - asd->params.dvs_stat->ver_prod.odd_real, - asd->params.dvs_ver_proj_bytes)) - return -EFAULT; - if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag, - asd->params.dvs_stat->ver_prod.odd_imag, - asd->params.dvs_ver_proj_bytes)) - return -EFAULT; - if (copy_to_user(stats->dvs2_stat.ver_prod.even_real, - asd->params.dvs_stat->ver_prod.even_real, - asd->params.dvs_ver_proj_bytes)) - return -EFAULT; - if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag, - asd->params.dvs_stat->ver_prod.even_imag, - asd->params.dvs_ver_proj_bytes)) - return -EFAULT; - if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real, - asd->params.dvs_stat->hor_prod.odd_real, - asd->params.dvs_hor_proj_bytes)) - return -EFAULT; - if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag, - asd->params.dvs_stat->hor_prod.odd_imag, - asd->params.dvs_hor_proj_bytes)) - return -EFAULT; - if (copy_to_user(stats->dvs2_stat.hor_prod.even_real, - asd->params.dvs_stat->hor_prod.even_real, - asd->params.dvs_hor_proj_bytes)) - return -EFAULT; - if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag, - asd->params.dvs_stat->hor_prod.even_imag, - asd->params.dvs_hor_proj_bytes)) - return -EFAULT; - - return 0; -} - -struct atomisp_css_shading_table *atomisp_css_shading_table_alloc( - unsigned int width, unsigned int height) -{ - return ia_css_shading_table_alloc(width, height); -} - -void atomisp_css_set_shading_table(struct atomisp_sub_device *asd, - struct atomisp_css_shading_table *table) -{ - asd->params.config.shading_table = table; -} - -void atomisp_css_shading_table_free(struct atomisp_css_shading_table *table) -{ - ia_css_shading_table_free(table); -} - -struct atomisp_css_morph_table *atomisp_css_morph_table_allocate( - unsigned int width, unsigned int height) -{ - return ia_css_morph_table_allocate(width, height); -} - -void atomisp_css_set_morph_table(struct atomisp_sub_device *asd, - struct atomisp_css_morph_table *table) -{ - asd->params.config.morph_table = table; -} - -void atomisp_css_get_morph_table(struct atomisp_sub_device *asd, - struct atomisp_css_morph_table *table) -{ - struct ia_css_isp_config isp_config; - struct atomisp_device *isp = asd->isp; - - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { - dev_err(isp->dev, - "%s called after streamoff, skipping.\n", __func__); - return; - } - memset(table, 0, sizeof(struct atomisp_css_morph_table)); - memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); - isp_config.morph_table = table; - ia_css_stream_get_isp_config( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - &isp_config); -} - -void atomisp_css_morph_table_free(struct atomisp_css_morph_table *table) -{ - ia_css_morph_table_free(table); -} - -void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp, - unsigned int overlap) -{ - /* CSS 2.0 doesn't support this API. */ - dev_dbg(isp->dev, "set cont prev start time is not supported.\n"); - return; -} - -void atomisp_css_acc_done(struct atomisp_sub_device *asd) -{ - complete(&asd->acc.acc_done); -} - -int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd) -{ - int ret = 0; - struct atomisp_device *isp = asd->isp; - - /* Unlock the isp mutex taken in IOCTL handler before sleeping! */ - rt_mutex_unlock(&isp->mutex); - if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done, - ATOMISP_ISP_TIMEOUT_DURATION) == 0) { - dev_err(isp->dev, "<%s: completion timeout\n", __func__); - atomisp_css_debug_dump_sp_sw_debug_info(); - atomisp_css_debug_dump_debug_info(__func__); - ret = -EIO; - } - rt_mutex_lock(&isp->mutex); - - return ret; -} - -/* Set the ACC binary arguments */ -int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw) -{ - unsigned int mem; - - for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) { - if (acc_fw->args[mem].length == 0) - continue; - - ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers, - IA_CSS_PARAM_CLASS_PARAM, mem, - acc_fw->args[mem].css_ptr, - acc_fw->args[mem].length); - } - - return 0; -} - -/* Load acc binary extension */ -int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd, - struct atomisp_css_fw_info *fw, - enum atomisp_css_pipe_id pipe_id, - unsigned int type) -{ - struct atomisp_css_fw_info **hd; - - fw->next = NULL; - hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipe_configs[pipe_id].acc_extension); - while (*hd) - hd = &(*hd)->next; - *hd = fw; - - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .update_pipe[pipe_id] = true; - return 0; -} - -/* Unload acc binary extension */ -void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd, - struct atomisp_css_fw_info *fw, - enum atomisp_css_pipe_id pipe_id) -{ - struct atomisp_css_fw_info **hd; - - hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipe_configs[pipe_id].acc_extension); - while (*hd && *hd != fw) - hd = &(*hd)->next; - if (!*hd) { - dev_err(asd->isp->dev, "did not find acc fw for removal\n"); - return; - } - *hd = fw->next; - fw->next = NULL; - - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .update_pipe[pipe_id] = true; -} - -int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd) -{ - struct atomisp_device *isp = asd->isp; - struct ia_css_pipe_config *pipe_config; - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - - if (stream_env->acc_stream) { - if (stream_env->acc_stream_state == CSS_STREAM_STARTED) { - if (ia_css_stream_stop(stream_env->acc_stream) - != IA_CSS_SUCCESS) { - dev_err(isp->dev, "stop acc_stream failed.\n"); - return -EBUSY; - } - } - - if (ia_css_stream_destroy(stream_env->acc_stream) - != IA_CSS_SUCCESS) { - dev_err(isp->dev, "destroy acc_stream failed.\n"); - return -EBUSY; - } - stream_env->acc_stream = NULL; - } - - pipe_config = &stream_env->pipe_configs[CSS_PIPE_ID_ACC]; - ia_css_pipe_config_defaults(pipe_config); - asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES * - sizeof(void *), GFP_KERNEL); - if (!asd->acc.acc_stages) - return -ENOMEM; - pipe_config->acc_stages = asd->acc.acc_stages; - pipe_config->mode = IA_CSS_PIPE_MODE_ACC; - pipe_config->num_acc_stages = 0; - - /* - * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe, - * because pipe configuration will soon be changed by - * atomisp_css_load_acc_binary() - */ - return 0; -} - -int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd) -{ - struct atomisp_device *isp = asd->isp; - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - struct ia_css_pipe_config *pipe_config = - &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]; - - if (ia_css_pipe_create(pipe_config, - &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != IA_CSS_SUCCESS) { - dev_err(isp->dev, "%s: ia_css_pipe_create failed\n", - __func__); - return -EBADE; - } - - memset(&stream_env->acc_stream_config, 0, - sizeof(struct ia_css_stream_config)); - if (ia_css_stream_create(&stream_env->acc_stream_config, 1, - &stream_env->pipes[IA_CSS_PIPE_ID_ACC], - &stream_env->acc_stream) != IA_CSS_SUCCESS) { - dev_err(isp->dev, "%s: create acc_stream error.\n", __func__); - return -EINVAL; - } - stream_env->acc_stream_state = CSS_STREAM_CREATED; - - init_completion(&asd->acc.acc_done); - asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC]; - - atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false); - - if (ia_css_start_sp() != IA_CSS_SUCCESS) { - dev_err(isp->dev, "start sp error.\n"); - return -EIO; - } - - if (ia_css_stream_start(stream_env->acc_stream) - != IA_CSS_SUCCESS) { - dev_err(isp->dev, "acc_stream start error.\n"); - return -EIO; - } - - stream_env->acc_stream_state = CSS_STREAM_STARTED; - return 0; -} - -int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - if (stream_env->acc_stream_state == CSS_STREAM_STARTED) { - ia_css_stream_stop(stream_env->acc_stream); - stream_env->acc_stream_state = CSS_STREAM_STOPPED; - } - return 0; -} - -void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - if (stream_env->acc_stream) { - if (ia_css_stream_destroy(stream_env->acc_stream) - != IA_CSS_SUCCESS) - dev_warn(asd->isp->dev, - "destroy acc_stream failed.\n"); - stream_env->acc_stream = NULL; - } - - if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) { - if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC]) - != IA_CSS_SUCCESS) - dev_warn(asd->isp->dev, - "destroy ACC pipe failed.\n"); - stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL; - stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false; - ia_css_pipe_config_defaults( - &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]); - ia_css_pipe_extra_config_defaults( - &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]); - } - asd->acc.pipeline = NULL; - - /* css 2.0 API limitation: ia_css_stop_sp() could be only called after - * destroy all pipes - */ - ia_css_stop_sp(); - - kfree(asd->acc.acc_stages); - asd->acc.acc_stages = NULL; - - atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false); -} - -int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd, - struct atomisp_css_fw_info *fw, - unsigned int index) -{ - struct ia_css_pipe_config *pipe_config = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipe_configs[IA_CSS_PIPE_ID_ACC]; - - if (index >= MAX_ACC_STAGES) { - dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n", - __func__, index); - return -ENOMEM; - } - - pipe_config->acc_stages[index] = fw; - pipe_config->num_acc_stages = index + 1; - pipe_config->acc_num_execs = 1; - - return 0; -} - -static struct atomisp_sub_device *__get_atomisp_subdev( - struct ia_css_pipe *css_pipe, - struct atomisp_device *isp, - enum atomisp_input_stream_id *stream_id) -{ - int i, j, k; - struct atomisp_sub_device *asd; - struct atomisp_stream_env *stream_env; - - for (i = 0; i < isp->num_of_streams; i++) { - asd = &isp->asd[i]; - if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED && - !asd->acc.pipeline) - continue; - for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) { - stream_env = &asd->stream_env[j]; - for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) { - if (stream_env->pipes[k] && - stream_env->pipes[k] == css_pipe) { - *stream_id = j; - return asd; - } - } - } - } - - return NULL; -} - -int atomisp_css_isr_thread(struct atomisp_device *isp, - bool *frame_done_found, - bool *css_pipe_done) -{ - enum atomisp_input_stream_id stream_id = 0; - struct atomisp_css_event current_event; - struct atomisp_sub_device *asd; -#ifndef ISP2401 - bool reset_wdt_timer[MAX_STREAM_NUM] = {false}; -#endif - int i; - - while (!atomisp_css_dequeue_event(¤t_event)) { - if (current_event.event.type == - IA_CSS_EVENT_TYPE_FW_ASSERT) { - /* - * Received FW assertion signal, - * trigger WDT to recover - */ - dev_err(isp->dev, "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n", - __func__, - current_event.event.fw_assert_module_id, - current_event.event.fw_assert_line_no); - for (i = 0; i < isp->num_of_streams; i++) - atomisp_wdt_stop(&isp->asd[i], 0); -#ifndef ISP2401 - atomisp_wdt(&isp->asd[0].wdt); -#else - queue_work(isp->wdt_work_queue, &isp->wdt_work); -#endif - return -EINVAL; - } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) { - dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n", - __func__, current_event.event.fw_warning, - current_event.event.exp_id); - continue; - } - - asd = __get_atomisp_subdev(current_event.event.pipe, - isp, &stream_id); - if (!asd) { - if (current_event.event.type == CSS_EVENT_TIMER) - dev_dbg(isp->dev, - "event: Timer event."); - else - dev_warn(isp->dev, "%s:no subdev.event:%d", - __func__, - current_event.event.type); - continue; - } - - atomisp_css_temp_pipe_to_pipe_id(asd, ¤t_event); - switch (current_event.event.type) { - case CSS_EVENT_OUTPUT_FRAME_DONE: - frame_done_found[asd->index] = true; - atomisp_buf_done(asd, 0, CSS_BUFFER_TYPE_OUTPUT_FRAME, - current_event.pipe, true, stream_id); -#ifndef ISP2401 - reset_wdt_timer[asd->index] = true; /* ISP running */ -#endif - break; - case CSS_EVENT_SEC_OUTPUT_FRAME_DONE: - frame_done_found[asd->index] = true; - atomisp_buf_done(asd, 0, CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME, - current_event.pipe, true, stream_id); -#ifndef ISP2401 - reset_wdt_timer[asd->index] = true; /* ISP running */ -#endif - break; - case CSS_EVENT_3A_STATISTICS_DONE: - atomisp_buf_done(asd, 0, - CSS_BUFFER_TYPE_3A_STATISTICS, - current_event.pipe, - false, stream_id); - break; - case CSS_EVENT_METADATA_DONE: - atomisp_buf_done(asd, 0, - CSS_BUFFER_TYPE_METADATA, - current_event.pipe, - false, stream_id); - break; - case CSS_EVENT_VF_OUTPUT_FRAME_DONE: - atomisp_buf_done(asd, 0, - CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, - current_event.pipe, true, stream_id); -#ifndef ISP2401 - reset_wdt_timer[asd->index] = true; /* ISP running */ -#endif - break; - case CSS_EVENT_SEC_VF_OUTPUT_FRAME_DONE: - atomisp_buf_done(asd, 0, - CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME, - current_event.pipe, true, stream_id); -#ifndef ISP2401 - reset_wdt_timer[asd->index] = true; /* ISP running */ -#endif - break; - case CSS_EVENT_DIS_STATISTICS_DONE: - atomisp_buf_done(asd, 0, - CSS_BUFFER_TYPE_DIS_STATISTICS, - current_event.pipe, - false, stream_id); - break; - case CSS_EVENT_PIPELINE_DONE: - css_pipe_done[asd->index] = true; - break; - case CSS_EVENT_ACC_STAGE_COMPLETE: - atomisp_acc_done(asd, current_event.event.fw_handle); - break; - default: - dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n", - current_event.event.type); - break; - } - } -#ifndef ISP2401 - /* If there are no buffers queued then - * delete wdt timer. */ - for (i = 0; i < isp->num_of_streams; i++) { - asd = &isp->asd[i]; - if (!asd) - continue; - if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) - continue; - if (!atomisp_buffers_queued(asd)) - atomisp_wdt_stop(asd, false); - else if (reset_wdt_timer[i]) - /* SOF irq should not reset wdt timer. */ - atomisp_wdt_refresh(asd, - ATOMISP_WDT_KEEP_CURRENT_DELAY); - } -#endif - - return 0; -} - -bool atomisp_css_valid_sof(struct atomisp_device *isp) -{ - unsigned int i, j; - - /* Loop for each css stream */ - for (i = 0; i < isp->num_of_streams; i++) { - struct atomisp_sub_device *asd = &isp->asd[i]; - /* Loop for each css vc stream */ - for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) { - if (asd->stream_env[j].stream && - asd->stream_env[j].stream_config.mode == - IA_CSS_INPUT_MODE_BUFFERED_SENSOR) - return false; - } - } - - return true; -} - -int atomisp_css_debug_dump_isp_binary(void) -{ - ia_css_debug_dump_isp_binary(); - return 0; -} - -int atomisp_css_dump_sp_raw_copy_linecount(bool reduced) -{ - sh_css_dump_sp_raw_copy_linecount(reduced); - return 0; -} - -int atomisp_css_dump_blob_infor(void) -{ - struct ia_css_blob_descr *bd = sh_css_blob_info; - unsigned int i, nm = sh_css_num_binaries; - - if (nm == 0) - return -EPERM; - if (bd == NULL) - return -EPERM; - - for (i = 1; i < sh_css_num_binaries; i++) - dev_dbg(atomisp_dev, "Num%d binary id is %d, name is %s\n", i, - bd[i-1].header.info.isp.sp.id, bd[i-1].name); - - return 0; -} - -void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd, - uint32_t isp_config_id) -{ - asd->params.config.isp_config_id = isp_config_id; -} - -void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd, - struct atomisp_css_frame *output_frame) -{ - asd->params.config.output_frame = output_frame; -} - -int atomisp_get_css_dbgfunc(void) -{ - return dbg_func; -} - -int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt) -{ - int ret; - - ret = __set_css_print_env(isp, opt); - if (ret == 0) - dbg_func = opt; - - return ret; -} -void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable) -{ - ia_css_en_dz_capt_pipe( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, - enable); -} - -struct atomisp_css_dvs_grid_info *atomisp_css_get_dvs_grid_info( - struct atomisp_css_grid_info *grid_info) -{ - if (!grid_info) - return NULL; - -#ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED - return &grid_info->dvs_grid.dvs_grid_info; -#else - return &grid_info->dvs_grid; -#endif -} |