From 86f144a267ddf56c767c097c21328c6db8ddeb10 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Tue, 23 Jun 2020 22:17:18 +0800 Subject: [PATCH] msm: camera: isp: Handling IRQ delays Checking the BUS write client last consumed address, if it matches with next request port io buffer address, then irq delay detected. We can signal port fence for both active request. CRs-Fixed: 2684890 Change-Id: I8265c06a2284897d43e9a24511ad2c13c9690186 Signed-off-by: Depeng Shao --- drivers/cam_core/cam_hw_mgr_intf.h | 4 + drivers/cam_isp/cam_isp_context.c | 419 ++++++++++++++---- drivers/cam_isp/cam_isp_context.h | 2 + drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 38 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 29 ++ .../hw_utils/cam_isp_packet_parser.c | 21 + .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 3 + .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 19 +- .../isp_hw/include/cam_vfe_hw_intf.h | 6 +- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h | 1 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 42 ++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h | 2 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 1 + .../isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe480.h | 1 + .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h | 3 +- .../isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h | 3 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c | 10 + .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h | 12 +- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c | 56 ++- .../isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h | 14 +- .../vfe_hw/vfe_top/cam_vfe_camif_ver3.c | 8 +- 26 files changed, 579 insertions(+), 120 deletions(-) diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 12b01ab688..626b3be148 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -74,11 +74,13 @@ struct cam_hw_update_entry { * * @resrouce_handle: Resource port id for the buffer * @sync_id: Sync id + * @image_buf_addr: Image buffer address array * */ struct cam_hw_fence_map_entry { uint32_t resource_handle; int32_t sync_id; + int32_t image_buf_addr[CAM_PACKET_MAX_PLANES]; }; /** @@ -107,6 +109,7 @@ struct cam_hw_done_event_data { * @ctxt_to_hw_map: HW context (returned) * @custom_enabled: ctx has custom enabled * @use_frame_header_ts: Use frame header for qtimer ts + * @support_consumed_addr: The platform has last consumed addr register * @acquired_hw_id: Acquired hardware mask * @acquired_hw_path: Acquired path mask for an input * if input splits into multiple paths, @@ -123,6 +126,7 @@ struct cam_hw_acquire_args { void *ctxt_to_hw_map; bool custom_enabled; bool use_frame_header_ts; + bool support_consumed_addr; uint32_t acquired_hw_id[CAM_MAX_ACQ_RES]; uint32_t acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT]; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index be3b123bd6..811d38a589 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -790,6 +790,70 @@ static void __cam_isp_ctx_handle_buf_done_fail_log( } } +static int __cam_isp_ctx_handle_buf_done_for_req_list( + struct cam_isp_context *ctx_isp, + struct cam_ctx_request *req) +{ + int rc = 0, i; + uint64_t buf_done_req_id; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + ctx_isp->active_req_cnt--; + buf_done_req_id = req->request_id; + + if (req_isp->bubble_detected && req_isp->bubble_report) { + req_isp->num_acked = 0; + req_isp->bubble_detected = false; + list_del_init(&req->list); + atomic_set(&ctx_isp->process_bubble, 0); + + if (buf_done_req_id <= ctx->last_flush_req) { + for (i = 0; i < req_isp->num_fence_map_out; i++) + rc = cam_sync_signal( + req_isp->fence_map_out[i].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + + list_add_tail(&req->list, &ctx->free_req_list); + CAM_DBG(CAM_REQ, + "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", + buf_done_req_id, ctx_isp->active_req_cnt, + ctx->ctx_id); + } else { + list_add(&req->list, &ctx->pending_req_list); + CAM_DBG(CAM_REQ, + "Move active request %lld to pending list(cnt = %d) [bubble recovery], ctx %u", + req->request_id, ctx_isp->active_req_cnt, + ctx->ctx_id); + } + } else { + if (!ctx_isp->use_frame_header_ts) { + if (ctx_isp->reported_req_id < buf_done_req_id) { + ctx_isp->reported_req_id = buf_done_req_id; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, + buf_done_req_id, + CAM_REQ_MGR_SOF_EVENT_SUCCESS); + } + } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + req_isp->reapply = false; + + CAM_DBG(CAM_REQ, + "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", + buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); + ctx_isp->req_info.last_bufdone_req_id = req->request_id; + } + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_DONE, buf_done_req_id); + + __cam_isp_ctx_update_event_record(ctx_isp, + CAM_ISP_CTX_EVENT_BUFDONE, req); + return rc; +} + static int __cam_isp_ctx_handle_buf_done_for_request( struct cam_isp_context *ctx_isp, struct cam_ctx_request *req, @@ -801,7 +865,6 @@ static int __cam_isp_ctx_handle_buf_done_for_request( int i, j; struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; - uint64_t buf_done_req_id; const char *handle_type; trace_cam_buf_done("ISP", ctx, req); @@ -811,10 +874,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request( CAM_DBG(CAM_ISP, "Enter with bubble_state %d, req_bubble_detected %d", bubble_state, req_isp->bubble_detected); - if (done_next_req) { - done_next_req->num_handles = 0; - done_next_req->timestamp = done->timestamp; - } + done_next_req->num_handles = 0; + done_next_req->timestamp = done->timestamp; for (i = 0; i < done->num_handles; i++) { for (j = 0; j < req_isp->num_fence_map_out; j++) { @@ -824,28 +885,21 @@ static int __cam_isp_ctx_handle_buf_done_for_request( } if (j == req_isp->num_fence_map_out) { - if (done_next_req) { - /* - * If not found in current request, it could be - * belonging to next request, This can happen if - * IRQ delay happens. - */ - CAM_WARN(CAM_ISP, - "BUF_DONE for res 0x%x not found in Req %lld ", - __cam_isp_resource_handle_id_to_type( - done->resource_handle[i]), - req->request_id); + /* + * If not found in current request, it could be + * belonging to next request, this can happen if + * IRQ delay happens. It is only valid when the + * platform doesn't have last consumed address. + */ + CAM_WARN(CAM_ISP, + "BUF_DONE for res %s not found in Req %lld ", + __cam_isp_resource_handle_id_to_type( + done->resource_handle[i]), + req->request_id); - done_next_req->resource_handle - [done_next_req->num_handles++] = - done->resource_handle[i]; - } else { - CAM_ERR(CAM_ISP, - "Can not find matching lane handle 0x%x! in Req %lld", - done->resource_handle[i], - req->request_id); - rc = -EINVAL; - } + done_next_req->resource_handle + [done_next_req->num_handles++] = + done->resource_handle[i]; continue; } @@ -866,12 +920,9 @@ static int __cam_isp_ctx_handle_buf_done_for_request( trace_cam_log_event("Duplicate BufDone", handle_type, req->request_id, ctx->ctx_id); - if (done_next_req) { - done_next_req->resource_handle - [done_next_req->num_handles++] = - done->resource_handle[i]; - } - + done_next_req->resource_handle + [done_next_req->num_handles++] = + done->resource_handle[i]; continue; } @@ -944,68 +995,156 @@ static int __cam_isp_ctx_handle_buf_done_for_request( if (req_isp->num_acked != req_isp->num_fence_map_out) return rc; - ctx_isp->active_req_cnt--; - buf_done_req_id = req->request_id; - - if (req_isp->bubble_detected && req_isp->bubble_report) { - req_isp->num_acked = 0; - req_isp->bubble_detected = false; - list_del_init(&req->list); - atomic_set(&ctx_isp->process_bubble, 0); - - if (buf_done_req_id <= ctx->last_flush_req) { - for (i = 0; i < req_isp->num_fence_map_out; i++) - cam_sync_signal( - req_isp->fence_map_out[i].sync_id, - CAM_SYNC_STATE_SIGNALED_ERROR); - - list_add_tail(&req->list, &ctx->free_req_list); - CAM_DBG(CAM_REQ, - "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", - buf_done_req_id, ctx_isp->active_req_cnt, - ctx->ctx_id); - } else { - list_add(&req->list, &ctx->pending_req_list); - CAM_DBG(CAM_REQ, - "Move active request %lld to pending list(cnt = %d) [bubble recovery], ctx %u", - req->request_id, ctx_isp->active_req_cnt, - ctx->ctx_id); - } - } else { - - if (!ctx_isp->use_frame_header_ts) { - if (ctx_isp->reported_req_id < buf_done_req_id) { - ctx_isp->reported_req_id = buf_done_req_id; - __cam_isp_ctx_send_sof_timestamp(ctx_isp, - buf_done_req_id, - CAM_REQ_MGR_SOF_EVENT_SUCCESS); - } - } - list_del_init(&req->list); - list_add_tail(&req->list, &ctx->free_req_list); - req_isp->reapply = false; - - CAM_DBG(CAM_REQ, - "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", - buf_done_req_id, ctx_isp->active_req_cnt, ctx->ctx_id); - ctx_isp->req_info.last_bufdone_req_id = req->request_id; - } - - __cam_isp_ctx_update_state_monitor_array(ctx_isp, - CAM_ISP_STATE_CHANGE_TRIGGER_DONE, buf_done_req_id); - - __cam_isp_ctx_update_event_record(ctx_isp, - CAM_ISP_CTX_EVENT_BUFDONE, req); + rc = __cam_isp_ctx_handle_buf_done_for_req_list(ctx_isp, req); return rc; } -static int __cam_isp_ctx_handle_buf_done_in_activated_state( +static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( + struct cam_isp_context *ctx_isp, + struct cam_ctx_request *req, + struct cam_isp_hw_done_event_data *done, + uint32_t bubble_state, + bool verify_consumed_addr) +{ + int rc = 0; + int i, j; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + const char *handle_type; + + trace_cam_buf_done("ISP", ctx, req); + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + CAM_DBG(CAM_ISP, "Enter with bubble_state %d, req_bubble_detected %d", + bubble_state, req_isp->bubble_detected); + + for (i = 0; i < done->num_handles; i++) { + for (j = 0; j < req_isp->num_fence_map_out; j++) { + if (verify_consumed_addr && + (done->last_consumed_addr[i] != + req_isp->fence_map_out[j].image_buf_addr[0])) + continue; + + if (done->resource_handle[i] == + req_isp->fence_map_out[j].resource_handle) + break; + } + + if (j == req_isp->num_fence_map_out) { + /* + * If not found in current request, it could be + * belonging to next request, this can happen if + * IRQ delay happens. It is only valid when the + * platform doesn't have last consumed address. + */ + CAM_DBG(CAM_ISP, + "BUF_DONE for res %s not found in Req %lld ", + __cam_isp_resource_handle_id_to_type( + done->resource_handle[i]), + req->request_id); + continue; + } + + if (req_isp->fence_map_out[j].sync_id == -1) { + if (ctx_isp->isp_device_type == CAM_IFE_DEVICE_TYPE) + handle_type = + __cam_isp_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle); + else + handle_type = + __cam_isp_tfe_resource_handle_id_to_type( + req_isp->fence_map_out[i].resource_handle); + + CAM_WARN(CAM_ISP, + "Duplicate BUF_DONE for req %lld : i=%d, j=%d, res=%s", + req->request_id, i, j, handle_type); + + trace_cam_log_event("Duplicate BufDone", + handle_type, req->request_id, ctx->ctx_id); + continue; + } + + if (!req_isp->bubble_detected) { + CAM_DBG(CAM_ISP, + "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u", + req->request_id, + req_isp->fence_map_out[j].resource_handle, + req_isp->fence_map_out[j].sync_id, + ctx->ctx_id); + + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS); + if (rc) + CAM_DBG(CAM_ISP, "Sync failed with rc = %d", + rc); + } else if (!req_isp->bubble_report) { + CAM_ERR(CAM_ISP, + "Sync with failure: req %lld res 0x%x fd 0x%x, ctx %u", + req->request_id, + req_isp->fence_map_out[j].resource_handle, + req_isp->fence_map_out[j].sync_id, + ctx->ctx_id); + + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc) + CAM_ERR(CAM_ISP, "Sync failed with rc = %d", + rc); + } else { + /* + * Ignore the buffer done if bubble detect is on + * Increment the ack number here, and queue the + * request back to pending list whenever all the + * buffers are done. + */ + req_isp->num_acked++; + CAM_DBG(CAM_ISP, + "buf done with bubble state %d recovery %d", + bubble_state, req_isp->bubble_report); + continue; + } + + CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x ctx %u", + req->request_id, + req_isp->fence_map_out[j].sync_id, ctx->ctx_id); + if (!rc) { + req_isp->num_acked++; + req_isp->fence_map_out[j].sync_id = -1; + } + + if ((ctx_isp->use_frame_header_ts) && + (req_isp->hw_update_data.frame_header_res_id == + req_isp->fence_map_out[j].resource_handle)) + __cam_isp_ctx_send_sof_timestamp_frame_header( + ctx_isp, + req_isp->hw_update_data.frame_header_cpu_addr, + req->request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); + } + + if (req_isp->num_acked > req_isp->num_fence_map_out) { + /* Should not happen */ + CAM_ERR(CAM_ISP, + "WARNING: req_id %lld num_acked %d > map_out %d, ctx %u", + req->request_id, req_isp->num_acked, + req_isp->num_fence_map_out, ctx->ctx_id); + WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out); + } + + if (req_isp->num_acked != req_isp->num_fence_map_out) + return rc; + + rc = __cam_isp_ctx_handle_buf_done_for_req_list(ctx_isp, req); + return rc; +} + +static int __cam_isp_ctx_handle_buf_done( struct cam_isp_context *ctx_isp, struct cam_isp_hw_done_event_data *done, uint32_t bubble_state) { int rc = 0; - struct cam_ctx_request *req; + struct cam_ctx_request *req; struct cam_context *ctx = ctx_isp->base; struct cam_isp_hw_done_event_data done_next_req; @@ -1063,6 +1202,111 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( return rc; } +static void __cam_isp_ctx_buf_done_match_req( + struct cam_ctx_request *req, + struct cam_isp_hw_done_event_data *done, + bool *irq_delay_detected) +{ + int i, j; + uint32_t match_count = 0; + struct cam_isp_ctx_req *req_isp; + + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + for (i = 0; i < done->num_handles; i++) { + for (j = 0; j < req_isp->num_fence_map_out; j++) { + if ((done->resource_handle[i] == + req_isp->fence_map_out[j].resource_handle) && + (done->last_consumed_addr[i] == + req_isp->fence_map_out[j].image_buf_addr[0])) { + match_count++; + break; + } + } + } + + if (match_count > 0) + *irq_delay_detected = true; + else + *irq_delay_detected = false; + + CAM_DBG(CAM_ISP, + "buf done num handles %d match count %d for next req:%lld", + done->num_handles, match_count, req->request_id); +} + +static int __cam_isp_ctx_handle_buf_done_verify_addr( + struct cam_isp_context *ctx_isp, + struct cam_isp_hw_done_event_data *done, + uint32_t bubble_state) +{ + int rc = 0; + bool irq_delay_detected = false; + struct cam_ctx_request *req; + struct cam_ctx_request *next_req = NULL; + struct cam_context *ctx = ctx_isp->base; + + if (list_empty(&ctx->active_req_list)) { + CAM_DBG(CAM_ISP, "Buf done with no active request"); + return 0; + } + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + + if (ctx_isp->active_req_cnt > 1) { + next_req = list_last_entry( + &ctx->active_req_list, + struct cam_ctx_request, list); + + if (next_req->request_id != req->request_id) + __cam_isp_ctx_buf_done_match_req(next_req, done, + &irq_delay_detected); + else + CAM_WARN(CAM_ISP, + "Req %lld only active request, spurious buf_done rxd", + req->request_id); + } + + /* + * If irq delay isn't detected, then we need to verify + * the consumed address for current req, otherwise, we + * can't verify the consumed address. + */ + rc = __cam_isp_ctx_handle_buf_done_for_request_verify_addr( + ctx_isp, req, done, bubble_state, + !irq_delay_detected); + + /* + * Verify the consumed address for next req all the time, + * since the reported buf done event may belong to current + * req, then we can't signal this event for next req. + */ + if (!rc && irq_delay_detected) + rc = __cam_isp_ctx_handle_buf_done_for_request_verify_addr( + ctx_isp, next_req, done, + bubble_state, true); + + return rc; +} + +static int __cam_isp_ctx_handle_buf_done_in_activated_state( + struct cam_isp_context *ctx_isp, + struct cam_isp_hw_done_event_data *done, + uint32_t bubble_state) +{ + int rc = 0; + + if (ctx_isp->support_consumed_addr) + rc = __cam_isp_ctx_handle_buf_done_verify_addr( + ctx_isp, done, bubble_state); + else + rc = __cam_isp_ctx_handle_buf_done( + ctx_isp, done, bubble_state); + + return rc; +} + static int __cam_isp_ctx_apply_req_offline( void *priv, void *data) { @@ -3663,6 +3907,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; + ctx_isp->support_consumed_addr = false; ctx_isp->req_info.last_bufdone_req_id = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -4340,6 +4585,8 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, */ ctx_isp->custom_enabled = param.custom_enabled; ctx_isp->use_frame_header_ts = param.use_frame_header_ts; + ctx_isp->support_consumed_addr = + param.support_consumed_addr; /* Query the context has rdi only resource */ hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 0847a1d7c9..26cc377c60 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -251,6 +251,7 @@ struct cam_isp_context_event_record { * @split_acquire: Indicate whether a separate acquire is expected * @custom_enabled: Custom HW enabled for this ctx * @use_frame_header_ts: Use frame header for qtimer ts + * @support_consumed_addr: Indicate whether HW has last consumed addr reg * @init_timestamp: Timestamp at which this context is initialized * @isp_device_type: ISP device type * @rxd_epoch: Indicate whether epoch has been received. Used to @@ -294,6 +295,7 @@ struct cam_isp_context { bool split_acquire; bool custom_enabled; bool use_frame_header_ts; + bool support_consumed_addr; unsigned int init_timestamp; uint32_t isp_device_type; atomic_t rxd_epoch; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index edc6d34cfc..c67c5754cc 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2982,6 +2982,32 @@ static int cam_ife_mgr_acquire_get_unified_structure( return 0; } +static bool cam_ife_mgr_is_consumed_addr_supported( + struct cam_ife_hw_mgr_ctx *ctx) +{ + bool support_consumed_addr = false; + struct cam_isp_hw_mgr_res *isp_hw_res = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_hw_res = &ctx->res_list_ife_out[0]; + + if (!isp_hw_res || !isp_hw_res->hw_res[0]) { + CAM_ERR(CAM_ISP, "Invalid ife out res."); + goto end; + } + + hw_intf = isp_hw_res->hw_res[0]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, + &support_consumed_addr, + sizeof(support_consumed_addr)); + } + +end: + return support_consumed_addr; +} + /* entry function: acquire_hw */ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -3144,6 +3170,9 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->internal_cdm = true; atomic_set(&ife_ctx->cdm_done, 1); + acquire_args->support_consumed_addr = + cam_ife_mgr_is_consumed_addr_supported(ife_ctx); + acquire_args->ctxt_to_hw_map = ife_ctx; acquire_args->custom_enabled = ife_ctx->custom_enabled; acquire_args->use_frame_header_ts = @@ -7303,7 +7332,7 @@ static int cam_ife_hw_mgr_handle_hw_epoch( if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; - epoch_done_event_data.frame_id_meta = event_info->th_reg_val; + epoch_done_event_data.frame_id_meta = event_info->reg_val; ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); @@ -7456,6 +7485,8 @@ static int cam_ife_hw_mgr_handle_hw_buf_done( buf_done_event_data.num_handles = 1; buf_done_event_data.resource_handle[0] = event_info->res_id; + buf_done_event_data.last_consumed_addr[0] = + event_info->reg_val; if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) return 0; @@ -7466,8 +7497,9 @@ static int cam_ife_hw_mgr_handle_hw_buf_done( CAM_ISP_HW_EVENT_DONE, &buf_done_event_data); } - CAM_DBG(CAM_ISP, "Buf done for VFE:%d out_res->res_id: 0x%x", - event_info->hw_idx, event_info->res_id); + CAM_DBG(CAM_ISP, + "Buf done for VFE:%d res_id: 0x%x last consumed addr: 0x%x", + event_info->hw_idx, event_info->res_id, event_info->reg_val); return 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 7523c69961..8a26c06e7c 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1733,6 +1733,32 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, } } +static bool cam_tfe_mgr_is_consumed_addr_supported( + struct cam_tfe_hw_mgr_ctx *ctx) +{ + bool support_consumed_addr = false; + struct cam_isp_hw_mgr_res *isp_hw_res = NULL; + struct cam_hw_intf *hw_intf = NULL; + + isp_hw_res = &ctx->res_list_tfe_out[0]; + + if (!isp_hw_res || !isp_hw_res->hw_res[0]) { + CAM_ERR(CAM_ISP, "Invalid ife out res."); + goto end; + } + + hw_intf = isp_hw_res->hw_res[0]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, + CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, + &support_consumed_addr, + sizeof(support_consumed_addr)); + } + +end: + return support_consumed_addr; +} + /* entry function: acquire_hw */ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -1942,6 +1968,9 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) tfe_ctx->ctx_in_use = 1; tfe_ctx->num_reg_dump_buf = 0; + acquire_args->support_consumed_addr = + cam_tfe_mgr_is_consumed_addr_supported(tfe_ctx); + cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx); CAM_DBG(CAM_ISP, "Exit...(success)"); 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 c498233f48..6cad5f6e73 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 @@ -481,6 +481,8 @@ int cam_isp_add_io_buffers( uint32_t i, j, num_out_buf, num_in_buf; uint32_t res_id_out, res_id_in, plane_id; uint32_t io_cfg_used_bytes, num_ent; + uint32_t *image_buf_addr; + uint32_t *image_buf_offset; uint64_t iova_addr; size_t size; int32_t hdl; @@ -696,6 +698,11 @@ int cam_isp_add_io_buffers( wm_update.num_buf = plane_id; wm_update.io_cfg = &io_cfg[i]; wm_update.frame_header = 0; + + for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES; + plane_id++) + wm_update.image_buf_offset[plane_id] = 0; + iova_addr = frame_header_info->frame_header_iova_addr; if ((frame_header_info->frame_header_enable) && !(frame_header_info->frame_header_res_id)) { @@ -728,6 +735,20 @@ int cam_isp_add_io_buffers( return rc; } io_cfg_used_bytes += update_buf.cmd.used_bytes; + + + image_buf_addr = + out_map_entries->image_buf_addr; + image_buf_offset = + wm_update.image_buf_offset; + if (j == CAM_ISP_HW_SPLIT_LEFT) { + for (plane_id = 0; + plane_id < CAM_PACKET_MAX_PLANES; + plane_id++) + image_buf_addr[plane_id] = + io_addr[plane_id] + + image_buf_offset[plane_id]; + } } for (j = 0; j < CAM_ISP_HW_SPLIT_MAX && io_cfg[i].direction == CAM_BUF_INPUT; j++) { diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 61b646a1e4..4243f1aceb 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -179,6 +179,7 @@ struct cam_isp_hw_epoch_event_data { * * @num_handles: Number of resource handeles * @resource_handle: Resource handle array + * @last_consumed_addr: Last consumed addr * @timestamp: Timestamp for the buf done event * */ @@ -186,6 +187,8 @@ struct cam_isp_hw_done_event_data { uint32_t num_handles; uint32_t resource_handle[ CAM_NUM_OUT_PER_COMP_IRQ_MAX]; + uint32_t last_consumed_addr[ + CAM_NUM_OUT_PER_COMP_IRQ_MAX]; uint64_t timestamp; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 22a75b9120..9181fdc2eb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -120,6 +120,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_DUMP_HW, CAM_ISP_HW_CMD_FE_TRIGGER_CMD, CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ, + CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT, CAM_ISP_HW_CMD_MAX, }; @@ -183,7 +184,7 @@ struct cam_isp_resource_node { * @res_id: Unique resource ID * @hw_idx: IFE hw index * @err_type: Error type if any - * @th_reg_val: Any critical register value captured during th + * @reg_val: Any critical register value captured during irq handling * */ struct cam_isp_hw_event_info { @@ -191,7 +192,7 @@ struct cam_isp_hw_event_info { uint32_t res_id; uint32_t hw_idx; uint32_t err_type; - uint32_t th_reg_val; + uint32_t reg_val; }; /* @@ -213,17 +214,19 @@ struct cam_isp_hw_cmd_buf_update { /* * struct cam_isp_hw_get_wm_update: * - * @Brief: Get cmd buffer for WM updates. + * @Brief: Get cmd buffer for WM updates. * - * @ image_buf: image buffer address array - * @ num_buf: Number of buffers in the image_buf array - * @ frame_header: frame header iova - * @ local_id: local id for the wm - * @ io_cfg: IO buffer config information sent from UMD + * @ image_buf: image buffer address array + * @ image_buf_offset: image buffer address offset array + * @ num_buf: Number of buffers in the image_buf array + * @ frame_header: frame header iova + * @ local_id: local id for the wm + * @ io_cfg: IO buffer config information sent from UMD * */ struct cam_isp_hw_get_wm_update { dma_addr_t *image_buf; + uint32_t image_buf_offset[CAM_PACKET_MAX_PLANES]; uint32_t num_buf; uint64_t frame_header; uint32_t local_id; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 41c4564eb3..adb33444cf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -289,15 +289,15 @@ struct cam_vfe_bw_control_args { * @list: list_head node for the payload * @irq_reg_val: IRQ and Error register values, read when IRQ was * handled - * @th_reg_val: Value of any critical register that needs to be - * read at th to avoid any latencies in bh processing + * @reg_val: Value of any critical register that needs to be + * read at during irq handling * * @ts: Timestamp */ struct cam_vfe_top_irq_evt_payload { struct list_head list; uint32_t irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX]; - uint32_t th_reg_val; + uint32_t reg_val; struct cam_isp_timestamp ts; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h index d22836edc9..6be379a393 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h @@ -820,6 +820,7 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { 0xD0000000, 0x00000000, }, + .support_consumed_addr = true, }; struct cam_tfe_hw_info cam_tfe530 = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 01ffb90d74..afa5464afd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -71,6 +71,7 @@ struct cam_tfe_bus_common_data { uint32_t num_sec_out; uint32_t comp_done_shift; bool is_lite; + bool support_consumed_addr; cam_hw_mgr_event_cb_func event_cb; bool rup_irq_enable[CAM_TFE_BUS_RUP_GRP_MAX]; }; @@ -95,6 +96,7 @@ struct cam_tfe_bus_wm_resource_data { uint32_t framedrop_pattern; uint32_t en_cfg; + uint32_t image_addr_offset; uint32_t is_dual; uint32_t acquired_width; @@ -124,6 +126,7 @@ struct cam_tfe_bus_tfe_out_data { uint32_t rup_group_id; uint32_t source_group; struct cam_tfe_bus_common_data *common_data; + struct cam_tfe_bus_priv *bus_priv; uint32_t num_wm; struct cam_isp_resource_node *wm_res[PLANE_MAX]; @@ -1221,6 +1224,7 @@ static int cam_tfe_bus_acquire_tfe_out(void *priv, void *acquire_args, rsrc_data->common_data->event_cb = acq_args->event_cb; rsrc_data->event_cb = acq_args->event_cb; rsrc_data->priv = acq_args->priv; + rsrc_data->bus_priv = bus_priv; secure_caps = cam_tfe_bus_can_be_secure(rsrc_data->out_id); mode = out_acquire_args->out_port_info->secure_mode; @@ -1643,6 +1647,31 @@ static int cam_tfe_bus_rup_bottom_half( return 0; } +static uint32_t cam_tfe_bus_get_last_consumed_addr( + struct cam_tfe_bus_priv *bus_priv, + uint32_t res_id) +{ + uint32_t val = 0; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_tfe_bus_tfe_out_data *rsrc_data = NULL; + struct cam_tfe_bus_wm_resource_data *wm_rsrc_data = NULL; + + if (res_id >= CAM_TFE_BUS_TFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "invalid res id:%u", res_id); + return 0; + } + + rsrc_node = &bus_priv->tfe_out[res_id]; + rsrc_data = rsrc_node->res_priv; + wm_rsrc_data = rsrc_data->wm_res[PLANE_Y]->res_priv; + + val = cam_io_r_mb( + wm_rsrc_data->common_data->mem_base + + wm_rsrc_data->hw_regs->addr_status_0); + + return val; +} + static int cam_tfe_bus_bufdone_bottom_half( struct cam_tfe_bus_priv *bus_priv, struct cam_tfe_irq_evt_payload *evt_payload) @@ -1673,6 +1702,10 @@ static int cam_tfe_bus_bufdone_bottom_half( evt_info.res_type = out_rsrc->res_type; evt_info.hw_idx = out_rsrc->hw_intf->hw_idx; evt_info.res_id = out_rsrc->res_id; + evt_info.reg_val = + cam_tfe_bus_get_last_consumed_addr( + out_rsrc_data->bus_priv, + evt_info.res_id); out_rsrc_data->event_cb(out_rsrc_data->priv, CAM_ISP_HW_EVENT_DONE, (void *)&evt_info); @@ -2117,6 +2150,7 @@ static int cam_tfe_bus_process_cmd(void *priv, struct cam_tfe_bus_priv *bus_priv; int rc = -EINVAL; uint32_t i, val; + bool *support_consumed_addr; if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -2148,6 +2182,12 @@ static int cam_tfe_bus_process_cmd(void *priv, bus_priv->common_data.common_reg->irq_mask[i]); } break; + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + bus_priv = (struct cam_tfe_bus_priv *) priv; + support_consumed_addr = (bool *)cmd_args; + *support_consumed_addr = + bus_priv->common_data.support_consumed_addr; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -2208,6 +2248,8 @@ int cam_tfe_bus_init( bus_priv->common_data.common_reg = &hw_info->common_reg; bus_priv->comp_buf_done_mask = hw_info->comp_buf_done_mask; bus_priv->comp_rup_done_mask = hw_info->comp_rup_done_mask; + bus_priv->common_data.support_consumed_addr = + hw_info->support_consumed_addr; for (i = 0; i < CAM_TFE_BUS_IRQ_REGISTERS_MAX; i++) bus_priv->bus_irq_error_mask[i] = diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h index db34083ede..2b2ca16ab1 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h @@ -180,6 +180,7 @@ struct cam_tfe_bus_tfe_out_hw_info { * @comp_buf_done_mask: Composite buf done bits mask * @comp_rup_done_mask: Reg update done mask * @bus_irq_error_mask: Bus irq error mask bits + * @support_consumed_addr: Indicate if bus support consumed address */ struct cam_tfe_bus_hw_info { struct cam_tfe_bus_reg_offset_common common_reg; @@ -194,6 +195,7 @@ struct cam_tfe_bus_hw_info { uint32_t comp_buf_done_mask; uint32_t comp_rup_done_mask; uint32_t bus_irq_error_mask[CAM_TFE_BUS_IRQ_REGISTERS_MAX]; + bool support_consumed_addr; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 9c82d7cbca..36a87fe310 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -2808,6 +2808,7 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_STRIPE_UPDATE: case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ: case CAM_ISP_HW_CMD_GET_SECURE_MODE: + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: rc = core_info->tfe_bus->hw_ops.process_cmd( core_info->tfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index bcb9263246..8eaca71f1e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -615,6 +615,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_GET_SECURE_MODE: case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: case CAM_ISP_HW_CMD_DUMP_BUS_INFO: + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index d0f85565a9..aa42c874e4 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -860,6 +860,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = { }, }, .top_irq_shift = 9, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe170_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h index 9aa1c05c19..670316b85c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h @@ -828,6 +828,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_150_bus_hw_info = { .max_height = -1, }, }, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe170_150_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h index 111eb486d5..7b7dee78b9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h @@ -1021,6 +1021,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = { }, }, .top_irq_shift = 9, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe175_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index ce0739d386..dd74b028f9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -1136,6 +1136,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = { }, }, .top_irq_shift = 9, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe175_130_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 1d9173a0c7..bda439a4c9 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1314,6 +1314,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = { }, .comp_done_shift = 6, .top_irq_shift = 7, + .support_consumed_addr = true, }; static struct cam_irq_register_set vfe480_bus_rd_irq_reg[1] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h index be6d1ada95..8139744ce8 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_LITE17X_H_ @@ -324,6 +324,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe17x_bus_hw_info = { }, }, .top_irq_shift = 9, + .support_consumed_addr = false, }; static struct cam_vfe_hw_info cam_vfe_lite17x_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h index 09da6810fd..730af4c945 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_LITE48x_H_ @@ -395,6 +395,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = { }, .comp_done_shift = 4, .top_irq_shift = 4, + .support_consumed_addr = true, }; static struct cam_vfe_hw_info cam_vfe_lite48x_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 1771ed7d52..82d0f555fa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -100,6 +100,7 @@ struct cam_vfe_bus_ver2_common_data { uint32_t addr_no_sync; cam_hw_mgr_event_cb_func event_cb; bool hw_init; + bool support_consumed_addr; }; struct cam_vfe_bus_ver2_wm_resource_data { @@ -3583,6 +3584,7 @@ static int cam_vfe_bus_process_cmd( int rc = -EINVAL; struct cam_vfe_bus_ver2_priv *bus_priv; uint32_t top_mask_0 = 0; + bool *support_consumed_addr; if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -3629,6 +3631,12 @@ static int cam_vfe_bus_process_cmd( cam_io_w_mb(top_mask_0, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->top_irq_mask_0); break; + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + bus_priv = (struct cam_vfe_bus_ver2_priv *) priv; + support_consumed_addr = (bool *)cmd_args; + *support_consumed_addr = + bus_priv->common_data.support_consumed_addr; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3691,6 +3699,8 @@ int cam_vfe_bus_ver2_init( bus_priv->common_data.addr_no_sync = CAM_VFE_BUS_ADDR_NO_SYNC_DEFAULT_VAL; bus_priv->common_data.hw_init = false; + bus_priv->common_data.support_consumed_addr = + ver2_hw_info->support_consumed_addr; mutex_init(&bus_priv->common_data.bus_mutex); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h index e611113bed..cfb8dda17d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h @@ -174,11 +174,12 @@ struct cam_vfe_bus_ver2_vfe_out_hw_info { * * @Brief: HW register info for entire Bus * - * @common_reg: Common register details - * @bus_client_reg: Bus client register info - * @comp_reg_grp: Composite group register info - * @vfe_out_hw_info: VFE output capability - * @top_irq_shift: Mask shift for top level BUS WR irq + * @common_reg: Common register details + * @bus_client_reg: Bus client register info + * @comp_reg_grp: Composite group register info + * @vfe_out_hw_info: VFE output capability + * @top_irq_shift: Mask shift for top level BUS WR irq + * @support_consumed_addr: Indicate if bus support consumed address */ struct cam_vfe_bus_ver2_hw_info { struct cam_vfe_bus_ver2_reg_offset_common common_reg; @@ -191,6 +192,7 @@ struct cam_vfe_bus_ver2_hw_info { struct cam_vfe_bus_ver2_vfe_out_hw_info vfe_out_hw_info[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; uint32_t top_irq_shift; + bool support_consumed_addr; }; /* 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 9c0f867990..727febe397 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 @@ -90,6 +90,7 @@ struct cam_vfe_bus_ver3_common_data { uint32_t comp_done_shift; bool is_lite; bool hw_init; + bool support_consumed_addr; cam_hw_mgr_event_cb_func event_cb; int rup_irq_handle[CAM_VFE_BUS_VER3_SRC_GRP_MAX]; }; @@ -157,6 +158,7 @@ struct cam_vfe_bus_ver3_vfe_out_data { uint32_t out_type; uint32_t source_group; struct cam_vfe_bus_ver3_common_data *common_data; + struct cam_vfe_bus_ver3_priv *bus_priv; uint32_t num_wm; struct cam_isp_resource_node *wm_res[PLANE_MAX]; @@ -2186,6 +2188,7 @@ static int cam_vfe_bus_ver3_acquire_vfe_out(void *bus_priv, void *acquire_args, rsrc_data = rsrc_node->res_priv; rsrc_data->common_data->event_cb = acq_args->event_cb; rsrc_data->priv = acq_args->priv; + rsrc_data->bus_priv = ver3_bus_priv; secure_caps = cam_vfe_bus_ver3_can_be_secure( rsrc_data->out_type); @@ -2552,6 +2555,34 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_top_half(uint32_t evt_id, return rc; } +static uint32_t cam_vfe_bus_ver3_get_last_consumed_addr( + struct cam_vfe_bus_ver3_priv *bus_priv, + uint32_t res_type) +{ + uint32_t val = 0; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_rsrc_data = NULL; + enum cam_vfe_bus_ver3_vfe_out_type res_id; + + res_id = cam_vfe_bus_ver3_get_out_res_id(res_type); + + if (res_id >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { + CAM_ERR(CAM_ISP, "invalid res id:%u", res_id); + return 0; + } + + rsrc_node = &bus_priv->vfe_out[res_id]; + rsrc_data = rsrc_node->res_priv; + wm_rsrc_data = rsrc_data->wm_res[PLANE_Y]->res_priv; + + val = cam_io_r_mb( + wm_rsrc_data->common_data->mem_base + + wm_rsrc_data->hw_regs->addr_status_0); + + return val; +} + static int cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half( void *handler_priv, void *evt_payload_priv) @@ -2586,6 +2617,10 @@ static int cam_vfe_bus_ver3_handle_vfe_out_done_bottom_half( rsrc_data->common_data->is_lite); for (i = 0; i < num_out; i++) { evt_info.res_id = out_list[i]; + evt_info.reg_val = + cam_vfe_bus_ver3_get_last_consumed_addr( + rsrc_data->bus_priv, + evt_info.res_id); if (rsrc_data->common_data->event_cb) rsrc_data->common_data->event_cb(ctx, evt_id, (void *)&evt_info); @@ -3110,22 +3145,28 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, /* WM Image address */ for (k = 0; k < loop_size; k++) { - if (wm_data->en_ubwc) + 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); - else if (wm_data->en_cfg & (0x3 << 16)) + 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)); - else + 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]); @@ -3661,6 +3702,7 @@ static int cam_vfe_bus_ver3_process_cmd( int rc = -EINVAL; struct cam_vfe_bus_ver3_priv *bus_priv; uint32_t top_mask_0 = 0; + bool *support_consumed_addr; if (!priv || !cmd_args) { CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments"); @@ -3718,6 +3760,12 @@ static int cam_vfe_bus_ver3_process_cmd( cam_io_w_mb(top_mask_0, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->top_irq_mask_0); break; + case CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT: + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + support_consumed_addr = (bool *)cmd_args; + *support_consumed_addr = + bus_priv->common_data.support_consumed_addr; + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3790,6 +3838,8 @@ int cam_vfe_bus_ver3_init( bus_priv->common_data.hw_init = false; bus_priv->common_data.is_lite = soc_private->is_ife_lite; + bus_priv->common_data.support_consumed_addr = + ver3_hw_info->support_consumed_addr; for (i = 0; i < CAM_VFE_BUS_VER3_SRC_GRP_MAX; i++) bus_priv->common_data.rup_irq_handle[i] = 0; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index f2430c5f2f..7b39c97f45 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -167,12 +167,13 @@ struct cam_vfe_bus_ver3_vfe_out_hw_info { * * @Brief: HW register info for entire Bus * - * @common_reg: Common register details - * @num_client: Total number of write clients - * @bus_client_reg: Bus client register info - * @vfe_out_hw_info: VFE output capability - * @comp_done_shift: Mask shift for comp done mask - * @top_irq_shift: Mask shift for top level BUS WR irq + * @common_reg: Common register details + * @num_client: Total number of write clients + * @bus_client_reg: Bus client register info + * @vfe_out_hw_info: VFE output capability + * @comp_done_shift: Mask shift for comp done mask + * @top_irq_shift: Mask shift for top level BUS WR irq + * @support_consumed_addr: Indicate if bus support consumed address */ struct cam_vfe_bus_ver3_hw_info { struct cam_vfe_bus_ver3_reg_offset_common common_reg; @@ -184,6 +185,7 @@ struct cam_vfe_bus_ver3_hw_info { vfe_out_hw_info[CAM_VFE_BUS_VER3_VFE_OUT_MAX]; uint32_t comp_done_shift; uint32_t top_irq_shift; + bool support_consumed_addr; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index 1f1e12ea57..27fdde7718 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -1272,7 +1272,7 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, } cam_isp_hw_get_timestamp(&evt_payload->ts); - evt_payload->th_reg_val = 0; + evt_payload->reg_val = 0; for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -1282,7 +1282,7 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, & camif_priv->reg_data->epoch0_irq_mask) { if ((camif_priv->common_reg->custom_frame_idx) && (camif_priv->cam_common_cfg.input_mux_sel_pp & 0x3)) - evt_payload->th_reg_val = cam_io_r_mb( + evt_payload->reg_val = cam_io_r_mb( camif_priv->mem_base + camif_priv->common_reg->custom_frame_idx); } @@ -1344,7 +1344,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, evt_info.hw_idx = camif_node->hw_intf->hw_idx; evt_info.res_id = camif_node->res_id; evt_info.res_type = camif_node->res_type; - evt_info.th_reg_val = 0; + evt_info.reg_val = 0; if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->sof_irq_mask) { @@ -1380,7 +1380,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->epoch0_irq_mask) { CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx); - evt_info.th_reg_val = payload->th_reg_val; + evt_info.reg_val = payload->reg_val; camif_priv->epoch_ts.tv_sec = payload->ts.mono_time.tv_sec; camif_priv->epoch_ts.tv_usec =