msm: camera: isp: Stop HW immediately in flush
When the userspace issues flush, ISP driver needs to ensure that wait and active list requests are flushed and corresponding buffer fences are signaled with error. For active and wait lists IFE hardware is stopped immediately. Therefore IFE must also be reset to ensure that VFE BUS FIFOs are cleared. Start IFE HW after receiving init packet again. CRs-Fixed: 2513939 Change-Id: I9a35ce05c24d6b63016e264a870d376eabb2b56f Signed-off-by: Venkat Chinta <vchinta@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
a5dc6c6cac
commit
aaab1ef87e
@@ -31,6 +31,9 @@ static struct cam_isp_ctx_debug isp_ctx_debug;
|
||||
static int cam_isp_context_dump_active_request(void *data, unsigned long iova,
|
||||
uint32_t buf_info);
|
||||
|
||||
static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
|
||||
struct cam_start_stop_dev_cmd *cmd);
|
||||
|
||||
static void __cam_isp_ctx_update_state_monitor_array(
|
||||
struct cam_isp_context *ctx_isp,
|
||||
enum cam_isp_state_change_trigger trigger_type,
|
||||
@@ -2072,13 +2075,15 @@ static int __cam_isp_ctx_flush_req(struct cam_context *ctx,
|
||||
}
|
||||
|
||||
static int __cam_isp_ctx_flush_req_in_top_state(
|
||||
struct cam_context *ctx,
|
||||
struct cam_context *ctx,
|
||||
struct cam_req_mgr_flush_request *flush_req)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_isp_context *ctx_isp;
|
||||
struct cam_hw_cmd_args hw_cmd_args;
|
||||
|
||||
int rc = 0;
|
||||
struct cam_isp_context *ctx_isp;
|
||||
struct cam_isp_stop_args stop_isp;
|
||||
struct cam_hw_stop_args stop_args;
|
||||
struct cam_hw_reset_args reset_args;
|
||||
struct cam_hw_cmd_args hw_cmd_args;
|
||||
|
||||
ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
|
||||
if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
|
||||
@@ -2087,7 +2092,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
|
||||
ctx->last_flush_req = flush_req->req_id;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_ISP, "try to flush pending list");
|
||||
CAM_DBG(CAM_ISP, "Flush pending list");
|
||||
spin_lock_bh(&ctx->lock);
|
||||
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
|
||||
spin_unlock_bh(&ctx->lock);
|
||||
@@ -2102,6 +2107,47 @@ static int __cam_isp_ctx_flush_req_in_top_state(
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
|
||||
if (ctx->state <= CAM_CTX_READY) {
|
||||
ctx->state = CAM_CTX_ACQUIRED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
|
||||
stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY;
|
||||
stop_isp.stop_only = true;
|
||||
stop_args.args = (void *)&stop_isp;
|
||||
rc = ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
|
||||
&stop_args);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "Failed to stop HW in Flush rc: %d",
|
||||
rc);
|
||||
|
||||
CAM_DBG(CAM_ISP, "Flush wait and active lists");
|
||||
spin_lock_bh(&ctx->lock);
|
||||
if (!list_empty(&ctx->wait_req_list))
|
||||
rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list,
|
||||
flush_req);
|
||||
|
||||
if (!list_empty(&ctx->active_req_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);
|
||||
|
||||
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)
|
||||
CAM_ERR(CAM_ISP, "Failed to reset HW rc: %d", rc);
|
||||
|
||||
ctx->state = CAM_CTX_FLUSHED;
|
||||
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT;
|
||||
ctx_isp->init_received = false;
|
||||
}
|
||||
|
||||
end:
|
||||
atomic_set(&ctx_isp->process_bubble, 0);
|
||||
return rc;
|
||||
}
|
||||
@@ -3454,6 +3500,55 @@ static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_isp_ctx_config_dev_in_flushed(struct cam_context *ctx,
|
||||
struct cam_config_dev_cmd *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_start_stop_dev_cmd start_cmd;
|
||||
struct cam_hw_cmd_args hw_cmd_args;
|
||||
struct cam_isp_hw_cmd_args isp_hw_cmd_args;
|
||||
struct cam_isp_context *ctx_isp =
|
||||
(struct cam_isp_context *) ctx->ctx_priv;
|
||||
|
||||
if (!ctx_isp->hw_acquired) {
|
||||
CAM_ERR(CAM_ISP, "HW is not acquired, reject packet");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!ctx_isp->init_received) {
|
||||
CAM_WARN(CAM_ISP,
|
||||
"Received update packet in flushed state, skip start");
|
||||
goto end;
|
||||
}
|
||||
|
||||
hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
|
||||
hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
|
||||
isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW;
|
||||
hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
|
||||
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
|
||||
&hw_cmd_args);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Failed to resume HW rc: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
start_cmd.dev_handle = cmd->dev_handle;
|
||||
start_cmd.session_handle = cmd->session_handle;
|
||||
rc = __cam_isp_ctx_start_dev_in_ready(ctx, &start_cmd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Failed to re-start HW after flush rc: %d", rc);
|
||||
|
||||
end:
|
||||
CAM_DBG(CAM_ISP, "next state %d sub_state:%d", ctx->state,
|
||||
ctx_isp->substate_activated);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx,
|
||||
struct cam_req_mgr_core_dev_link_setup *link)
|
||||
{
|
||||
@@ -3543,7 +3638,11 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
|
||||
start_isp.hw_config.priv = &req_isp->hw_update_data;
|
||||
start_isp.hw_config.init_packet = 1;
|
||||
start_isp.hw_config.reapply = 0;
|
||||
start_isp.start_only = false;
|
||||
|
||||
if (ctx->state == CAM_CTX_FLUSHED)
|
||||
start_isp.start_only = true;
|
||||
else
|
||||
start_isp.start_only = false;
|
||||
|
||||
atomic_set(&ctx_isp->process_bubble, 0);
|
||||
ctx_isp->frame_id = 0;
|
||||
@@ -3966,6 +4065,22 @@ static struct cam_ctx_ops
|
||||
.pagefault_ops = cam_isp_context_dump_active_request,
|
||||
.dumpinfo_ops = cam_isp_context_info_dump,
|
||||
},
|
||||
/* Flushed */
|
||||
{
|
||||
.ioctl_ops = {
|
||||
.stop_dev = __cam_isp_ctx_stop_dev_in_activated,
|
||||
.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,
|
||||
},
|
||||
.crm_ops = {
|
||||
.unlink = __cam_isp_ctx_unlink_in_ready,
|
||||
.process_evt = __cam_isp_ctx_process_evt,
|
||||
},
|
||||
.irq_ops = NULL,
|
||||
.pagefault_ops = cam_isp_context_dump_active_request,
|
||||
.dumpinfo_ops = cam_isp_context_info_dump,
|
||||
},
|
||||
/* Activated */
|
||||
{
|
||||
.ioctl_ops = {
|
||||
|
Reference in New Issue
Block a user