From 4b76edff35ad91da202c8db57946b3e1c7b08745 Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Thu, 7 Jan 2021 15:36:46 +0530 Subject: [PATCH 01/20] msm: camera: icp: allow icp debug clock for debug purpose Max support clock frequency varies from target to target. Do not restrict the debug icp clock with max supported clock and allow it to set with any value. CRs-Fixed: 2878329 Change-Id: Ia157d38c4aa4b1183650bf6ff47f3181fb8012cd Signed-off-by: Alok Chauhan --- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index e556ca6f1857..d6a1ecee86f9 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -1062,8 +1062,7 @@ static bool cam_icp_update_clk_free(struct cam_icp_hw_mgr *hw_mgr, static bool cam_icp_debug_clk_update(struct cam_icp_clk_info *hw_mgr_clk_info) { - if (icp_hw_mgr.icp_debug_clk < ICP_CLK_TURBO_HZ && - icp_hw_mgr.icp_debug_clk && + if (icp_hw_mgr.icp_debug_clk && icp_hw_mgr.icp_debug_clk != hw_mgr_clk_info->curr_clk) { hw_mgr_clk_info->base_clk = icp_hw_mgr.icp_debug_clk; hw_mgr_clk_info->curr_clk = icp_hw_mgr.icp_debug_clk; From d3c7cff028bb770d1f728aa1769eee624017635d Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Thu, 1 Apr 2021 14:36:58 +0530 Subject: [PATCH 02/20] msm: camera: cpas: Change to set OT value to 8 for RT block This change is set the OT values for RT client of Camonc to 8 for Yupik camera. CRs-Fixed: 2924987 Change-Id: Icb7f30c23f5899558a41308fe313d46fd8d992a3 Signed-off-by: Ayush Kumar --- drivers/cam_cpas/cpas_top/cpastop_v165_100.h | 63 ++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h index 8e41284604f6..9dc47566bb37 100644 --- a/drivers/cam_cpas/cpas_top/cpastop_v165_100.h +++ b/drivers/cam_cpas/cpas_top/cpastop_v165_100.h @@ -289,6 +289,27 @@ static struct cam_camnoc_specific */ .enable = false, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4808, /* IFE01234_RDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4820, /* IFE01234_RDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4824, /* IFE01234_RDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IFE01_NRDI_WRITE, @@ -343,6 +364,27 @@ static struct cam_camnoc_specific .offset = 0x3B88, /* IFE01_NRDI_ENCCTL_LOW */ .value = 1, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4708, /* IFE01_NRDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4720, /* IFE01_NRDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4724, /* IFE01_NRDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IFE2_NRDI_WRITE, @@ -397,6 +439,27 @@ static struct cam_camnoc_specific .offset = 0x5588, /* IFE2_NRDI_ENCCTL_LOW */ .value = 0, }, + .qosgen_mainctl = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5188, /* IFE2_NRDI_QOSGEN_MAINCTL */ + .value = 0x2, + }, + .qosgen_shaping_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x51A0, /* IFE2_NRDI_QOSGEN_SHAPING_LOW */ + .value = 0x07070707, + }, + .qosgen_shaping_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x51A4, /* IFE2_NRDI_QOSGEN_SHAPING_HIGH */ + .value = 0x07070707, + }, }, { .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ, From 8f9d699778908bbcbcf8044e734b16231d44dece Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 15 Apr 2021 13:31:25 +0530 Subject: [PATCH 03/20] msm: camera: tfe: Drop first rdi frame in dual tfe scenario In Dual tfe scenario, tfe csid drop first frame in the ipp pix path to sync both master and slave, but rdi frame will go to tfe. this will cause issues in the camif and rdi sub sampling scenarios. in sub sampling scenarios both camif and rdi should be subsampled on same frames. To achieve this drop the rdi first frame from csid in dual tfe scenarios. Change-Id: I73e98a6d3d973af93bbe6afef7585a95578f2a2b CRs-Fixed: 2923045 Signed-off-by: Ravikishore Pampana --- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 216 +++++++++++++++++- .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.h | 12 +- 2 files changed, 219 insertions(+), 9 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index a22a68e1efe0..8dd9f0f0337e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -203,6 +203,152 @@ static int cam_tfe_csid_get_format_ipp( return rc; } +static void cam_tfe_csid_enable_path_for_init_frame_drop( + struct cam_tfe_csid_hw *csid_hw, + int res_id) +{ + struct cam_tfe_csid_path_cfg *path_data; + const struct cam_tfe_csid_pxl_reg_offset *pxl_reg = NULL; + const struct cam_tfe_csid_rdi_reg_offset *rdi_reg = NULL; + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_isp_resource_node *res; + uint32_t val; + + if (!csid_hw) { + CAM_WARN(CAM_ISP, "csid_hw cannot be NULL"); + return; + } + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + if (res_id == CAM_TFE_CSID_PATH_RES_IPP) { + res = &csid_hw->ipp_res; + pxl_reg = csid_reg->ipp_reg; + } else if (res_id >= CAM_TFE_CSID_PATH_RES_RDI_0 && + res_id <= CAM_TFE_CSID_PATH_RES_RDI_2) { + res = &csid_hw->rdi_res[res_id]; + rdi_reg = csid_reg->rdi_reg[res_id]; + } else { + CAM_ERR(CAM_ISP, "Invalid res_id"); + return; + } + + path_data = (struct cam_tfe_csid_path_cfg *)res->res_priv; + + if (!path_data || !path_data->init_frame_drop) + return; + if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) + return; + + path_data->res_sof_cnt++; + if ((path_data->res_sof_cnt + 1) < + path_data->res_sof_cnt) { + CAM_WARN(CAM_ISP, "Res %d sof count overflow %d", + res_id, path_data->res_sof_cnt); + return; + } + + CAM_DBG(CAM_ISP, "CSID:%d res_id %d SOF cnt:%d init_frame_drop:%d", + csid_hw->hw_intf->hw_idx, res_id, path_data->res_sof_cnt, + path_data->init_frame_drop); + + if ((path_data->res_sof_cnt == + path_data->init_frame_drop) && + pxl_reg) { + CAM_DBG(CAM_ISP, "Enabling pixel IPP Path"); + if (path_data->sync_mode != + CAM_ISP_HW_SYNC_SLAVE) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + val |= CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY; + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_ctrl_addr); + } + + if (!(csid_hw->csid_debug & + TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + val &= ~(TFE_CSID_PATH_INFO_INPUT_SOF); + cam_io_w_mb(val, + soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_irq_mask_addr); + } + } else if ((path_data->res_sof_cnt == + path_data->init_frame_drop) && rdi_reg) { + CAM_DBG(CAM_ISP, "Enabling RDI %d Path", res_id); + cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_ctrl_addr); + if (!(csid_hw->csid_debug & + TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_irq_mask_addr); + val &= ~(TFE_CSID_PATH_INFO_INPUT_SOF); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_irq_mask_addr); + } + } +} + +static bool cam_tfe_csid_check_path_active(struct cam_tfe_csid_hw *csid_hw) +{ + const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t i; + uint32_t path_status = 1; + + csid_reg = csid_hw->csid_info->csid_reg; + soc_info = &csid_hw->hw_info->soc_info; + + /* check the IPP path status */ + if (csid_reg->cmn_reg->num_pix) { + path_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_status_addr); + CAM_DBG(CAM_ISP, "CSID:%d IPP path status:%d", + csid_hw->hw_intf->hw_idx, path_status); + /* if status is 0 then it is active */ + if (!path_status) + goto end; + } + + /* Check the RDI path status */ + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + path_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_status_addr); + CAM_DBG(CAM_ISP, "CSID:%d RDI:%d path status:%d", + csid_hw->hw_intf->hw_idx, i, path_status); + /* if status is 0 then it is active */ + if (!path_status) + goto end; + } + +end: + /* if status is 0 then path is active */ + return path_status ? false : true; +} + +static void cam_tfe_csid_reset_path_data( + struct cam_tfe_csid_hw *csid_hw, + struct cam_isp_resource_node *res) +{ + struct cam_tfe_csid_path_cfg *path_data = NULL; + + if (!csid_hw || !res) { + CAM_WARN(CAM_ISP, "csid_hw or res cannot be NULL"); + return; + } + path_data = res->res_priv; + + if (path_data) { + path_data->init_frame_drop = 0; + path_data->res_sof_cnt = 0; + } +} + static int cam_tfe_csid_cid_get(struct cam_tfe_csid_hw *csid_hw, int32_t vc, uint32_t dt, uint32_t *cid) { @@ -249,6 +395,7 @@ static int cam_tfe_csid_global_reset(struct cam_tfe_csid_hw *csid_hw) { struct cam_hw_soc_info *soc_info; const struct cam_tfe_csid_reg_offset *csid_reg; + struct cam_tfe_csid_path_cfg *path_data = NULL; int rc = 0; uint32_t val = 0, i; uint32_t status; @@ -348,6 +495,15 @@ static int cam_tfe_csid_global_reset(struct cam_tfe_csid_hw *csid_hw) csid_hw->error_irq_count = 0; csid_hw->prev_boot_timestamp = 0; + path_data = (struct cam_tfe_csid_path_cfg *)csid_hw->ipp_res.res_priv; + path_data->res_sof_cnt = 0; + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + path_data = (struct cam_tfe_csid_path_cfg *) + csid_hw->rdi_res[i].res_priv; + path_data->res_sof_cnt = 0; + } + return rc; } @@ -675,6 +831,7 @@ static int cam_tfe_csid_path_reserve(struct cam_tfe_csid_hw *csid_hw, path_data->height = reserve->in_port->height; path_data->start_line = reserve->in_port->line_start; path_data->end_line = reserve->in_port->line_end; + path_data->usage_type = reserve->in_port->usage_type; csid_hw->event_cb = reserve->event_cb; csid_hw->event_cb_priv = reserve->event_cb_prv; @@ -868,7 +1025,8 @@ static int cam_tfe_csid_enable_hw(struct cam_tfe_csid_hw *csid_hw) { int rc = 0; const struct cam_tfe_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; + struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data = NULL; uint32_t i, val, clk_lvl; unsigned long flags; @@ -949,6 +1107,16 @@ static int cam_tfe_csid_enable_hw(struct cam_tfe_csid_hw *csid_hw) spin_unlock_irqrestore(&csid_hw->spin_lock, flags); cam_tasklet_start(csid_hw->tasklet); + path_data = (struct cam_tfe_csid_path_cfg *)csid_hw->ipp_res.res_priv; + path_data->res_sof_cnt = 0; + + for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { + path_data = (struct cam_tfe_csid_path_cfg *) + csid_hw->rdi_res[i].res_priv; + path_data->res_sof_cnt = 0; + } + + return rc; disable_soc: @@ -1512,11 +1680,14 @@ static int cam_tfe_csid_enable_rdi_path( { const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data; uint32_t id, val; + bool path_active = false; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; id = res->res_id; + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW || res->res_id > CAM_TFE_CSID_PATH_RES_RDI_2 || @@ -1528,17 +1699,38 @@ static int cam_tfe_csid_enable_rdi_path( return -EINVAL; } - /* resume at frame boundary */ - cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, - soc_info->reg_map[0].mem_base + - csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + /*Drop one frame extra on RDI for dual TFE use case */ + if (path_data->usage_type == CAM_ISP_TFE_IN_RES_USAGE_DUAL) + path_data->init_frame_drop = 1; + + /*resume at frame boundary */ + if (!path_data->init_frame_drop) { + CAM_DBG(CAM_ISP, "Start RDI:%d path", id); + /* resume at frame boundary */ + cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + } else { + path_active = cam_tfe_csid_check_path_active(csid_hw); + if (path_active) + cam_io_w_mb(CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY, + soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + + CAM_DBG(CAM_ISP, + "CSID:%d %s RDI:%d path frame drop %d", + csid_hw->hw_intf->hw_idx, + path_active ? "Starting" : "Not Starting", id, + path_data->init_frame_drop); + } /* Enable the required RDI interrupts */ val = TFE_CSID_PATH_INFO_RST_DONE | TFE_CSID_PATH_ERROR_FIFO_OVERFLOW | TFE_CSID_PATH_RDI_ERROR_CCIF_VIOLATION | TFE_CSID_PATH_RDI_OVERFLOW_IRQ; - if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ) + if ((csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ) || + (path_data->init_frame_drop && !path_active)) val |= TFE_CSID_PATH_INFO_INPUT_SOF; if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ) val |= TFE_CSID_PATH_INFO_INPUT_EOF; @@ -1560,10 +1752,12 @@ static int cam_tfe_csid_disable_rdi_path( uint32_t id, val = 0; const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; id = res->res_id; + path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; if ((res->res_id > CAM_TFE_CSID_PATH_RES_RDI_2) || (!csid_reg->rdi_reg[res->res_id])) { @@ -1599,6 +1793,9 @@ static int cam_tfe_csid_disable_rdi_path( CAM_DBG(CAM_ISP, "CSID:%d res_id:%d", csid_hw->hw_intf->hw_idx, res->res_id); + path_data->init_frame_drop = 0; + path_data->res_sof_cnt = 0; + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); @@ -1964,6 +2161,8 @@ static int cam_tfe_csid_release(void *hw_priv, res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + cam_tfe_csid_reset_path_data(csid_hw, res); + end: mutex_unlock(&csid_hw->hw_info->hw_mutex); return rc; @@ -3276,6 +3475,9 @@ handle_fatal_error: complete(&csid_hw->csid_rdin_complete[i]); } + if (irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) + cam_tfe_csid_enable_path_for_init_frame_drop(csid_hw, i); + if ((irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { if (!csid_hw->sof_irq_triggered) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index 55d71df6fada..b13d4b0473f8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_CSID_HW_H_ @@ -332,7 +332,12 @@ struct cam_tfe_csid_cid_data { * @sensor_fps Sensor fps * @sensor_hbi Sensor horizontal blanking interval * @sensor_vbi Sensor vertical blanking interval - * + * @usage_type: dual or single tfe information + * @init_frame_drop init frame drop value. In dual ife case rdi need to drop one + * more frame than pix. + * @res_sof_cnt path resource sof count value. it used for initial + * frame drop + */ struct cam_tfe_csid_path_cfg { uint32_t vc; @@ -355,6 +360,9 @@ struct cam_tfe_csid_path_cfg { uint32_t sensor_fps; uint32_t sensor_hbi; uint32_t sensor_vbi; + uint32_t usage_type; + uint32_t init_frame_drop; + uint32_t res_sof_cnt; }; /** From 8570262453322571fbe8b26d3a284813735b2ef2 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Mon, 19 Apr 2021 16:38:46 +0530 Subject: [PATCH 04/20] msm: camera: isp: Reset csid error irq count on flush This change is to reset csid_error_irq_count on flush to prevent from recovery. CRs-Fixed: 2926200 Change-Id: I8568fdc679317e41c31f4aeb9cf8c3ae579d8448 Signed-off-by: Ayush Kumar --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 91c9cabf0af4..84c286ba3bfe 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -4232,6 +4232,8 @@ int cam_ife_csid_stop(void *hw_priv, res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW; } + csid_hw->error_irq_count = 0; + CAM_DBG(CAM_ISP, "%s: Exit\n", __func__); return rc; From 72c9ddcce942bf7701b5be6d6d7948d5c6d6b8a3 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 5 Apr 2021 10:21:18 +0530 Subject: [PATCH 05/20] msm: camera: isp: Check ife out res validity This change adds validity check for ife out res. If ife out res is NULL we can run into crash or issues. CRs-Fixed: 2915741 Change-Id: I8722b2a4e2634bda42f0080e00bf09050bbd6b91 Signed-off-by: Vikram Sharma --- .../isp_hw_mgr/hw_utils/cam_isp_packet_parser.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 4147efe58af0..09b0cdb0e881 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -141,6 +141,14 @@ static int cam_isp_update_dual_config( } hw_mgr_res = &res_list_isp_out[i]; + if (!hw_mgr_res) { + CAM_ERR(CAM_ISP, + "Invalid isp out resource i %d num_out_res %d", + i, dual_config->num_ports); + rc = -EINVAL; + goto end; + } + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { if (!hw_mgr_res->hw_res[j]) continue; From dd8b69b832c77733b7ee73c1fde2bb2ab864ea86 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Mon, 26 Apr 2021 13:44:16 +0800 Subject: [PATCH 06/20] msm: camera: isp: Update the reported_req_id correctly The request id is updated to 0 when the substate is BUBBLE, then the original request id can't be notified to UMD, since the reported_req_id is already updated to the original request id. This change updateds the reported_req_id only when the final request id is valid. CRs-Fixed: 2932602 Change-Id: Ib30f849782283c647f784cfb0deb49bee3d04287 Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f7a95795744b..c6b227fdd6d3 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -1863,7 +1863,6 @@ notify_only: if ((!req_isp->bubble_detected) && (req->request_id > ctx_isp->reported_req_id)) { request_id = req->request_id; - ctx_isp->reported_req_id = request_id; __cam_isp_ctx_update_event_record(ctx_isp, CAM_ISP_CTX_EVENT_EPOCH, req); break; @@ -1873,6 +1872,9 @@ notify_only: if (ctx_isp->substate_activated == CAM_ISP_CTX_ACTIVATED_BUBBLE) request_id = 0; + if (request_id != 0) + ctx_isp->reported_req_id = request_id; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); From 6f9f6f4854211a1de0997672d5e961851d6d9d19 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Mon, 26 Apr 2021 15:44:42 +0800 Subject: [PATCH 07/20] msm: camera: reqmgr: Only do self-correction at SOF Since the SOF timestamp is only updated at SOF, so we can't do self-correction at EOF. When the frames already in sync, but the req is a EOF triggered req, then the req can't be applied at SOF, but it will fail to pass self-correction checking at EOF. Then we will loop this progress, the req can't be applied anymore. CRs-Fixed: 2930497 Change-Id: I079cbd3cb9ac9541f049c5369baeee831f7444a2 Signed-off-by: Depeng Shao --- drivers/cam_req_mgr/cam_req_mgr_core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 0bd68d76fa68..c7d6e8252b02 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1339,7 +1339,8 @@ static int __cam_req_mgr_check_sync_for_mslave( static int __cam_req_mgr_check_sync_req_is_ready( struct cam_req_mgr_core_link *link, struct cam_req_mgr_core_link *sync_link, - struct cam_req_mgr_slot *slot) + struct cam_req_mgr_slot *slot, + uint32_t trigger) { struct cam_req_mgr_slot *sync_rd_slot = NULL; int64_t req_id = 0, sync_req_id = 0; @@ -1513,7 +1514,8 @@ static int __cam_req_mgr_check_sync_req_is_ready( */ master_slave_diff = sync_frame_duration; do_div(master_slave_diff, 5); - if ((sync_link->sof_timestamp > 0) && + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (sync_link->sof_timestamp > 0) && (sof_timestamp_delta < master_slave_diff) && (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { @@ -1574,7 +1576,8 @@ static int __cam_req_mgr_check_multi_sync_link_ready( } if (link->max_delay == link->sync_link[i]->max_delay) { rc = __cam_req_mgr_check_sync_req_is_ready( - link, link->sync_link[i], slot); + link, link->sync_link[i], + slot, trigger); if (rc < 0) { CAM_DBG(CAM_CRM, "link %x not ready", link->link_hdl); From c4d768fad0324bee097a2015a72afb24e54ee154 Mon Sep 17 00:00:00 2001 From: Tejas Prajapati Date: Tue, 27 Apr 2021 16:39:24 +0530 Subject: [PATCH 08/20] msm: camera: ife: Program image addr for once in RDI batch mode For RDI only batch mode use case the image address needs to be programmed only once the consecutive image address is taken from the frame increament address and image address we have provided. CRs-Fixed: 2948881 Change-Id: I94bce9522aaace00b567b023bba1cc3443d849ef Signed-off-by: Tejas Prajapati --- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 57 ++++++++----------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 3796f94bfe4d..44de3efdb383 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -2954,9 +2954,8 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; struct cam_vfe_bus_ver3_reg_offset_ubwc_client *ubwc_client = NULL; uint32_t *reg_val_pair; - uint32_t i, j, k, size = 0; + uint32_t i, j, size = 0; uint32_t frame_inc = 0, val; - uint32_t loop_size = 0; bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; @@ -3086,41 +3085,31 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, wm_data->index, reg_val_pair[j-1]); } - if ((!bus_priv->common_data.is_lite && wm_data->index > 22) || - bus_priv->common_data.is_lite) - loop_size = wm_data->irq_subsample_period + 1; - else - loop_size = 1; - /* WM Image address */ - for (k = 0; k < loop_size; k++) { - if (wm_data->en_ubwc) { - CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - wm_data->hw_regs->image_addr, - update_buf->wm_update->image_buf[i] + - io_cfg->planes[i].meta_size + - k * frame_inc); - update_buf->wm_update->image_buf_offset[i] = - io_cfg->planes[i].meta_size; - } else if (wm_data->en_cfg & (0x3 << 16)) { - CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - wm_data->hw_regs->image_addr, - (update_buf->wm_update->image_buf[i] + - wm_data->offset + k * frame_inc)); - update_buf->wm_update->image_buf_offset[i] = - wm_data->offset; - } else { - CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - wm_data->hw_regs->image_addr, - (update_buf->wm_update->image_buf[i] + - k * frame_inc)); - update_buf->wm_update->image_buf_offset[i] = 0; - } - - CAM_DBG(CAM_ISP, "WM:%d image address 0x%X", - wm_data->index, reg_val_pair[j-1]); + if (wm_data->en_ubwc) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + update_buf->wm_update->image_buf[i] + + io_cfg->planes[i].meta_size); + update_buf->wm_update->image_buf_offset[i] = + io_cfg->planes[i].meta_size; + } else if (wm_data->en_cfg & (0x3 << 16)) { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + (update_buf->wm_update->image_buf[i] + + wm_data->offset)); + update_buf->wm_update->image_buf_offset[i] = + wm_data->offset; + } else { + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->image_addr, + update_buf->wm_update->image_buf[i]); + update_buf->wm_update->image_buf_offset[i] = 0; } + CAM_DBG(CAM_ISP, "WM:%d image address 0x%X", + wm_data->index, reg_val_pair[j-1]); + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->frame_incr, frame_inc); CAM_DBG(CAM_ISP, "WM:%d frame_inc %d", From e1f751f7606d52ab176c14529e29ee91c3f8cc1d Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Fri, 30 Apr 2021 16:25:28 +0530 Subject: [PATCH 09/20] msm: camera: ife: Update resource state in tpg start Resource state is not proper during csid stop for PHY TPG hence stop doesn't call for it. Update the correct resource state during tpg start for PHY TPG. CRs-Fixed: 2906168 Change-Id: Ib5fd05a380f6e1dbb303af23b7b0017d9f88c125 Signed-off-by: Alok Chauhan --- .../cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 1445bd098aa2..aa6f9a4c7392 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -1684,6 +1684,8 @@ static int cam_ife_csid_tpg_start(struct cam_ife_csid_hw *csid_hw, CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", 0x600, val); } + res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + return 0; } From f6f57c8d7fa751a3228f99a6608e8fce21754ed1 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Tue, 4 May 2021 14:20:25 +0530 Subject: [PATCH 10/20] msm: camera: cpas: Add support for blair camnoc Blair has different version of CPAS version which requires camnoc interface changes and CPAS version change. This change adds the same. CRs-Fixed: 2944976 Change-Id: I700d99e52dacee9badcb2f66a7a295fb18771231 Signed-off-by: Ayush Kumar --- Makefile | 9 + config/blaircamera.conf | 17 + config/blaircameraconf.h | 10 + drivers/cam_cpas/cpas_top/cam_cpastop_hw.c | 9 +- drivers/cam_cpas/cpas_top/cpastop_v545_110.h | 322 +++++++++++++++++++ drivers/cam_cpas/include/cam_cpas_api.h | 3 +- 6 files changed, 367 insertions(+), 3 deletions(-) create mode 100644 config/blaircamera.conf create mode 100644 config/blaircameraconf.h create mode 100644 drivers/cam_cpas/cpas_top/cpastop_v545_110.h diff --git a/Makefile b/Makefile index 44714b7440f5..ecbee305dbf2 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,10 @@ ifeq ($(CONFIG_ARCH_HOLI), y) include $(srctree)/techpack/camera/config/holicamera.conf endif +ifeq ($(CONFIG_ARCH_BLAIR), y) +include $(srctree)/techpack/camera/config/blaircamera.conf +endif + ifeq ($(CONFIG_ARCH_SHIMA), y) include $(srctree)/techpack/camera/config/shimacamera.conf endif @@ -55,6 +59,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/holicameraconf.h endif +ifeq ($(CONFIG_ARCH_BLAIR), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/blaircameraconf.h +endif + ifeq ($(CONFIG_ARCH_SHIMA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/shimacameraconf.h diff --git a/config/blaircamera.conf b/config/blaircamera.conf new file mode 100644 index 000000000000..be2ce67888d1 --- /dev/null +++ b/config/blaircamera.conf @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2021, The Linux Foundation. All rights reserved. + +ifeq ($(CONFIG_QGKI),y) +export CONFIG_SPECTRA_CAMERA=y +$(info "SPECTRA_CAMERA IS STATIC") +else +$(info "SPECTRA_CAMERA IS MODULAR") +export CONFIG_SPECTRA_CAMERA=m +endif + +ifneq (,$(filter $(CONFIG_SPECTRA_CAMERA), y m)) +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_OPE=y +export CONFIG_SPECTRA_TFE=y +export CONFIG_SPECTRA_SENSOR=y +endif diff --git a/config/blaircameraconf.h b/config/blaircameraconf.h new file mode 100644 index 000000000000..816797dee642 --- /dev/null +++ b/config/blaircameraconf.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_OPE 1 +#define CONFIG_SPECTRA_TFE 1 +#define CONFIG_SPECTRA_SENSOR 1 diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 6447b3b40dc3..01a376dd51c1 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -28,6 +28,7 @@ #include "cpastop_v540_100.h" #include "cpastop_v520_100.h" #include "cpastop_v545_100.h" +#include "cpastop_v545_110.h" #include "cpastop_v570_200.h" #include "cpastop_v680_100.h" #include "cpastop_v165_100.h" @@ -119,7 +120,7 @@ static const uint32_t cam_cpas_hw_version_map { CAM_CPAS_TITAN_545_V100, 0, - 0, + CAM_CPAS_TITAN_545_V110, 0, 0, 0, @@ -934,6 +935,10 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, camnoc_info = &cam545_cpas100_camnoc_info; qchannel_info = &cam545_cpas100_qchannel_info; break; + case CAM_CPAS_TITAN_545_V110: + camnoc_info = &cam545_cpas110_camnoc_info; + qchannel_info = &cam545_cpas110_qchannel_info; + break; case CAM_CPAS_TITAN_570_V200: camnoc_info = &cam570_cpas200_camnoc_info; qchannel_info = &cam570_cpas200_qchannel_info; diff --git a/drivers/cam_cpas/cpas_top/cpastop_v545_110.h b/drivers/cam_cpas/cpas_top/cpastop_v545_110.h new file mode 100644 index 000000000000..d8833047c250 --- /dev/null +++ b/drivers/cam_cpas/cpas_top/cpastop_v545_110.h @@ -0,0 +1,322 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V545_110_H_ +#define _CPASTOP_V545_110_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v545_110_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA40, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + (TEST_IRQ_ENABLE ? + 0x2 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0) /* SBM_FAULTINEN0_LOW_PORT1_MASK */, + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA48, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xA80, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x3 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v545_110_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = true, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xD08, /* ERRORLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xD10, /* ERRORLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xD18, /* ERRORLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA88, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA90, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + + +static struct cam_camnoc_specific + cam_cpas_v545_110_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE38, /* CDM_URGENCY_LOW */ + .value = 0x00000003, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x30, + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x34, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x40, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x48, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x4030, + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x4034, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4038, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x4040, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x4048, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + }, + { + .port_type = CAM_CAMNOC_TFE_2, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x5030, + .value = 0x55554433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x5034, + .value = 0x66666655, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5038, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5040, /* TFE_DANGERLUT_LOW */ + .value = 0xffff0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5048, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + }, + { + .port_type = CAM_CAMNOC_OPE, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x438, /* OPE_URGENCY_LOW */ + .value = 0x00000033, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* OPE_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* OPE_SAFELUT_LOW */ + .value = 0xF, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam545_cpas110_err_logger_offsets = { + .mainctrl = 0xD08, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0xD10, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0xD20, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0xD24, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0xD28, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0xD2C, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0xD30, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0xD34, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0xD38, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0xD3C, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_camnoc_info cam545_cpas110_camnoc_info = { + .specific = &cam_cpas_v545_110_camnoc_specific[0], + .specific_size = ARRAY_SIZE(cam_cpas_v545_110_camnoc_specific), + .irq_sbm = &cam_cpas_v545_110_irq_sbm, + .irq_err = &cam_cpas_v545_110_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v545_110_irq_err), + .err_logger = &cam545_cpas110_err_logger_offsets, + .errata_wa_list = NULL, +}; + +static struct cam_cpas_camnoc_qchannel cam545_cpas110_qchannel_info = { + .qchannel_ctrl = 0x14, + .qchannel_status = 0x18, +}; +#endif /* _CPASTOP_V545_110_H_ */ diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 2b82d1f283e4..87fe72a42a64 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_API_H_ @@ -139,6 +139,7 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_540_V100 = 0x540100, CAM_CPAS_TITAN_520_V100 = 0x520100, CAM_CPAS_TITAN_545_V100 = 0x545100, + CAM_CPAS_TITAN_545_V110 = 0x545110, CAM_CPAS_TITAN_570_V200 = 0x570200, CAM_CPAS_TITAN_680_V100 = 0x680100, CAM_CPAS_TITAN_MAX From 9f18463541eee28977c4e8639fa13ae78ed37f38 Mon Sep 17 00:00:00 2001 From: Sridhar Gujje Date: Sun, 9 May 2021 02:16:46 +0530 Subject: [PATCH 11/20] Revert "Revert "msm: camera: req_mgr: Enhance camera v4l2 subdev shutdown sequence"" This reverts commit 4a487d963840940caf55c9de4026573bf0768eed. Change-Id: I9d052d9260581ed8155d3fbd3e5eff3a81247306 Signed-off-by: Sridhar Gujje --- drivers/cam_core/cam_context.c | 27 +++++++- drivers/cam_core/cam_context.h | 19 ++++- drivers/cam_core/cam_node.c | 23 ++++++- drivers/cam_core/cam_node.h | 26 +++++++ drivers/cam_core/cam_subdev.c | 15 ++++ drivers/cam_cpas/cam_cpas_intf.c | 24 ++++++- drivers/cam_cust/cam_custom_context.c | 18 +++++ drivers/cam_cust/cam_custom_context.h | 12 ++++ drivers/cam_cust/cam_custom_dev.c | 16 ++++- drivers/cam_fd/cam_fd_context.c | 26 ++++++- drivers/cam_fd/cam_fd_context.h | 11 +++ drivers/cam_fd/cam_fd_dev.c | 21 +++++- drivers/cam_icp/cam_icp_context.c | 19 ++++- drivers/cam_icp/cam_icp_context.h | 8 +++ drivers/cam_icp/cam_icp_subdev.c | 23 +++++-- drivers/cam_isp/cam_isp_context.c | 11 +++ drivers/cam_isp/cam_isp_context.h | 11 +++ drivers/cam_isp/cam_isp_dev.c | 15 +++- drivers/cam_jpeg/cam_jpeg_context.c | 26 +++++++ drivers/cam_jpeg/cam_jpeg_context.h | 12 ++++ drivers/cam_jpeg/cam_jpeg_dev.c | 16 ++++- drivers/cam_lrme/cam_lrme_context.c | 19 ++++- drivers/cam_lrme/cam_lrme_context.h | 12 ++++ drivers/cam_lrme/cam_lrme_dev.c | 15 +++- drivers/cam_ope/cam_ope_context.c | 19 ++++- drivers/cam_ope/cam_ope_context.h | 8 +++ drivers/cam_ope/cam_ope_subdev.c | 16 ++++- drivers/cam_req_mgr/cam_req_mgr_dev.c | 66 +++++++++++++++++- drivers/cam_req_mgr/cam_req_mgr_dev.h | 6 ++ drivers/cam_req_mgr/cam_req_mgr_util.c | 31 +++++++++ drivers/cam_req_mgr/cam_req_mgr_util.h | 7 ++ drivers/cam_req_mgr/cam_subdev.h | 27 ++++++++ .../cam_actuator/cam_actuator_dev.c | 63 ++++++++++++----- .../cam_csiphy/cam_csiphy_dev.c | 69 ++++++++++++------- .../cam_eeprom/cam_eeprom_dev.c | 66 ++++++++++++------ .../cam_flash/cam_flash_dev.c | 58 +++++++++++----- .../cam_sensor_module/cam_ois/cam_ois_dev.c | 67 +++++++++++------- .../cam_sensor/cam_sensor_dev.c | 69 ++++++++++++------- 38 files changed, 843 insertions(+), 154 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 9637a8715af6..a9a635d606f9 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -583,6 +583,31 @@ int cam_context_handle_stop_dev(struct cam_context *ctx, return rc; } +int cam_context_handle_shutdown_dev(struct cam_context *ctx, + struct cam_control *cmd, struct v4l2_subdev_fh *fh) +{ + int rc = 0; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid stop device command payload"); + return -EINVAL; + } + + if (ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev) + rc = ctx->state_machine[ctx->state].ioctl_ops.shutdown_dev( + (struct v4l2_subdev *)cmd->handle, fh); + else + CAM_WARN(CAM_CORE, "No shutdown device in dev %d, state %d", + ctx->dev_hdl, ctx->state); + + return rc; +} + int cam_context_handle_info_dump(void *context, enum cam_context_dump_id id) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 5be078536ff5..e55da3c3c4e7 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CONTEXT_H_ @@ -9,6 +9,7 @@ #include #include #include +#include #include "cam_req_mgr_interface.h" #include "cam_hw_mgr_intf.h" #include "cam_smmu_api.h" @@ -95,6 +96,7 @@ struct cam_ctx_request { * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * @dump_dev: Function pointer for dump dev + * @shutdown_dev: Function pointer for shutdown dev * */ struct cam_ctx_ioctl_ops { @@ -114,6 +116,8 @@ struct cam_ctx_ioctl_ops { int (*release_hw)(struct cam_context *ctx, void *args); int (*dump_dev)(struct cam_context *ctx, struct cam_dump_req_cmd *cmd); + int (*shutdown_dev)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); }; /** @@ -479,6 +483,19 @@ int cam_context_handle_start_dev(struct cam_context *ctx, int cam_context_handle_stop_dev(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +/** + * cam_context_handle_shutdown_dev() + * + * @brief: Handle shutdown device command + * + * @ctx: Object pointer for cam_context + * @cmd: Shutdown device command payload + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_context_handle_shutdown_dev(struct cam_context *ctx, + struct cam_control *cmd, struct v4l2_subdev_fh *fh); + /** * cam_context_handle_dump_dev() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index c3770f2df745..d27bcdd6bf0d 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -297,6 +297,27 @@ static int __cam_node_handle_stop_dev(struct cam_node *node, return rc; } +int cam_node_handle_shutdown_dev(struct cam_node *node, + struct cam_control *cmd, struct v4l2_subdev_fh *fh) +{ + struct cam_context *ctx = NULL; + int32_t dev_index = -1; + int rc = 0, ret = 0; + + while ((dev_index = cam_get_dev_handle_info(cmd->handle, + &ctx, dev_index)) < CAM_REQ_MGR_MAX_HANDLES_V2) { + ret = cam_context_handle_shutdown_dev(ctx, cmd, fh); + if (ret) { + rc = ret; + CAM_ERR(CAM_CORE, "Shutdown failure for node %s", + node->name); + continue; + } + } + + return rc; +} + static int __cam_node_handle_config_dev(struct cam_node *node, struct cam_config_dev_cmd *config) { diff --git a/drivers/cam_core/cam_node.h b/drivers/cam_core/cam_node.h index 640798b387d6..81503f28974f 100644 --- a/drivers/cam_core/cam_node.h +++ b/drivers/cam_core/cam_node.h @@ -100,4 +100,30 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, */ void cam_node_put_ctxt_to_free_list(struct kref *ref); +/** + * cam_get_dev_handle_info() + * + * @brief: provides the active dev index. + * + * @handle: pointer to struct v4l2_dev + * @ctx: pointer to struct cam_context + * @dev_index: dev index + * + */ +int32_t cam_get_dev_handle_info(uint64_t handle, + struct cam_context **ctx, int32_t dev_index); + +/** + * cam_node_handle_shutdown_dev() + * + * @brief: Shutdowns all the active devices. + * + * @node: pointer to struct node + * @cmd: pointer to struct cmd + * @fh: pointer to struct v4l2_subdev_fh + * + */ +int cam_node_handle_shutdown_dev(struct cam_node *node, + struct cam_control *cmd, struct v4l2_subdev_fh *fh); + #endif /* _CAM_NODE_H_ */ diff --git a/drivers/cam_core/cam_subdev.c b/drivers/cam_core/cam_subdev.c index 52612951dca7..cbe1b4ca3336 100644 --- a/drivers/cam_core/cam_subdev.c +++ b/drivers/cam_core/cam_subdev.c @@ -45,6 +45,8 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, long rc; struct cam_node *node = (struct cam_node *) v4l2_get_subdevdata(sd); + struct v4l2_subdev_fh *fh = (struct v4l2_subdev_fh *)arg; + struct cam_control cntrl_cmd; if (!node || node->state == CAM_NODE_STATE_UNINIT) { rc = -EINVAL; @@ -56,6 +58,19 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, rc = cam_node_handle_ioctl(node, (struct cam_control *) arg); break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_WARN(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + cntrl_cmd.op_code = CAM_SD_SHUTDOWN; + cntrl_cmd.handle = (uint64_t)sd; + rc = cam_node_handle_shutdown_dev(node, &cntrl_cmd, fh); + if (rc) + CAM_ERR(CAM_CORE, "shutdown device failed(rc = %d)", + rc); + break; default: CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd, node->name); diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index f5bb5db85c29..3c8f5dc166e2 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -691,7 +691,7 @@ static int cam_cpas_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_cpas_subdev_close(struct v4l2_subdev *sd, +static int __cam_cpas_subdev_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd); @@ -702,6 +702,11 @@ static int cam_cpas_subdev_close(struct v4l2_subdev *sd, } mutex_lock(&cpas_intf->intf_lock); + if (cpas_intf->open_cnt <= 0) { + CAM_WARN(CAM_CPAS, "device already closed, open_cnt: %d", cpas_intf->open_cnt); + mutex_unlock(&cpas_intf->intf_lock); + return 0; + } cpas_intf->open_cnt--; CAM_DBG(CAM_CPAS, "CPAS Subdev close count %d", cpas_intf->open_cnt); mutex_unlock(&cpas_intf->intf_lock); @@ -709,6 +714,19 @@ static int cam_cpas_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_cpas_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CPAS); + + if (crm_active) { + CAM_DBG(CAM_CPAS, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return __cam_cpas_subdev_close(sd, fh); +} + static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -724,6 +742,9 @@ static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd, case VIDIOC_CAM_CONTROL: rc = cam_cpas_subdev_cmd(cpas_intf, (struct cam_control *) arg); break; + case CAM_SD_SHUTDOWN: + rc = __cam_cpas_subdev_close(sd, NULL); + break; default: CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd); rc = -EINVAL; @@ -811,6 +832,7 @@ static int cam_cpas_subdev_register(struct platform_device *pdev) subdev->sd_flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; subdev->ent_function = CAM_CPAS_DEVICE_TYPE; + subdev->close_seq_prior = CAM_SD_CLOSE_LOW_PRIORITY; rc = cam_register_subdev(subdev); if (rc) { diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index ca4d1d1e35d5..2b617b15f5a0 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -1604,6 +1604,19 @@ static int __cam_custom_ctx_apply_default_req( return rc; } +static int __cam_custom_ctx_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + int rc = -EINVAL; + + if (!sd || !fh) { + CAM_ERR(CAM_CUSTOM, "Invalid input pointer"); + return rc; + } + + return cam_custom_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -1618,6 +1631,7 @@ static struct cam_ctx_ops .ioctl_ops = { .acquire_dev = __cam_custom_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -1629,6 +1643,7 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev_in_acquired, .release_hw = __cam_custom_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .link = __cam_custom_ctx_link_in_acquired, @@ -1647,6 +1662,7 @@ static struct cam_ctx_ops .release_dev = __cam_custom_release_dev_in_acquired, .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1664,6 +1680,7 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev_in_flushed, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, @@ -1680,6 +1697,7 @@ static struct cam_ctx_ops .config_dev = __cam_custom_ctx_config_dev, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, + .shutdown_dev = __cam_custom_ctx_shutdown_dev, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index ef7fe1f87434..74c45d541610 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -150,4 +150,16 @@ int cam_custom_dev_context_init(struct cam_custom_context *ctx, */ int cam_custom_dev_context_deinit(struct cam_custom_context *ctx); +/** + * cam_custom_subdev_close_internal() + * + * @brief: Close function for the Custom context + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_CUSTOM_CONTEXT_H_ */ diff --git a/drivers/cam_cust/cam_custom_dev.c b/drivers/cam_cust/cam_custom_dev.c index 3c3bea4c22c0..36dde62fc51d 100644 --- a/drivers/cam_cust/cam_custom_dev.c +++ b/drivers/cam_cust/cam_custom_dev.c @@ -58,7 +58,7 @@ static int cam_custom_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_custom_subdev_close(struct v4l2_subdev *sd, +int cam_custom_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -86,6 +86,19 @@ end: return rc; } +static int cam_custom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CUSTOM); + + if (crm_active) { + CAM_DBG(CAM_CUSTOM, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_custom_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_custom_subdev_internal_ops = { .close = cam_custom_subdev_close, .open = cam_custom_subdev_open, @@ -102,6 +115,7 @@ static int cam_custom_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops; + g_custom_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; rc = cam_subdev_probe(&g_custom_dev.sd, pdev, CAM_CUSTOM_DEV_NAME, CAM_CUSTOM_DEVICE_TYPE); diff --git a/drivers/cam_fd/cam_fd_context.c b/drivers/cam_fd/cam_fd_context.c index c79f2f90e007..0f3fa85f079e 100644 --- a/drivers/cam_fd/cam_fd_context.c +++ b/drivers/cam_fd/cam_fd_context.c @@ -169,6 +169,19 @@ static int __cam_fd_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_fd_shutdown_dev(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + int rc = -EINVAL; + + if (!sd || !fh) { + CAM_ERR(CAM_FD, "Invalid input pointer"); + return rc; + } + + return cam_fd_dev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_fd_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -182,6 +195,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_fd_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -192,18 +206,25 @@ static struct cam_ctx_ops .release_dev = __cam_fd_ctx_release_dev_in_acquired, .config_dev = __cam_fd_ctx_config_dev_in_acquired, .start_dev = __cam_fd_ctx_start_dev_in_acquired, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = { }, + .ioctl_ops = { + .shutdown_dev = __cam_fd_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_fd_shutdown_dev, + }, + }, /* Activated */ { .ioctl_ops = { @@ -212,6 +233,7 @@ static struct cam_ctx_ops .config_dev = __cam_fd_ctx_config_dev_in_activated, .flush_dev = __cam_fd_ctx_flush_dev_in_activated, .dump_dev = __cam_fd_ctx_dump_dev_in_activated, + .shutdown_dev = __cam_fd_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_fd_ctx_handle_irq_in_activated, diff --git a/drivers/cam_fd/cam_fd_context.h b/drivers/cam_fd/cam_fd_context.h index a751a04d2d67..615e8d94cf6e 100644 --- a/drivers/cam_fd/cam_fd_context.h +++ b/drivers/cam_fd/cam_fd_context.h @@ -27,4 +27,15 @@ int cam_fd_context_init(struct cam_fd_context *fd_ctx, uint32_t ctx_id); int cam_fd_context_deinit(struct cam_fd_context *ctx); +/** + * cam_fd_dev_close_internal() + * + * @brief: Close function for the fd dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_fd_dev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_FD_CONTEXT_H_ */ diff --git a/drivers/cam_fd/cam_fd_dev.c b/drivers/cam_fd/cam_fd_dev.c index bc1864edb24e..a58db056f6fb 100644 --- a/drivers/cam_fd/cam_fd_dev.c +++ b/drivers/cam_fd/cam_fd_dev.c @@ -57,7 +57,7 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_fd_dev_close(struct v4l2_subdev *sd, +static int cam_fd_dev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_fd_dev *fd_dev = &g_fd_dev; @@ -69,6 +69,11 @@ static int cam_fd_dev_close(struct v4l2_subdev *sd, } mutex_lock(&fd_dev->lock); + if (fd_dev->open_cnt == 0) { + CAM_WARN(CAM_FD, "device already closed"); + mutex_unlock(&fd_dev->lock); + return 0; + } fd_dev->open_cnt--; CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); mutex_unlock(&fd_dev->lock); @@ -83,6 +88,19 @@ static int cam_fd_dev_close(struct v4l2_subdev *sd, return 0; } +static int cam_fd_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_FD); + + if (crm_active) { + CAM_DBG(CAM_FD, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_fd_dev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_fd_subdev_internal_ops = { .open = cam_fd_dev_open, .close = cam_fd_dev_close, @@ -98,6 +116,7 @@ static int cam_fd_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_fd_dev.sd.internal_ops = &cam_fd_subdev_internal_ops; + g_fd_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ rc = cam_subdev_probe(&g_fd_dev.sd, pdev, CAM_FD_DEV_NAME, diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 57a80bcd7341..03ead2c3b693 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -221,6 +221,12 @@ static int __cam_icp_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } +static int __cam_icp_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_icp_subdev_close_internal(sd, fh); +} + static struct cam_ctx_ops cam_icp_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -233,6 +239,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_icp_acquire_dev_in_available, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -245,6 +252,7 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, @@ -258,16 +266,23 @@ static struct cam_ctx_ops .config_dev = __cam_icp_config_dev_in_ready, .flush_dev = __cam_icp_flush_dev_in_ready, .dump_dev = __cam_icp_dump_dev_in_ready, + .shutdown_dev = __cam_icp_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_icp_handle_buf_done_in_ready, .pagefault_ops = cam_icp_context_dump_active_request, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_icp_shutdown_dev, + }, + }, /* Activated */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_icp_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_icp_context_dump_active_request, diff --git a/drivers/cam_icp/cam_icp_context.h b/drivers/cam_icp/cam_icp_context.h index dc9018d1c229..9150bcf43f62 100644 --- a/drivers/cam_icp/cam_icp_context.h +++ b/drivers/cam_icp/cam_icp_context.h @@ -39,4 +39,12 @@ int cam_icp_context_init(struct cam_icp_context *ctx, */ int cam_icp_context_deinit(struct cam_icp_context *ctx); +/** + * cam_icp_subdev_close_internal() - Close function for the icp dev + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_ICP_CONTEXT_H_ */ diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 6a12cdd3e2fc..3288964444ef 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -98,7 +98,7 @@ end: return rc; } -static int cam_icp_subdev_close(struct v4l2_subdev *sd, +int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -107,9 +107,8 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt <= 0) { - CAM_DBG(CAM_ICP, "ICP subdev is already closed"); - rc = -EINVAL; - goto end; + CAM_WARN(CAM_ICP, "ICP subdev is already closed"); + return 0; } g_icp_dev.open_cnt--; if (!node) { @@ -133,7 +132,20 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd, end: mutex_unlock(&g_icp_dev.icp_lock); - return 0; + return rc; +} + +static int cam_icp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ICP); + + if (crm_active) { + CAM_DBG(CAM_ICP, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_icp_subdev_close_internal(sd, fh); } const struct v4l2_subdev_internal_ops cam_icp_subdev_internal_ops = { @@ -157,6 +169,7 @@ static int cam_icp_component_bind(struct device *dev, g_icp_dev.sd.pdev = pdev; g_icp_dev.sd.internal_ops = &cam_icp_subdev_internal_ops; + g_icp_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_icp_dev.sd, pdev, CAM_ICP_DEV_NAME, CAM_ICP_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f7a95795744b..d7cdaa4aa67e 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -5837,6 +5837,12 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_isp_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_isp_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_isp_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -5850,6 +5856,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_isp_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -5861,6 +5868,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_acquired, .release_hw = __cam_isp_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .link = __cam_isp_ctx_link_in_acquired, @@ -5880,6 +5888,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_top_state, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -5897,6 +5906,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_flushed, .release_hw = __cam_isp_ctx_release_hw_in_activated, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, @@ -5914,6 +5924,7 @@ static struct cam_ctx_ops .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_activated, + .shutdown_dev = __cam_isp_shutdown_dev, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_activated, diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index c0861f07964e..108dc096d897 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -364,5 +364,16 @@ int cam_isp_context_init(struct cam_isp_context *ctx, */ int cam_isp_context_deinit(struct cam_isp_context *ctx); +/** + * cam_isp_subdev_close_internal() + * + * @brief: Close function for the isp dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); #endif /* __CAM_ISP_CONTEXT_H__ */ diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 98de92cb3d58..9409c1015c6c 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -71,7 +71,7 @@ static int cam_isp_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_isp_subdev_close(struct v4l2_subdev *sd, +int cam_isp_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -99,6 +99,18 @@ end: return rc; } +static int cam_isp_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ISP); + + if (crm_active) { + CAM_DBG(CAM_ISP, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_isp_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = { .close = cam_isp_subdev_close, .open = cam_isp_subdev_open, @@ -120,6 +132,7 @@ static int cam_isp_dev_component_bind(struct device *dev, (const char **)&compat_str); g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops; + g_isp_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY; /* Initialize the v4l2 subdevice first. (create cam_node) */ if (strnstr(compat_str, "ife", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, diff --git a/drivers/cam_jpeg/cam_jpeg_context.c b/drivers/cam_jpeg/cam_jpeg_context.c index 93d4ade12c42..20dd4a02127b 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.c +++ b/drivers/cam_jpeg/cam_jpeg_context.c @@ -135,6 +135,12 @@ static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_jpeg_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_jpeg_subdev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -148,6 +154,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_jpeg_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = NULL, @@ -160,11 +167,30 @@ static struct cam_ctx_ops .stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired, .flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired, .dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired, + .shutdown_dev = __cam_jpeg_shutdown_dev, }, .crm_ops = { }, .irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired, .pagefault_ops = cam_jpeg_context_dump_active_request, }, + /* Ready */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, + /* Flushed */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, + /* Activated */ + { + .ioctl_ops = { + .shutdown_dev = __cam_jpeg_shutdown_dev, + }, + }, }; int cam_jpeg_context_init(struct cam_jpeg_context *ctx, diff --git a/drivers/cam_jpeg/cam_jpeg_context.h b/drivers/cam_jpeg/cam_jpeg_context.h index 85394047d97f..f8a8b06d09f0 100644 --- a/drivers/cam_jpeg/cam_jpeg_context.h +++ b/drivers/cam_jpeg/cam_jpeg_context.h @@ -64,4 +64,16 @@ int cam_jpeg_context_init(struct cam_jpeg_context *ctx, */ int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx); +/** + * cam_jpeg_subdev_close_internal() + * + * @brief: Close function for the jpeg dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* __CAM_JPEG_CONTEXT_H__ */ diff --git a/drivers/cam_jpeg/cam_jpeg_dev.c b/drivers/cam_jpeg/cam_jpeg_dev.c index 966bbb1fab06..a47476a06144 100644 --- a/drivers/cam_jpeg/cam_jpeg_dev.c +++ b/drivers/cam_jpeg/cam_jpeg_dev.c @@ -56,13 +56,12 @@ static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, return 0; } -static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, +int cam_jpeg_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; struct cam_node *node = v4l2_get_subdevdata(sd); - mutex_lock(&g_jpeg_dev.jpeg_mutex); if (g_jpeg_dev.open_cnt <= 0) { CAM_DBG(CAM_JPEG, "JPEG subdev is already closed"); @@ -86,6 +85,18 @@ end: return rc; } +static int cam_jpeg_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_JPEG); + + if (crm_active) { + CAM_DBG(CAM_JPEG, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_jpeg_subdev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = { .close = cam_jpeg_subdev_close, .open = cam_jpeg_subdev_open, @@ -102,6 +113,7 @@ static int cam_jpeg_dev_component_bind(struct device *dev, struct platform_device *pdev = to_platform_device(dev); g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops; + g_jpeg_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME, CAM_JPEG_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_lrme/cam_lrme_context.c b/drivers/cam_lrme/cam_lrme_context.c index 537432f982bf..7025b384b1d2 100644 --- a/drivers/cam_lrme/cam_lrme_context.c +++ b/drivers/cam_lrme/cam_lrme_context.c @@ -172,6 +172,12 @@ static int __cam_lrme_ctx_handle_irq_in_activated(void *context, return rc; } +static int __cam_lrme_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_lrme_dev_close_internal(sd, fh); +} + /* top state machine */ static struct cam_ctx_ops cam_lrme_ctx_state_machine[CAM_CTX_STATE_MAX] = { @@ -185,6 +191,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_lrme_ctx_acquire_dev_in_available, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -195,18 +202,25 @@ static struct cam_ctx_ops .config_dev = __cam_lrme_ctx_config_dev_in_activated, .release_dev = __cam_lrme_ctx_release_dev_in_acquired, .start_dev = __cam_lrme_ctx_start_dev_in_acquired, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, }, /* Ready */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_lrme_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, }, /* Flushed */ - {}, + { + .ioctl_ops = { + .shutdown_dev = __cam_lrme_shutdown_dev, + }, + }, /* Activate */ { .ioctl_ops = { @@ -215,6 +229,7 @@ static struct cam_ctx_ops .stop_dev = __cam_lrme_ctx_stop_dev_in_activated, .flush_dev = __cam_lrme_ctx_flush_dev_in_activated, .dump_dev = __cam_lrme_ctx_dump_dev_in_activated, + .shutdown_dev = __cam_lrme_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_lrme_ctx_handle_irq_in_activated, diff --git a/drivers/cam_lrme/cam_lrme_context.h b/drivers/cam_lrme/cam_lrme_context.h index bc459cce2f95..34ed1693f944 100644 --- a/drivers/cam_lrme/cam_lrme_context.h +++ b/drivers/cam_lrme/cam_lrme_context.h @@ -30,4 +30,16 @@ int cam_lrme_context_init(struct cam_lrme_context *lrme_ctx, uint32_t index); int cam_lrme_context_deinit(struct cam_lrme_context *lrme_ctx); +/** + * cam_lrme_dev_close_internal() + * + * @brief: Close function for the jpeg dev + * + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + * + */ +int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_LRME_CONTEXT_H_ */ diff --git a/drivers/cam_lrme/cam_lrme_dev.c b/drivers/cam_lrme/cam_lrme_dev.c index 3735ff9370a2..5055444c3d8a 100644 --- a/drivers/cam_lrme/cam_lrme_dev.c +++ b/drivers/cam_lrme/cam_lrme_dev.c @@ -72,7 +72,7 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd, return 0; } -static int cam_lrme_dev_close(struct v4l2_subdev *sd, +int cam_lrme_dev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -106,6 +106,18 @@ end: return rc; } +static int cam_lrme_dev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_LRME); + + if (crm_active) { + CAM_DBG(CAM_LRME, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + return cam_lrme_dev_close_internal(sd, fh); +} + static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = { .open = cam_lrme_dev_open, .close = cam_lrme_dev_close, @@ -126,6 +138,7 @@ static int cam_lrme_component_bind(struct device *dev, return -ENOMEM; } g_lrme_dev->sd.internal_ops = &cam_lrme_subdev_internal_ops; + g_lrme_dev->sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; mutex_init(&g_lrme_dev->lock); diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index d1f39e8fce17..c8be0da353d4 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -195,6 +195,12 @@ static int __cam_ope_handle_buf_done_in_ready(void *ctx, return cam_context_buf_done_from_hw(ctx, done, evt_id); } +static int __cam_ope_shutdown_dev( + struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + return cam_ope_subdev_close_internal(sd, fh); +} + static struct cam_ctx_ops cam_ope_ctx_state_machine[CAM_CTX_STATE_MAX] = { /* Uninit */ @@ -207,6 +213,7 @@ static struct cam_ctx_ops { .ioctl_ops = { .acquire_dev = __cam_ope_acquire_dev_in_available, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = NULL, @@ -219,6 +226,7 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, @@ -232,14 +240,23 @@ static struct cam_ctx_ops .config_dev = __cam_ope_config_dev_in_ready, .flush_dev = __cam_ope_flush_dev_in_ready, .dump_dev = __cam_ope_dump_dev_in_ready, + .shutdown_dev = __cam_ope_shutdown_dev, }, .crm_ops = {}, .irq_ops = __cam_ope_handle_buf_done_in_ready, .pagefault_ops = cam_ope_context_dump_active_request, }, + /* Flushed */ + { + .ioctl_ops = { + .shutdown_dev = __cam_ope_shutdown_dev, + }, + }, /* Activated */ { - .ioctl_ops = {}, + .ioctl_ops = { + .shutdown_dev = __cam_ope_shutdown_dev, + }, .crm_ops = {}, .irq_ops = NULL, .pagefault_ops = cam_ope_context_dump_active_request, diff --git a/drivers/cam_ope/cam_ope_context.h b/drivers/cam_ope/cam_ope_context.h index e79e0f33225d..5e6d28c3ff59 100644 --- a/drivers/cam_ope/cam_ope_context.h +++ b/drivers/cam_ope/cam_ope_context.h @@ -41,4 +41,12 @@ int cam_ope_context_init(struct cam_ope_context *ctx, */ int cam_ope_context_deinit(struct cam_ope_context *ctx); +/** + * cam_ope_subdev_close_internal() - Close function for the icp dev + * @sd: Pointer to struct v4l2_subdev + * @fh: Pointer to struct v4l2_subdev_fh + */ +int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh); + #endif /* _CAM_OPE_CONTEXT_H_ */ diff --git a/drivers/cam_ope/cam_ope_subdev.c b/drivers/cam_ope/cam_ope_subdev.c index edfdd1e75e77..a04abe3bcf8c 100644 --- a/drivers/cam_ope/cam_ope_subdev.c +++ b/drivers/cam_ope/cam_ope_subdev.c @@ -95,7 +95,7 @@ end: return rc; } -static int cam_ope_subdev_close(struct v4l2_subdev *sd, +int cam_ope_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc = 0; @@ -134,6 +134,19 @@ end: return rc; } +static int cam_ope_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_OPE); + + if (crm_active) { + CAM_DBG(CAM_OPE, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_ope_subdev_close_internal(sd, fh); +} + const struct v4l2_subdev_internal_ops cam_ope_subdev_internal_ops = { .open = cam_ope_subdev_open, .close = cam_ope_subdev_close, @@ -156,6 +169,7 @@ static int cam_ope_subdev_component_bind(struct device *dev, g_ope_dev.sd.pdev = pdev; g_ope_dev.sd.internal_ops = &cam_ope_subdev_internal_ops; + g_ope_dev.sd.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_subdev_probe(&g_ope_dev.sd, pdev, OPE_DEV_NAME, CAM_OPE_DEVICE_TYPE); if (rc) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 6ae85e826c5e..350c9ea171bf 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "cam_req_mgr_dev.h" #include "cam_req_mgr_util.h" @@ -32,6 +33,7 @@ static struct cam_req_mgr_device g_dev; struct kmem_cache *g_cam_req_mgr_timer_cachep; +static struct list_head cam_req_mgr_ordered_sd_list; static struct device_attribute camera_debug_sysfs_attr = __ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store); @@ -122,6 +124,7 @@ static int cam_req_mgr_open(struct file *filep) spin_unlock_bh(&g_dev.cam_eventq_lock); g_dev.open_cnt++; + g_dev.read_active_dev_id_hdls = 0; rc = cam_mem_mgr_init(); if (rc) { g_dev.open_cnt--; @@ -158,6 +161,7 @@ static unsigned int cam_req_mgr_poll(struct file *f, static int cam_req_mgr_close(struct file *filep) { struct v4l2_subdev *sd; + struct cam_subdev *csd; struct v4l2_fh *vfh = filep->private_data; struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); @@ -172,18 +176,23 @@ static int cam_req_mgr_close(struct file *filep) } cam_req_mgr_handle_core_shutdown(); + g_dev.shutdown_state = true; - list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + list_for_each_entry(csd, &cam_req_mgr_ordered_sd_list, list) { + sd = &csd->sd; if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) continue; - if (sd->internal_ops && sd->internal_ops->close) { + if (sd->internal_ops) { CAM_DBG(CAM_CRM, "Invoke subdev close for device %s", sd->name); - sd->internal_ops->close(sd, subdev_fh); + v4l2_subdev_call(sd, core, ioctl, + CAM_SD_SHUTDOWN, subdev_fh); } } g_dev.open_cnt--; + g_dev.shutdown_state = false; + g_dev.read_active_dev_id_hdls = 0; v4l2_fh_release(filep); spin_lock_bh(&g_dev.cam_eventq_lock); @@ -659,6 +668,51 @@ void cam_subdev_notify_message(u32 subdev_type, } EXPORT_SYMBOL(cam_subdev_notify_message); + +static int cam_req_mgr_ordered_list_cmp(void *priv, + struct list_head *head_1, struct list_head *head_2) +{ + struct cam_subdev *entry_1 = + list_entry(head_1, struct cam_subdev, list); + struct cam_subdev *entry_2 = + list_entry(head_2, struct cam_subdev, list); + int ret = -1; + + if (entry_1->close_seq_prior > entry_2->close_seq_prior) + return 1; + else if (entry_1->close_seq_prior < entry_2->close_seq_prior) + return ret; + else + return 0; +} + +bool cam_req_mgr_is_open(uint64_t dev_id) +{ + bool crm_status; + bool dev_id_status; + + mutex_lock(&g_dev.cam_lock); + crm_status = g_dev.open_cnt ? true : false; + + if (!g_dev.read_active_dev_id_hdls) { + g_dev.active_dev_id_hdls = cam_get_dev_handle_status(); + g_dev.read_active_dev_id_hdls++; + } + + dev_id_status = (g_dev.active_dev_id_hdls & dev_id) ? true : false; + crm_status &= dev_id_status; + mutex_unlock(&g_dev.cam_lock); + + return crm_status; +} +EXPORT_SYMBOL(cam_req_mgr_is_open); + +bool cam_req_mgr_is_shutdown(void) +{ + return g_dev.shutdown_state; +} +EXPORT_SYMBOL(cam_req_mgr_is_shutdown); + int cam_register_subdev(struct cam_subdev *csd) { struct v4l2_subdev *sd; @@ -687,6 +741,10 @@ int cam_register_subdev(struct cam_subdev *csd) sd->entity.pads = NULL; sd->entity.function = csd->ent_function; + list_add(&csd->list, &cam_req_mgr_ordered_sd_list); + list_sort(NULL, &cam_req_mgr_ordered_sd_list, + cam_req_mgr_ordered_list_cmp); + rc = v4l2_device_register_subdev(g_dev.v4l2_dev, sd); if (rc) { CAM_ERR(CAM_CRM, "register subdev failed"); @@ -747,6 +805,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) goto video_setup_fail; g_dev.open_cnt = 0; + g_dev.shutdown_state = false; mutex_init(&g_dev.cam_lock); spin_lock_init(&g_dev.cam_eventq_lock); mutex_init(&g_dev.dev_lock); @@ -764,6 +823,7 @@ static int cam_req_mgr_component_master_bind(struct device *dev) } g_dev.state = true; + INIT_LIST_HEAD(&cam_req_mgr_ordered_sd_list); if (g_cam_req_mgr_timer_cachep == NULL) { g_cam_req_mgr_timer_cachep = kmem_cache_create("crm_timer", diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.h b/drivers/cam_req_mgr/cam_req_mgr_dev.h index d374f6cce319..0a55789b7c7d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.h +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.h @@ -19,6 +19,9 @@ * @cam_lock: per file handle lock * @cam_eventq: event queue * @cam_eventq_lock: lock for event queue + * @shutdown_state: shutdown state + * @active_dev_id_hdls: active dev id handles + * @read_active_dev_id_hdls: read active_dev_id_hdls status */ struct cam_req_mgr_device { struct video_device *video; @@ -30,6 +33,9 @@ struct cam_req_mgr_device { struct mutex cam_lock; struct v4l2_fh *cam_eventq; spinlock_t cam_eventq_lock; + bool shutdown_state; + uint64_t active_dev_id_hdls; + int read_active_dev_id_hdls; }; #define CAM_REQ_MGR_GET_PAYLOAD_PTR(ev, type) \ diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.c b/drivers/cam_req_mgr/cam_req_mgr_util.c index 02e4e53ef5d7..00b919fcec30 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -14,6 +14,7 @@ #include #include "cam_req_mgr_util.h" #include "cam_debug_util.h" +#include "cam_context.h" static struct cam_req_mgr_util_hdl_tbl *hdl_tbl; static DEFINE_SPINLOCK(hdl_tbl_lock); @@ -209,6 +210,36 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) return handle; } +int32_t cam_get_dev_handle_info(uint64_t handle, + struct cam_context **ctx, int32_t dev_index) +{ + int32_t idx; + struct v4l2_subdev *sd = (struct v4l2_subdev *)handle; + + for (idx = dev_index + 1; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) { + if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) { + *ctx = (struct cam_context *)cam_get_device_priv( + hdl_tbl->hdl[idx].hdl_value); + if ((*ctx) && !strcmp(sd->name, (*ctx)->dev_name)) + return idx; + } + } + *ctx = NULL; + return CAM_REQ_MGR_MAX_HANDLES_V2; +} + +uint64_t cam_get_dev_handle_status(void) +{ + int32_t idx; + uint64_t active_dev_hdls = 0; + + for (idx = 0; idx < CAM_REQ_MGR_MAX_HANDLES_V2; idx++) + if (hdl_tbl->hdl[idx].state == HDL_ACTIVE) + active_dev_hdls |= hdl_tbl->hdl[idx].dev_id; + + return active_dev_hdls; +} + void *cam_get_device_priv(int32_t dev_hdl) { int idx; diff --git a/drivers/cam_req_mgr/cam_req_mgr_util.h b/drivers/cam_req_mgr/cam_req_mgr_util.h index 0d0fec1f8e01..fb70401306d9 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_util.h +++ b/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -166,4 +166,11 @@ int32_t cam_req_mgr_util_deinit(void); */ int32_t cam_req_mgr_util_free_hdls(void); +/** + * cam_get_dev_handle_status() - get dev handles status + * + * Returns dev handle status + */ +uint64_t cam_get_dev_handle_status(void); + #endif /* _CAM_REQ_MGR_UTIL_API_H_ */ diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index a6f6d7062c0f..e37d7177c8a3 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -21,6 +21,13 @@ enum cam_subdev_message_type_t { CAM_SUBDEV_MESSAGE_CLOCK_UPDATE }; +/* Enum for close sequence priority */ +enum cam_subdev_close_seq_priority { + CAM_SD_CLOSE_HIGH_PRIORITY, + CAM_SD_CLOSE_MEDIUM_PRIORITY, + CAM_SD_CLOSE_LOW_PRIORITY +}; + /** * struct cam_subdev - describes a camera sub-device * @@ -39,6 +46,8 @@ enum cam_subdev_message_type_t { * @ent_function: Media entity function type. Can be: * %CAM_IFE_DEVICE_TYPE - identifies as IFE device. * %CAM_ICP_DEVICE_TYPE - identifies as ICP device. + * @list: list pointer + * @close_seq_prior: cam_subdev_close_seq_priority type * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. This structure should be @@ -58,6 +67,8 @@ struct cam_subdev { struct v4l2_subdev *sd, enum cam_subdev_message_type_t msg_type, uint32_t data); + struct list_head list; + enum cam_subdev_close_seq_priority close_seq_prior; }; /** @@ -119,4 +130,20 @@ int cam_register_subdev(struct cam_subdev *sd); */ int cam_unregister_subdev(struct cam_subdev *sd); +/** + * cam_req_mgr_is_open() + * + * @brief: This common utility function returns the crm active status + * + * @dev_id: device id type + */ +bool cam_req_mgr_is_open(uint64_t dev_id); + +/** + * cam_req_mgr_is_shutdown() + * + * @brief: This common utility function returns the shutdown state + */ +bool cam_req_mgr_is_shutdown(void); + #endif /* _CAM_SUBDEV_H_ */ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 96435bcd5fe6..d51dae6d37d7 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -10,6 +10,38 @@ #include "cam_trace.h" #include "camera_main.h" +static int cam_actuator_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_actuator_ctrl_t *a_ctrl = + v4l2_get_subdevdata(sd); + + if (!a_ctrl) { + CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&(a_ctrl->actuator_mutex)); + cam_actuator_shutdown(a_ctrl); + mutex_unlock(&(a_ctrl->actuator_mutex)); + + return 0; +} + +static int cam_actuator_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_ACTUATOR); + + if (crm_active) { + CAM_INFO(CAM_ACTUATOR, + "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_actuator_subdev_close_internal(sd, fh); +} + static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -24,6 +56,14 @@ static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd, CAM_ERR(CAM_ACTUATOR, "Failed for driver_cmd: %d", rc); break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_actuator_subdev_close_internal(sd, NULL); + break; default: CAM_ERR(CAM_ACTUATOR, "Invalid ioctl cmd: %u", cmd); rc = -ENOIOCTLCMD; @@ -77,24 +117,6 @@ static long cam_actuator_init_subdev_do_ioctl(struct v4l2_subdev *sd, } #endif -static int cam_actuator_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_actuator_ctrl_t *a_ctrl = - v4l2_get_subdevdata(sd); - - if (!a_ctrl) { - CAM_ERR(CAM_ACTUATOR, "a_ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&(a_ctrl->actuator_mutex)); - cam_actuator_shutdown(a_ctrl); - mutex_unlock(&(a_ctrl->actuator_mutex)); - - return 0; -} - static struct v4l2_subdev_core_ops cam_actuator_subdev_core_ops = { .ioctl = cam_actuator_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -127,10 +149,13 @@ static int cam_actuator_init_subdev(struct cam_actuator_ctrl_t *a_ctrl) a_ctrl->v4l2_dev_str.ent_function = CAM_ACTUATOR_DEVICE_TYPE; a_ctrl->v4l2_dev_str.token = a_ctrl; + a_ctrl->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(a_ctrl->v4l2_dev_str)); if (rc) - CAM_ERR(CAM_SENSOR, "Fail with cam_register_subdev rc: %d", rc); + CAM_ERR(CAM_ACTUATOR, + "Fail with cam_register_subdev rc: %d", rc); return rc; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index fbe53591fc6e..17216d86d038 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -77,29 +77,7 @@ static void cam_csiphy_debug_unregister(void) root_dentry = NULL; } -static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); - int rc = 0; - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_csiphy_core_cfg(csiphy_dev, arg); - if (rc) - CAM_ERR(CAM_CSIPHY, - "Failed in configuring the device: %d", rc); - break; - default: - CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, +static int cam_csiphy_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct csiphy_device *csiphy_dev = @@ -117,6 +95,49 @@ static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_CSIPHY); + + if (crm_active) { + CAM_INFO(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_csiphy_subdev_close_internal(sd, fh); +} + +static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); + int rc = 0; + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_csiphy_core_cfg(csiphy_dev, arg); + if (rc) + CAM_ERR(CAM_CSIPHY, + "Failed in configuring the device: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_csiphy_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_CSIPHY, "Wrong ioctl : %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + #ifdef CONFIG_COMPAT static long cam_csiphy_subdev_compat_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -236,6 +257,8 @@ static int cam_csiphy_component_bind(struct device *dev, cam_csiphy_subdev_handle_message; new_csiphy_dev->v4l2_dev_str.token = new_csiphy_dev; + new_csiphy_dev->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(new_csiphy_dev->v4l2_dev_str)); if (rc < 0) { diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index 2c0f791b6f7e..cfcc166892d7 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -10,28 +10,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_eeprom_driver_cmd(e_ctrl, arg); - if (rc) - CAM_ERR(CAM_EEPROM, - "Failed in Driver cmd: %d", rc); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, +static int cam_eeprom_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_eeprom_ctrl_t *e_ctrl = @@ -49,6 +28,48 @@ static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_EEPROM); + + if (crm_active) { + CAM_INFO(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_eeprom_subdev_close_internal(sd, fh); +} + +static long cam_eeprom_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_eeprom_driver_cmd(e_ctrl, arg); + if (rc) + CAM_ERR(CAM_EEPROM, + "Failed in Driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_eeprom_subdev_close_internal(sd, NULL); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_eeprom_i2c_info_t *i2c_info) { @@ -147,6 +168,7 @@ static int cam_eeprom_init_subdev(struct cam_eeprom_ctrl_t *e_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); e_ctrl->v4l2_dev_str.ent_function = CAM_EEPROM_DEVICE_TYPE; e_ctrl->v4l2_dev_str.token = e_ctrl; + e_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(e_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 5a4655834eaa..8386d8d6b817 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -236,6 +236,37 @@ static const struct of_device_id cam_flash_dt_match[] = { {} }; +static int cam_flash_subdev_close_internal(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct cam_flash_ctrl *fctrl = + v4l2_get_subdevdata(sd); + + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); + return -EINVAL; + } + + mutex_lock(&fctrl->flash_mutex); + cam_flash_shutdown(fctrl); + mutex_unlock(&fctrl->flash_mutex); + + return 0; +} + +static int cam_flash_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_FLASH); + + if (crm_active) { + CAM_INFO(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_flash_subdev_close_internal(sd, fh); +} + static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -257,6 +288,14 @@ static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd, "Failed in driver cmd: %d", rc); break; } + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_flash_subdev_close_internal(sd, NULL); + break; default: CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type"); rc = -ENOIOCTLCMD; @@ -328,24 +367,6 @@ static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client) return rc; } -static int cam_flash_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct cam_flash_ctrl *fctrl = - v4l2_get_subdevdata(sd); - - if (!fctrl) { - CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL"); - return -EINVAL; - } - - mutex_lock(&fctrl->flash_mutex); - cam_flash_shutdown(fctrl); - mutex_unlock(&fctrl->flash_mutex); - - return 0; -} - static struct v4l2_subdev_core_ops cam_flash_subdev_core_ops = { .ioctl = cam_flash_subdev_ioctl, #ifdef CONFIG_COMPAT @@ -375,6 +396,7 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; fctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE; fctrl->v4l2_dev_str.token = fctrl; + fctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(fctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index b47d90225ca0..94b6a9cd8271 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -10,29 +10,7 @@ #include "cam_debug_util.h" #include "camera_main.h" -static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_ois_driver_cmd(o_ctrl, arg); - if (rc) - CAM_ERR(CAM_OIS, - "Failed with driver cmd: %d", rc); - break; - default: - CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -static int cam_ois_subdev_close(struct v4l2_subdev *sd, +static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_ois_ctrl_t *o_ctrl = @@ -50,6 +28,48 @@ static int cam_ois_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_ois_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_OIS); + + if (crm_active) { + CAM_INFO(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_ois_subdev_close_internal(sd, fh); +} + +static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_ois_driver_cmd(o_ctrl, arg); + if (rc) + CAM_ERR(CAM_OIS, + "Failed with driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + rc = cam_ois_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_OIS, "Wrong IOCTL cmd: %u", cmd); + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + static int32_t cam_ois_update_i2c_info(struct cam_ois_ctrl_t *o_ctrl, struct cam_ois_i2c_info_t *i2c_info) { @@ -144,6 +164,7 @@ static int cam_ois_init_subdev_param(struct cam_ois_ctrl_t *o_ctrl) (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); o_ctrl->v4l2_dev_str.ent_function = CAM_OIS_DEVICE_TYPE; o_ctrl->v4l2_dev_str.token = o_ctrl; + o_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(o_ctrl->v4l2_dev_str)); if (rc) diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 92a5d940f339..9c6e2f2a2060 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -9,29 +9,7 @@ #include "cam_sensor_core.h" #include "camera_main.h" -static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - int rc = 0; - struct cam_sensor_ctrl_t *s_ctrl = - v4l2_get_subdevdata(sd); - - switch (cmd) { - case VIDIOC_CAM_CONTROL: - rc = cam_sensor_driver_cmd(s_ctrl, arg); - if (rc) - CAM_ERR(CAM_SENSOR, - "Failed in Driver cmd: %d", rc); - break; - default: - CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); - rc = -ENOIOCTLCMD; - break; - } - return rc; -} - -static int cam_sensor_subdev_close(struct v4l2_subdev *sd, +static int cam_sensor_subdev_close_internal(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct cam_sensor_ctrl_t *s_ctrl = @@ -49,6 +27,49 @@ static int cam_sensor_subdev_close(struct v4l2_subdev *sd, return 0; } +static int cam_sensor_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + bool crm_active = cam_req_mgr_is_open(CAM_SENSOR); + + if (crm_active) { + CAM_INFO(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); + return 0; + } + + return cam_sensor_subdev_close_internal(sd, fh); +} + +static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + int rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = + v4l2_get_subdevdata(sd); + + switch (cmd) { + case VIDIOC_CAM_CONTROL: + rc = cam_sensor_driver_cmd(s_ctrl, arg); + if (rc) + CAM_ERR(CAM_SENSOR, + "Failed in Driver cmd: %d", rc); + break; + case CAM_SD_SHUTDOWN: + if (!cam_req_mgr_is_shutdown()) { + CAM_ERR(CAM_CORE, "SD shouldn't come from user space"); + return 0; + } + + rc = cam_sensor_subdev_close_internal(sd, NULL); + break; + default: + CAM_ERR(CAM_SENSOR, "Invalid ioctl cmd: %d", cmd); + rc = -ENOIOCTLCMD; + break; + } + return rc; +} + #ifdef CONFIG_COMPAT static long cam_sensor_init_subdev_do_ioctl(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) @@ -122,6 +143,8 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl) s_ctrl->v4l2_dev_str.ent_function = CAM_SENSOR_DEVICE_TYPE; s_ctrl->v4l2_dev_str.token = s_ctrl; + s_ctrl->v4l2_dev_str.close_seq_prior = + CAM_SD_CLOSE_MEDIUM_PRIORITY; rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str)); if (rc) From 41716fade55176e8d73865491fec824e9a78784d Mon Sep 17 00:00:00 2001 From: Alok Chauhan Date: Fri, 30 Apr 2021 16:11:43 +0530 Subject: [PATCH 12/20] msm: camera: req_mgr: Fix deadlock in ICP driver in close sequence ICP driver is not releasing mutex in error scenario in close sequence and causing deadlock further in open. Fix the deadlock and avoid prints in other driver while close in provider crash. CRs-Fixed: 2938073 Change-Id: I226c9a8e9b2d0c30e90282b11fbd15ea0b085f87 Signed-off-by: Alok Chauhan --- drivers/cam_icp/cam_icp_subdev.c | 4 ++-- drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c | 2 +- drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c | 2 +- drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c | 2 +- drivers/cam_sensor_module/cam_flash/cam_flash_dev.c | 2 +- drivers/cam_sensor_module/cam_ois/cam_ois_dev.c | 2 +- drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/cam_icp/cam_icp_subdev.c b/drivers/cam_icp/cam_icp_subdev.c index 3288964444ef..1a3be9b64ad5 100644 --- a/drivers/cam_icp/cam_icp_subdev.c +++ b/drivers/cam_icp/cam_icp_subdev.c @@ -107,8 +107,8 @@ int cam_icp_subdev_close_internal(struct v4l2_subdev *sd, mutex_lock(&g_icp_dev.icp_lock); if (g_icp_dev.open_cnt <= 0) { - CAM_WARN(CAM_ICP, "ICP subdev is already closed"); - return 0; + CAM_DBG(CAM_ICP, "ICP subdev is already closed"); + goto end; } g_icp_dev.open_cnt--; if (!node) { diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c index d51dae6d37d7..17b310eee33a 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -34,7 +34,7 @@ static int cam_actuator_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_ACTUATOR); if (crm_active) { - CAM_INFO(CAM_ACTUATOR, + CAM_DBG(CAM_ACTUATOR, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 17216d86d038..204f1df7c653 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -101,7 +101,7 @@ static int cam_csiphy_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_CSIPHY); if (crm_active) { - CAM_INFO(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_CSIPHY, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c index cfcc166892d7..00d695326bcf 100644 --- a/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c +++ b/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c @@ -34,7 +34,7 @@ static int cam_eeprom_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_EEPROM); if (crm_active) { - CAM_INFO(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_EEPROM, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 8386d8d6b817..471b788cc211 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -260,7 +260,7 @@ static int cam_flash_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_FLASH); if (crm_active) { - CAM_INFO(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_FLASH, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index 94b6a9cd8271..a7616d4d19b1 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -34,7 +34,7 @@ static int cam_ois_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_OIS); if (crm_active) { - CAM_INFO(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_OIS, "CRM is ACTIVE, close should be from CRM"); return 0; } diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 9c6e2f2a2060..d4982ab2311e 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -33,7 +33,7 @@ static int cam_sensor_subdev_close(struct v4l2_subdev *sd, bool crm_active = cam_req_mgr_is_open(CAM_SENSOR); if (crm_active) { - CAM_INFO(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); + CAM_DBG(CAM_SENSOR, "CRM is ACTIVE, close should be from CRM"); return 0; } From 4c9ba2b3627c6719616c41ac3a8ecde4c35d7afa Mon Sep 17 00:00:00 2001 From: Amit Somani Date: Mon, 8 Feb 2021 19:22:07 +0530 Subject: [PATCH 13/20] msm: camera: config: Add Support for monaco target Add camera config support for MONACO target. CRs-Fixed: 2918290 Change-Id: I98ff2a0d540aa6a4fb5a31a8d26f7abe0750918d Signed-off-by: Amit Somani --- Makefile | 9 +++++++++ config/monacocamera.conf | 8 ++++++++ config/monacocameraconf.h | 11 +++++++++++ 3 files changed, 28 insertions(+) create mode 100644 config/monacocamera.conf create mode 100644 config/monacocameraconf.h diff --git a/Makefile b/Makefile index 44714b7440f5..e25a6ede1961 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,10 @@ ifeq ($(CONFIG_ARCH_BENGAL), y) include $(srctree)/techpack/camera/config/bengalcamera.conf endif +ifeq ($(CONFIG_ARCH_MONACO), y) +include $(srctree)/techpack/camera/config/monacocamera.conf +endif + ifeq ($(CONFIG_ARCH_LAHAINA), y) include $(srctree)/techpack/camera/config/lahainacamera.conf endif @@ -45,6 +49,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/bengalcameraconf.h endif +ifeq ($(CONFIG_ARCH_MONACO), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/monacocameraconf.h +endif + ifeq ($(CONFIG_ARCH_LAHAINA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/lahainacameraconf.h diff --git a/config/monacocamera.conf b/config/monacocamera.conf new file mode 100644 index 000000000000..99b81918e8a3 --- /dev/null +++ b/config/monacocamera.conf @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2019,2021 The Linux Foundation. All rights reserved. + +export CONFIG_SPECTRA_CAMERA=y +export CONFIG_SPECTRA_TFE=y +export CONFIG_SPECTRA_ISP=y +export CONFIG_SPECTRA_SENSOR=y +export CONFIG_SPECTRA_OPE=y diff --git a/config/monacocameraconf.h b/config/monacocameraconf.h new file mode 100644 index 000000000000..17a038cc14d9 --- /dev/null +++ b/config/monacocameraconf.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_TFE 1 +#define CONFIG_SPECTRA_ISP 1 +#define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_SPECTRA_OPE 1 + From d3f13f02a4b0acf7a61a3b88a4783347b60bc24c Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 21 May 2021 12:22:20 +0530 Subject: [PATCH 14/20] msm: camera: core: Make Blair camera module dynamic This change is to make Blair camera module dynamic. CRs-Fixed: 2944976 Change-Id: I1af60fd3e1e607f52285d7abf30321ff6682149e Signed-off-by: Ayush Kumar --- config/blaircamera.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/blaircamera.conf b/config/blaircamera.conf index be2ce67888d1..4a5de0e8362a 100644 --- a/config/blaircamera.conf +++ b/config/blaircamera.conf @@ -2,7 +2,7 @@ # Copyright (c) 2021, The Linux Foundation. All rights reserved. ifeq ($(CONFIG_QGKI),y) -export CONFIG_SPECTRA_CAMERA=y +export CONFIG_SPECTRA_CAMERA=m $(info "SPECTRA_CAMERA IS STATIC") else $(info "SPECTRA_CAMERA IS MODULAR") From 5c97b95b7b76869cfb5e60a945021ceeec5f9cf5 Mon Sep 17 00:00:00 2001 From: Sureshnaidu Laveti Date: Fri, 5 Mar 2021 16:17:57 -0800 Subject: [PATCH 15/20] msm: camera: sensor: extend I2C read/write size Extend I2C read/write capability to 20kb CRs-Fixed: 2952585 Change-Id: Ia5465342fd1d434f90e472c3dd5a5275c3fab8cd Signed-off-by: Sureshnaidu Laveti --- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 6 +++--- drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 46cf0315dcab..5e12aa557cd9 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CCI_DEV_H_ @@ -50,8 +50,8 @@ #define CCI_READ_MAX 256 #define CCI_READ_MAX_V_1_2 0xE #define CCI_I2C_READ_MAX_RETRIES 3 -#define CCI_I2C_MAX_READ 10240 -#define CCI_I2C_MAX_WRITE 10240 +#define CCI_I2C_MAX_READ 20480 +#define CCI_I2C_MAX_WRITE 20480 #define CCI_I2C_MAX_BYTE_COUNT 65535 #define CAMX_CCI_DEV_NAME "cam-cci-driver" diff --git a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h index e37314a46571..6cece10403c9 100644 --- a/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h +++ b/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_I2C_H_ @@ -18,7 +18,7 @@ #define I2C_COMPARE_MATCH 0 #define I2C_COMPARE_MISMATCH 1 -#define I2C_REG_DATA_MAX (10*1024) +#define I2C_REG_DATA_MAX (20*1024) /** * @client: CCI client structure From 93f25fccc80cf7e3103beaabf44c70a70c52da62 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 13 Apr 2021 13:54:28 +0800 Subject: [PATCH 16/20] msm: camera: isp: Mask process_bubble for SHDR usecase SHDR usecase doesn't report bubble to CRM, but we still need to know whether it is processing bubble during applying request, since we may haven't received the reg update of the previous applied request, then we have a chance to apply a new req to HW, this may result in overflow issue. This change masks the process_bubble for SHDR case during epoch in applied sub state. CRs-Fixed: 2948932 Change-Id: I699a2f59ea874693b78a918895db98727b95c634 Signed-off-by: Depeng Shao --- drivers/cam_isp/cam_isp_context.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 60f974ff94e7..00af70d8a093 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -864,6 +864,18 @@ static int __cam_isp_ctx_handle_buf_done_for_req_list( list_add_tail(&req->list, &ctx->free_req_list); req_isp->reapply = false; req_isp->cdm_reset_before_apply = false; + req_isp->num_acked = 0; + req_isp->num_deferred_acks = 0; + req_isp->bubble_detected = false; + /* + * Only update the process_bubble and bubble_frame_cnt + * when bubble is detected on this req, in case the other + * request is processing bubble. + */ + if (req_isp->bubble_detected) { + atomic_set(&ctx_isp->process_bubble, 0); + ctx_isp->bubble_frame_cnt = 0; + } CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", @@ -2101,6 +2113,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, ctx_isp->frame_id, ctx->ctx_id); } } + atomic_set(&ctx_isp->process_bubble, 1); } /* @@ -2336,6 +2349,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( ctx_isp->frame_id, ctx->ctx_id); } } + atomic_set(&ctx_isp->process_bubble, 1); } /* From 56f616b4634fa5cb6068e9b9305a50053204ca11 Mon Sep 17 00:00:00 2001 From: Amit Somani Date: Thu, 20 May 2021 06:10:23 +0530 Subject: [PATCH 17/20] msm: camera: sensor: fix 64-bit division for 32-bit kernel compilation Fix a 64bit division error for 32bit kernel compilation. CRs-Fixed: 2918290 Change-Id: Ic729644088eb6e8640de240d76b2e8971d2f569c Signed-off-by: Amit Somani --- drivers/cam_sensor_module/cam_flash/cam_flash_core.c | 4 ++-- drivers/cam_utils/cam_soc_icc.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 8cda6c3831c8..8fe5b78243f3 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -10,6 +10,7 @@ #include "cam_res_mgr_api.h" #include "cam_common_util.h" #include "cam_packet_util.h" +#include static uint default_on_timer = 2; module_param(default_on_timer, uint, 0644); @@ -1558,8 +1559,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) add_req.trigger_eof = true; /* Active time for the preflash */ flash_data->flash_active_time_ms = - (flash_operation_info->time_on_duration_ns) - / 1000000; + do_div(flash_operation_info->time_on_duration_ns, 1000000); CAM_DBG(CAM_FLASH, "PRECISE FLASH: active_time: %llu", flash_data->flash_active_time_ms); diff --git a/drivers/cam_utils/cam_soc_icc.c b/drivers/cam_utils/cam_soc_icc.c index a30e0f153b1b..757254777740 100644 --- a/drivers/cam_utils/cam_soc_icc.c +++ b/drivers/cam_utils/cam_soc_icc.c @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include #include "cam_soc_bus.h" - +#include /** * struct cam_soc_bus_client_data : Bus client data * @@ -37,8 +37,8 @@ int cam_soc_bus_client_update_request(void *client, unsigned int idx) CAM_DBG(CAM_PERF, "Bus client=[%s] index[%d] ab[%llu] ib[%llu]", bus_client->common_data->name, idx, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab), - Bps_to_icc(ib)); + rc = icc_set_bw(bus_client_data->icc_data, do_div(ab, 1000), + do_div(ib, 1000)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s], idx: %d", @@ -60,8 +60,8 @@ int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib) CAM_DBG(CAM_PERF, "Bus client=[%s] :ab[%llu] ib[%llu]", bus_client->common_data->name, ab, ib); - rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab), - Bps_to_icc(ib)); + rc = icc_set_bw(bus_client_data->icc_data, do_div(ab, 1000), + do_div(ib, 1000)); if (rc) { CAM_ERR(CAM_UTIL, "Update request failed, client[%s]", bus_client->common_data->name); From 7a10111a875e1f380cf3739e745fa8230fe0d5d5 Mon Sep 17 00:00:00 2001 From: Jigar Agrawal Date: Thu, 4 Feb 2021 11:54:21 -0800 Subject: [PATCH 18/20] msm: camera: sensor: Increase slot ids in sensor Increase the max supported slot ids to 16 in sensor. CRs-Fixed: 2871214 Change-Id: I08910f2c34f70333bf25dbb31de5994c3beb7a8f Signed-off-by: Jigar Agrawal --- .../cam_sensor_utils/cam_sensor_cmn_header.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 25ab72ae6069..58a248f4c882 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_CMN_HEADER_ @@ -345,6 +345,12 @@ enum msm_sensor_camera_id_t { CAMERA_7, CAMERA_8, CAMERA_9, + CAMERA_10, + CAMERA_11, + CAMERA_12, + CAMERA_13, + CAMERA_14, + CAMERA_15, MAX_CAMERAS, }; From de2b0fb94b1ac6910cefea9512805a123cf3aa7f Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Thu, 6 May 2021 11:38:30 +0530 Subject: [PATCH 19/20] msm: camera: flash: Add support for I2C flash - Add Regulator power up for I2C flash - Add GPIO support in probe call for I2C flash - Add flash type in query capability call of flash. CRs-Fixed: 2938804 Change-Id: I7d5575ecdf4c1c3b329e6bf49586771e37611e5a Signed-off-by: shiwgupt --- .../cam_sensor_module/cam_flash/cam_flash_dev.c | 17 ++++++++++++++++- .../cam_sensor_module/cam_flash/cam_flash_dev.h | 5 ++++- .../cam_sensor_module/cam_flash/cam_flash_soc.c | 8 +++++++- .../cam_sensor_utils/cam_sensor_util.c | 4 ++++ include/uapi/camera/media/cam_sensor.h | 4 +++- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 5a4655834eaa..d92b81605fdc 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -133,7 +133,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, struct cam_flash_query_cap_info flash_cap = {0}; CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP"); - flash_cap.slot_info = fctrl->soc_info.index; + flash_cap.slot_info = fctrl->soc_info.index; + flash_cap.flash_type = soc_private->flash_type; for (i = 0; i < fctrl->flash_num_sources; i++) { flash_cap.max_current_flash[i] = soc_private->flash_max_current[i]; @@ -390,6 +391,7 @@ static int cam_flash_component_bind(struct device *dev, struct cam_flash_ctrl *fctrl = NULL; struct device_node *of_parent = NULL; struct platform_device *pdev = to_platform_device(dev); + struct cam_hw_soc_info *soc_info = NULL; CAM_DBG(CAM_FLASH, "Binding flash component"); if (!pdev->dev.of_node) { @@ -445,6 +447,19 @@ static int cam_flash_component_bind(struct device *dev, fctrl->io_master_info.cci_client->cci_device = fctrl->cci_num; CAM_DBG(CAM_FLASH, "cci-index %d", fctrl->cci_num, rc); + soc_info = &fctrl->soc_info; + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &fctrl->power_info.gpio_num_info); + if ((rc < 0) || (!fctrl->power_info.gpio_num_info)) { + CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs"); + return -EINVAL; + } + rc = cam_sensor_util_regulator_powerup(soc_info); + if (rc < 0) { + CAM_ERR(CAM_FLASH, "regulator power up for flash failed %d", rc); + return rc; + } + fctrl->i2c_data.per_frame = kzalloc(sizeof(struct i2c_settings_array) * MAX_PER_FRAME_ARRAY, GFP_KERNEL); diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index b8416cd15d8b..cc1c9738d2b6 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FLASH_DEV_H_ @@ -30,6 +30,7 @@ #include "cam_subdev.h" #include "cam_mem_mgr.h" #include "cam_sensor_cmn_header.h" +#include "cam_sensor_util.h" #include "cam_soc_util.h" #include "cam_debug_util.h" #include "cam_sensor_io.h" @@ -137,6 +138,7 @@ struct cam_flash_frame_setting { * @torch_op_current : Torch operational current * @torch_max_current : Max supported current for LED in torch mode * @is_wled_flash : Detection between WLED/LED flash + * @flash_type : Flash type */ struct cam_flash_private_soc { @@ -149,6 +151,7 @@ struct cam_flash_private_soc { uint32_t torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; bool is_wled_flash; + uint32_t flash_type; }; struct cam_flash_func_tbl { diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index 17b7c7e0aec8..9af39e9560fb 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -73,6 +73,12 @@ static int32_t cam_get_source_node_info( soc_private->is_wled_flash = of_property_read_bool(of_node, "wled-flash-support"); + rc = of_property_read_u32(of_node, "flash-type", &soc_private->flash_type); + if (rc) { + CAM_ERR(CAM_FLASH, + "flash-type read failed rc=%d", rc); + } + switch_src_node = of_parse_phandle(of_node, "switch-source", 0); if (!switch_src_node) { CAM_WARN(CAM_FLASH, "switch_src_node NULL"); diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 4147c1dc7409..771ca38fa6d8 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -2407,6 +2407,10 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, case SENSOR_CUSTOM_GPIO1: case SENSOR_CUSTOM_GPIO2: + if (!gpio_num_info) { + CAM_ERR(CAM_SENSOR, "failed: No gpio"); + continue; + } if (!gpio_num_info->valid[pd->seq_type]) continue; diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index cff997346943..f935a7a702b3 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_SENSOR_H__ @@ -476,6 +476,7 @@ struct cam_flash_query_curr { * @max_current_flash : max supported current for flash * @max_duration_flash : max flash turn on duration * @max_current_torch : max supported current for torch + * @flash_type : Indicates about the flash type -I2C,GPIO,PMIC * */ struct cam_flash_query_cap_info { @@ -483,6 +484,7 @@ struct cam_flash_query_cap_info { __u32 max_current_flash[CAM_FLASH_MAX_LED_TRIGGERS]; __u32 max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS]; __u32 max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS]; + __u32 flash_type; } __attribute__ ((packed)); #endif From 0c570733eee53cf47a261d84e438cbaa6d0eb6d2 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kanakanti Date: Tue, 1 Jun 2021 19:56:41 +0530 Subject: [PATCH 20/20] msm: camera: cci: Fix CCI Timeout during burst_read concurrency During burst read concurrency, is_burst_read variable not updated properly leading to missing th_complete signal. is_burst_read variable updated per master to avoid concurrency issue. CRs-Fixed: 2962232 Change-Id: Id741d48e0b9a6987b4aa7bc7361daf555d9bc587 Signed-off-by: Anil Kumar Kanakanti --- drivers/cam_sensor_module/cam_cci/cam_cci_core.c | 10 ++++------ drivers/cam_sensor_module/cam_cci/cam_cci_dev.c | 6 +++--- drivers/cam_sensor_module/cam_cci/cam_cci_dev.h | 4 ++-- drivers/cam_sensor_module/cam_cci/cam_cci_soc.c | 3 ++- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index 59dad9ee4e72..e4e185bb28c1 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -985,6 +985,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, } mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); + cci_dev->is_burst_read[master] = true; reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]); soc_info = &cci_dev->soc_info; @@ -1256,6 +1257,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, } mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); + cci_dev->is_burst_read[master] = false; reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]); soc_info = &cci_dev->soc_info; @@ -1622,7 +1624,7 @@ static int32_t cam_cci_read_bytes_v_1_2(struct v4l2_subdev *sd, else read_cfg->num_byte = read_bytes; - cci_dev->is_burst_read = false; + cci_dev->is_burst_read[master] = false; rc = cam_cci_read(sd, c_ctrl); if (rc) { CAM_ERR(CAM_CCI, "failed to read rc:%d", rc); @@ -1639,7 +1641,6 @@ static int32_t cam_cci_read_bytes_v_1_2(struct v4l2_subdev *sd, } while (read_bytes); ERROR: - cci_dev->is_burst_read = false; return rc; } @@ -1704,10 +1705,8 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, read_cfg->num_byte = read_bytes; if (read_cfg->num_byte >= CCI_READ_MAX) { - cci_dev->is_burst_read = true; rc = cam_cci_burst_read(sd, c_ctrl); } else { - cci_dev->is_burst_read = false; rc = cam_cci_read(sd, c_ctrl); } if (rc) { @@ -1726,7 +1725,6 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd, } while (read_bytes); ERROR: - cci_dev->is_burst_read = false; return rc; } diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 8b5ab58539f1..e496ca83cf65 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_cci_dev.h" @@ -112,7 +112,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) (!rd_done_th_assert)) { cci_dev->cci_master_info[MASTER_0].status = 0; rd_done_th_assert = true; - if (cci_dev->is_burst_read) + if (cci_dev->is_burst_read[MASTER_0]) complete( &cci_dev->cci_master_info[MASTER_0].th_complete); complete(&cci_dev->cci_master_info[MASTER_0].rd_done); @@ -168,7 +168,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) (!rd_done_th_assert)) { cci_dev->cci_master_info[MASTER_1].status = 0; rd_done_th_assert = true; - if (cci_dev->is_burst_read) + if (cci_dev->is_burst_read[MASTER_1]) complete( &cci_dev->cci_master_info[MASTER_1].th_complete); complete(&cci_dev->cci_master_info[MASTER_1].rd_done); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 46cf0315dcab..6ea516b361b2 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CCI_DEV_H_ @@ -224,7 +224,7 @@ struct cci_device { uint32_t cpas_handle; uint32_t irq_status1; spinlock_t lock_status; - bool is_burst_read; + bool is_burst_read[MASTER_MAX]; uint32_t irqs_disabled; struct mutex init_mutex; uint64_t dump_en; diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c index 39433a3f43e1..268e6c119824 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_cci_dev.h" @@ -76,6 +76,7 @@ static int cam_cci_init_master(struct cci_device *cci_dev, cci_dev->cci_master_info[master].status = 0; cci_dev->cci_master_info[master].is_initilized = true; + cci_dev->is_burst_read[master] = false; } return 0;