From 1c55b1bbe3e0761a62cd6f0c134ca967d915fc09 Mon Sep 17 00:00:00 2001 From: Ravikishore Pampana Date: Thu, 14 Feb 2019 09:18:00 +0530 Subject: [PATCH] msm: camera: isp: Handle wait and active list during flush all If umd issues flush all, isp driver need to make sure that wait and active list requests also flushed and corresponding buffer fences needed to returned. For active and wait list flush, ife hardware need to stop at frame boundary and release the fences. Ife hardware need to reset to make sure that vfe bus write master fifos are cleared. Start the ife hardware after reset and set the isp context state to sof. Change-Id: Ibc57e64fbcef07de13520f2b9e4cc37c7c62bb37 Signed-off-by: Ravikishore Pampana --- .../msm/camera/cam_core/cam_hw_mgr_intf.h | 12 ++++ .../msm/camera/cam_isp/cam_isp_context.c | 66 +++++++++++++++++-- .../cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 51 ++++++++++++-- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 8 --- 4 files changed, 119 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h index 6b7a9007cff94..2afdafb031844 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h @@ -262,6 +262,16 @@ struct cam_hw_dump_pf_args { bool *mem_found; }; +/** + * struct cam_hw_reset_args -hw reset arguments + * + * @ctxt_to_hw_map: HW context from the acquire + * + */ +struct cam_hw_reset_args { + void *ctxt_to_hw_map; +}; + /* enum cam_hw_mgr_command - Hardware manager command type */ enum cam_hw_mgr_command { CAM_HW_MGR_CMD_INTERNAL, @@ -313,6 +323,7 @@ struct cam_hw_cmd_args { * @hw_open: Function pointer for HW init * @hw_close: Function pointer for HW deinit * @hw_flush: Function pointer for HW flush + * @hw_reset: Function pointer for HW reset * */ struct cam_hw_mgr_intf { @@ -333,6 +344,7 @@ struct cam_hw_mgr_intf { int (*hw_open)(void *hw_priv, void *fw_download_args); int (*hw_close)(void *hw_priv, void *hw_close_args); int (*hw_flush)(void *hw_priv, void *hw_flush_args); + int (*hw_reset)(void *hw_priv, void *hw_reset_args); }; #endif /* _CAM_HW_MGR_INTF_H_ */ diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index 0d0ce4210ae47..cf97c4679bd1b 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -1922,16 +1922,19 @@ static int __cam_isp_ctx_flush_req_in_top_state( struct cam_req_mgr_flush_request *flush_req) { int rc = 0; - struct cam_isp_context *ctx_isp; - - ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + struct cam_isp_stop_args stop_isp; + struct cam_hw_stop_args stop_args; + struct cam_isp_start_args start_isp; + struct cam_hw_reset_args reset_args; if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { - CAM_INFO(CAM_ISP, "Last request id to flush is %lld", - flush_req->req_id); + CAM_INFO(CAM_ISP, "ctx id:%d Last request id to flush is %lld", + ctx->ctx_id, flush_req->req_id); ctx->last_flush_req = flush_req->req_id; } - CAM_DBG(CAM_ISP, "try to flush pending list"); + CAM_DBG(CAM_ISP, "ctx id:%d try to flush pending list", ctx->ctx_id); spin_lock_bh(&ctx->lock); rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); @@ -1954,6 +1957,57 @@ static int __cam_isp_ctx_flush_req_in_top_state( spin_unlock_bh(&ctx->lock); atomic_set(&ctx_isp->process_bubble, 0); + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + /* if active and wait list are empty, return */ + spin_lock_bh(&ctx->lock); + if ((list_empty(&ctx->wait_req_list)) && + (list_empty(&ctx->active_req_list))) { + spin_unlock_bh(&ctx->lock); + CAM_DBG(CAM_ISP, "ctx id:%d active,wait list are empty", + ctx->ctx_id); + goto end; + } + spin_unlock_bh(&ctx->lock); + + /* Stop hw first before active list flush */ + CAM_DBG(CAM_ISP, "ctx id:%d try to stop hw", ctx->ctx_id); + stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; + stop_isp.stop_only = true; + stop_args.args = (void *)&stop_isp; + ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, + &stop_args); + + spin_lock_bh(&ctx->lock); + CAM_DBG(CAM_ISP, "try to flush wait list"); + rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list, + flush_req); + CAM_DBG(CAM_ISP, "try to flush active list"); + rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list, + flush_req); + ctx_isp->active_req_cnt = 0; + spin_unlock_bh(&ctx->lock); + + CAM_DBG(CAM_ISP, "try to reset hw"); + /* Reset hw */ + reset_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + rc = ctx->hw_mgr_intf->hw_reset(ctx->hw_mgr_intf->hw_mgr_priv, + &reset_args); + if (rc) + goto end; + + CAM_DBG(CAM_ISP, "ctx id%d try to start hw", ctx->ctx_id); + /* Start hw */ + start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; + start_isp.start_only = true; + start_isp.hw_config.priv = NULL; + + rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, + &start_isp); + } + +end: + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; return rc; } diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 3b6d04a302ed8..fde33d223e584 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2572,6 +2572,11 @@ static int cam_ife_mgr_pause_hw(struct cam_ife_hw_mgr_ctx *ctx) return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_EXCLUDE); } +static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx) +{ + return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE); +} + /* entry function: stop_hw */ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) { @@ -2925,6 +2930,9 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index); + if (start_isp->start_only) + cam_ife_mgr_resume_hw(ctx); + /* start the IFE out devices */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { rc = cam_ife_hw_mgr_start_hw_res( @@ -3025,6 +3033,44 @@ static int cam_ife_mgr_write(void *hw_mgr_priv, void *write_args) return -EPERM; } +static int cam_ife_mgr_reset(void *hw_mgr_priv, void *hw_reset_args) +{ + struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_reset_args *reset_args = hw_reset_args; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr_res *hw_mgr_res; + uint32_t i; + int rc = 0; + + if (!hw_mgr_priv || !hw_reset_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_ife_hw_mgr_ctx *)reset_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "reset csid and vfe hw"); + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, + list) { + rc = cam_ife_hw_mgr_reset_csid_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Failed RESET (%d) rc:%d", + hw_mgr_res->res_id, rc); + goto end; + } + } + + for (i = 0; i < ctx->num_base; i++) + rc = cam_ife_mgr_reset_vfe_hw(hw_mgr, ctx->base[i].idx); + +end: + return rc; +} + static int cam_ife_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args) { @@ -4025,10 +4071,6 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv, return rc; } -static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx) -{ - return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE); -} static int cam_ife_mgr_sof_irq_debug( struct cam_ife_hw_mgr_ctx *ctx, @@ -5852,6 +5894,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) hw_mgr_intf->hw_prepare_update = cam_ife_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; + hw_mgr_intf->hw_reset = cam_ife_mgr_reset; if (iommu_hdl) *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 15d720a086a61..195867b5d5d8e 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -566,10 +566,6 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, init_completion(complete); reset_strb_val = csid_reg->cmn_reg->path_rst_stb_all; - /* Enable the Test gen before reset */ - cam_io_w_mb(1, csid_hw->hw_info->soc_info.reg_map[0].mem_base + - csid_reg->tpg_reg->csid_tpg_ctrl_addr); - /* Reset the corresponding ife csid path */ cam_io_w_mb(reset_strb_val, soc_info->reg_map[0].mem_base + reset_strb_addr); @@ -584,10 +580,6 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, rc = -ETIMEDOUT; } - /* Disable Test Gen after reset*/ - cam_io_w_mb(0, soc_info->reg_map[0].mem_base + - csid_reg->tpg_reg->csid_tpg_ctrl_addr); - end: return rc;