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 =