From 02af3487fa6bfa41863342822abdcf31fb826e23 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Tue, 22 Oct 2019 14:54:38 -0700 Subject: [PATCH] msm: camera: custom: Add support for SW sync & snapshot Add support to handle SW sync & ZSLSnapshot. Add substate machine and mechanism to handle the lifecycle of requests based on irqs accordingly. CRs-Fixed: 2524308 Change-Id: Ie5ba97d4ae1b38f4b44c2d3935d2882df59fcac6 Signed-off-by: Karthik Anantha Ram --- drivers/cam_cust/cam_custom_context.c | 388 ++++++++++++++++-- drivers/cam_cust/cam_custom_context.h | 56 ++- .../cam_custom_hw1/cam_custom_sub_mod_core.c | 4 +- .../cam_custom_hw1/cam_custom_sub_mod_core.h | 2 + .../cam_custom_hw_mgr/cam_custom_hw_mgr.c | 235 ++++++++--- .../cam_custom_hw_mgr/cam_custom_hw_mgr.h | 4 + .../cam_custom_hw_mgr/include/cam_custom_hw.h | 22 + .../include/cam_custom_hw_mgr_intf.h | 66 ++- 8 files changed, 667 insertions(+), 110 deletions(-) diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index b38b08750c..de9777a8b1 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -27,6 +27,258 @@ static int __cam_custom_ctx_handle_irq_in_activated( static int __cam_custom_ctx_start_dev_in_ready( struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); +static int __cam_custom_ctx_apply_req_in_activated_state( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply, + uint32_t next_state); + +static int __cam_custom_ctx_apply_default_settings( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); + +static int __cam_custom_ctx_apply_req_in_activated( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + rc = __cam_custom_ctx_apply_req_in_activated_state( + ctx, apply, CAM_CUSTOM_CTX_ACTIVATED_APPLIED); + CAM_DBG(CAM_CUSTOM, "new substate %d", custom_ctx->substate_activated); + + if (rc) + CAM_ERR(CAM_CUSTOM, "Apply failed in state %d rc %d", + custom_ctx->substate_activated, rc); + + return rc; +} + +static int __cam_custom_ctx_handle_error( + struct cam_custom_context *custom_ctx, void *evt_data) +{ + /* + * Handle any HW error scenerios here, all the + * requests in all the lists can be signaled error. + * Notify UMD about this error if needed. + */ + + return 0; +} + +static int __cam_custom_ctx_reg_upd_in_sof( + struct cam_custom_context *custom_ctx, void *evt_data) +{ + struct cam_ctx_request *req = NULL; + struct cam_custom_dev_ctx_req *req_custom; + struct cam_context *ctx = custom_ctx->base; + + custom_ctx->frame_id++; + + /* + * This is for the first update before streamon. + * The initial setting will cause the reg_upd in the + * first frame. + */ + if (!list_empty(&ctx->wait_req_list)) { + req = list_first_entry(&ctx->wait_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + if (req_custom->num_fence_map_out == req_custom->num_acked) { + list_add_tail(&req->list, &ctx->free_req_list); + } else { + list_add_tail(&req->list, &ctx->active_req_list); + custom_ctx->active_req_cnt++; + CAM_DBG(CAM_REQ, + "move request %lld to active list(cnt = %d), ctx %u", + req->request_id, custom_ctx->active_req_cnt, + ctx->ctx_id); + } + } + + return 0; +} + +static int __cam_custom_ctx_reg_upd_in_applied_state( + struct cam_custom_context *custom_ctx, void *evt_data) +{ + struct cam_ctx_request *req; + struct cam_context *ctx = custom_ctx->base; + struct cam_custom_dev_ctx_req *req_custom; + + custom_ctx->frame_id++; + if (list_empty(&ctx->wait_req_list)) { + CAM_ERR(CAM_CUSTOM, + "Reg upd ack with no waiting request"); + goto end; + } + req = list_first_entry(&ctx->wait_req_list, + struct cam_ctx_request, list); + list_del_init(&req->list); + + req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; + if (req_custom->num_fence_map_out != 0) { + list_add_tail(&req->list, &ctx->active_req_list); + custom_ctx->active_req_cnt++; + CAM_DBG(CAM_REQ, + "move request %lld to active list(cnt = %d), ctx %u", + req->request_id, custom_ctx->active_req_cnt, + ctx->ctx_id); + } else { + /* no io config, so the request is completed. */ + list_add_tail(&req->list, &ctx->free_req_list); + CAM_DBG(CAM_ISP, + "move active request %lld to free list(cnt = %d), ctx %u", + req->request_id, custom_ctx->active_req_cnt, + ctx->ctx_id); + } + + custom_ctx->substate_activated = CAM_CUSTOM_CTX_ACTIVATED_SOF; + CAM_DBG(CAM_CUSTOM, "next substate %d", custom_ctx->substate_activated); + +end: + return 0; +} + +static int __cam_custom_ctx_frame_done( + struct cam_custom_context *custom_ctx, void *evt_data) +{ + int rc = 0, i, j; + uint64_t frame_done_req_id; + struct cam_ctx_request *req; + struct cam_custom_dev_ctx_req *req_custom; + struct cam_context *ctx = custom_ctx->base; + struct cam_custom_hw_done_event_data *done_data = + (struct cam_custom_hw_done_event_data *)evt_data; + + if (list_empty(&ctx->active_req_list)) { + CAM_DBG(CAM_CUSTOM, "Frame done with no active request"); + return 0; + } + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_custom = req->req_priv; + + for (i = 0; i < done_data->num_handles; i++) { + for (j = 0; j < req_custom->num_fence_map_out; j++) { + if (done_data->resource_handle[i] == + req_custom->fence_map_out[j].resource_handle) + break; + } + + if (j == req_custom->num_fence_map_out) { + CAM_ERR(CAM_CUSTOM, + "Can not find matching rsrc handle 0x%x!", + done_data->resource_handle[i]); + rc = -EINVAL; + continue; + } + + if (req_custom->fence_map_out[j].sync_id == -1) { + CAM_WARN(CAM_CUSTOM, + "Duplicate frame done for req %lld", + req->request_id); + continue; + } + + rc = cam_sync_signal(req_custom->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_SUCCESS); + if (rc) + CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); + + req_custom->num_acked++; + req_custom->fence_map_out[j].sync_id = -1; + } + + if (req_custom->num_acked > req_custom->num_fence_map_out) { + CAM_ERR(CAM_CUSTOM, + "WARNING: req_id %lld num_acked %d > map_out %d, ctx %u", + req->request_id, req_custom->num_acked, + req_custom->num_fence_map_out, ctx->ctx_id); + } + + if (req_custom->num_acked != req_custom->num_fence_map_out) + return rc; + + custom_ctx->active_req_cnt--; + frame_done_req_id = req->request_id; + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + CAM_DBG(CAM_REQ, + "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", + frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); + + return rc; +} + +static struct cam_ctx_ops + cam_custom_ctx_activated_state_machine + [CAM_CUSTOM_CTX_ACTIVATED_MAX] = { + /* SOF */ + { + .ioctl_ops = {}, + .crm_ops = { + .apply_req = __cam_custom_ctx_apply_req_in_activated, + .apply_default = + __cam_custom_ctx_apply_default_settings, + }, + .irq_ops = NULL, + }, + /* APPLIED */ + { + .ioctl_ops = {}, + .crm_ops = { + .apply_req = __cam_custom_ctx_apply_req_in_activated, + .apply_default = + __cam_custom_ctx_apply_default_settings, + }, + .irq_ops = NULL, + }, + /* HW ERROR */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, + /* HALT */ + { + .ioctl_ops = {}, + .crm_ops = {}, + .irq_ops = NULL, + }, +}; + +static struct cam_custom_ctx_irq_ops + cam_custom_ctx_activated_state_machine_irq + [CAM_CUSTOM_CTX_ACTIVATED_MAX] = { + /* SOF */ + { + .irq_ops = { + __cam_custom_ctx_handle_error, + __cam_custom_ctx_reg_upd_in_sof, + __cam_custom_ctx_frame_done, + }, + }, + /* APPLIED */ + { + .irq_ops = { + __cam_custom_ctx_handle_error, + __cam_custom_ctx_reg_upd_in_applied_state, + __cam_custom_ctx_frame_done, + }, + }, + /* HW ERROR */ + { + .irq_ops = { + NULL, + NULL, + NULL, + }, + }, + /* HALT */ + { + }, +}; static int __cam_custom_ctx_enqueue_request_in_order( struct cam_context *ctx, struct cam_ctx_request *req) @@ -484,7 +736,8 @@ static int __cam_custom_ctx_apply_default_settings( } static int __cam_custom_ctx_apply_req_in_activated_state( - struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply, + uint32_t next_state) { int rc = 0; struct cam_ctx_request *req; @@ -499,6 +752,9 @@ static int __cam_custom_ctx_apply_req_in_activated_state( goto end; } + if (!list_empty(&ctx->wait_req_list)) + CAM_WARN(CAM_CUSTOM, "Apply invoked with a req in wait list"); + custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; spin_lock_bh(&ctx->lock); req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, @@ -531,19 +787,10 @@ static int __cam_custom_ctx_apply_req_in_activated_state( "Can not apply the configuration"); } else { spin_lock_bh(&ctx->lock); + custom_ctx->substate_activated = next_state; list_del_init(&req->list); - if (!req->num_out_map_entries) { - list_add_tail(&req->list, &ctx->free_req_list); - spin_unlock_bh(&ctx->lock); - } else { - list_add_tail(&req->list, &ctx->active_req_list); - spin_unlock_bh(&ctx->lock); - /* - * for test purposes only-this should be - * triggered based on irq - */ - __cam_custom_ctx_handle_irq_in_activated(ctx, 0, NULL); - } + list_add_tail(&req->list, &ctx->wait_req_list); + spin_unlock_bh(&ctx->lock); } end: @@ -610,6 +857,10 @@ static int __cam_custom_ctx_acquire_hw_v1( goto free_res; } + ctx_custom->substate_machine_irq = + cam_custom_ctx_activated_state_machine_irq; + ctx_custom->substate_machine = + cam_custom_ctx_activated_state_machine; ctx_custom->hw_ctx = param.ctxt_to_hw_map; ctx_custom->hw_acquired = true; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; @@ -808,7 +1059,9 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, cfg.packet = packet; cfg.ctxt_to_hw_map = ctx_custom->hw_ctx; cfg.out_map_entries = req_custom->fence_map_out; + cfg.max_out_map_entries = CAM_CUSTOM_DEV_CTX_RES_MAX; cfg.in_map_entries = req_custom->fence_map_in; + cfg.max_in_map_entries = CAM_CUSTOM_DEV_CTX_RES_MAX; cfg.priv = &req_custom->hw_update_data; cfg.pf_data = &(req->pf_data); @@ -824,6 +1077,7 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, req_custom->num_fence_map_out = cfg.num_out_map_entries; req_custom->num_fence_map_in = cfg.num_in_map_entries; req_custom->num_acked = 0; + req_custom->hw_update_data.num_cfg = cfg.num_out_map_entries; for (i = 0; i < req_custom->num_fence_map_out; i++) { rc = cam_sync_get_obj_ref(req_custom->fence_map_out[i].sync_id); @@ -1025,6 +1279,13 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, else custom_start.start_only = false; + ctx_custom->frame_id = 0; + ctx_custom->active_req_cnt = 0; + ctx_custom->substate_activated = + (req_custom->num_fence_map_out) ? + CAM_CUSTOM_CTX_ACTIVATED_APPLIED : + CAM_CUSTOM_CTX_ACTIVATED_SOF; + ctx->state = CAM_CTX_ACTIVATED; rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &custom_start); @@ -1040,10 +1301,7 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, spin_lock_bh(&ctx->lock); list_del_init(&req->list); - if (req_custom->num_fence_map_out) - list_add_tail(&req->list, &ctx->active_req_list); - else - list_add_tail(&req->list, &ctx->free_req_list); + list_add_tail(&req->list, &ctx->wait_req_list); spin_unlock_bh(&ctx->lock); end: @@ -1103,20 +1361,28 @@ static int __cam_custom_ctx_process_evt(struct cam_context *ctx, static int __cam_custom_ctx_handle_irq_in_activated(void *context, uint32_t evt_id, void *evt_data) { - int rc; - struct cam_context *ctx = - (struct cam_context *)context; + int rc = 0; + struct cam_custom_ctx_irq_ops *custom_irq_ops = NULL; + struct cam_context *ctx = (struct cam_context *)context; + struct cam_custom_context *ctx_custom = + (struct cam_custom_context *)ctx->ctx_priv; - CAM_DBG(CAM_CUSTOM, "Enter %d", ctx->ctx_id); + spin_lock(&ctx->lock); + CAM_DBG(CAM_CUSTOM, "Enter: State %d, Substate %d, evt id %d", + ctx->state, ctx_custom->substate_activated, evt_id); + custom_irq_ops = &ctx_custom->substate_machine_irq[ + ctx_custom->substate_activated]; + if (custom_irq_ops->irq_ops[evt_id]) + rc = custom_irq_ops->irq_ops[evt_id](ctx_custom, + evt_data); + else + CAM_DBG(CAM_CUSTOM, "No handle function for substate %d", + ctx_custom->substate_activated); - /* - * handle based on different irq's currently - * triggering only buf done if there are fences - */ - rc = cam_context_buf_done_from_hw(ctx, evt_data, 0); - if (rc) - CAM_ERR(CAM_CUSTOM, "Failed in buf done, rc=%d", rc); + CAM_DBG(CAM_CUSTOM, "Exit: State %d Substate %d", + ctx->state, ctx_custom->substate_activated); + spin_unlock(&ctx->lock); return rc; } @@ -1141,6 +1407,67 @@ static int __cam_custom_ctx_acquire_hw_in_acquired( return rc; } +static int __cam_custom_ctx_apply_req(struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_ctx_ops *ctx_ops = NULL; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + CAM_DBG(CAM_CUSTOM, + "Enter: apply req in Substate %d request _id:%lld", + custom_ctx->substate_activated, apply->request_id); + + ctx_ops = &custom_ctx->substate_machine[ + custom_ctx->substate_activated]; + if (ctx_ops->crm_ops.apply_req) { + rc = ctx_ops->crm_ops.apply_req(ctx, apply); + } else { + CAM_WARN_RATE_LIMIT(CAM_CUSTOM, + "No handle function in activated substate %d", + custom_ctx->substate_activated); + rc = -EFAULT; + } + + if (rc) + CAM_WARN_RATE_LIMIT(CAM_CUSTOM, + "Apply failed in active substate %d rc %d", + custom_ctx->substate_activated, rc); + return rc; +} + +static int __cam_custom_ctx_apply_default_req( + struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_ctx_ops *ctx_ops = NULL; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + + CAM_DBG(CAM_CUSTOM, + "Enter: apply req in Substate %d request _id:%lld", + custom_ctx->substate_activated, apply->request_id); + + ctx_ops = &custom_ctx->substate_machine[ + custom_ctx->substate_activated]; + if (ctx_ops->crm_ops.apply_default) { + rc = ctx_ops->crm_ops.apply_default(ctx, apply); + } else { + CAM_WARN_RATE_LIMIT(CAM_CUSTOM, + "No handle function in activated substate %d", + custom_ctx->substate_activated); + rc = -EFAULT; + } + + if (rc) + CAM_WARN_RATE_LIMIT(CAM_CUSTOM, + "Apply default failed in active substate %d rc %d", + custom_ctx->substate_activated, rc); + return rc; +} + /* top state machine */ static struct cam_ctx_ops cam_custom_dev_ctx_top_state_machine[CAM_CTX_STATE_MAX] = { @@ -1219,10 +1546,9 @@ static struct cam_ctx_ops }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, - .apply_req = - __cam_custom_ctx_apply_req_in_activated_state, + .apply_req = __cam_custom_ctx_apply_req, .apply_default = - __cam_custom_ctx_apply_default_settings, + __cam_custom_ctx_apply_default_req, .flush_req = __cam_custom_ctx_flush_req_in_top_state, .process_evt = __cam_custom_ctx_process_evt, }, diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index 723644f7e8..d2bf069b47 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -19,13 +19,39 @@ * output port resource. The current maximum resource number * is 2. */ -#define CAM_CUSTOM_DEV_CTX_RES_MAX 2 +#define CAM_CUSTOM_DEV_CTX_RES_MAX 1 #define CAM_CUSTOM_CTX_CFG_MAX 8 /* forward declaration */ struct cam_custom_context; +/* cam custom context irq handling function type */ +typedef int (*cam_custom_hw_event_cb_func)( + struct cam_custom_context *custom_ctx, void *evt_data); + +/** + * enum cam_custom_ctx_activated_substate - sub states for activated + * + */ +enum cam_custom_ctx_activated_substate { + CAM_CUSTOM_CTX_ACTIVATED_SOF, + CAM_CUSTOM_CTX_ACTIVATED_APPLIED, + CAM_CUSTOM_CTX_ACTIVATED_HW_ERROR, + CAM_CUSTOM_CTX_ACTIVATED_HALT, + CAM_CUSTOM_CTX_ACTIVATED_MAX, +}; + +/** + * struct cam_custom_ctx_irq_ops - Function table for handling IRQ callbacks + * + * @irq_ops: Array of handle function pointers. + * + */ +struct cam_custom_ctx_irq_ops { + cam_custom_hw_event_cb_func irq_ops[CAM_CUSTOM_HW_EVENT_MAX]; +}; + /** * struct cam_custom_dev_ctx_req - Custom context request object * @@ -69,22 +95,28 @@ struct cam_custom_dev_ctx_req { * @active_req_cnt: Counter for the active request * @frame_id: Frame id tracking for the custom context * @hw_acquired: Flag to indicate if HW is acquired for this context + * @substate_actiavted: Current substate for the activated state. + * @substate_machine: Custom substate machine for external interface + * @substate_machine_irq: Custom substate machine for irq handling * @req_base: common request structure * @req_custom: custom request structure * */ struct cam_custom_context { - struct cam_context *base; - struct cam_ctx_ops *state_machine; - uint32_t state; - void *hw_ctx; - bool init_received; - uint32_t subscribe_event; - uint32_t active_req_cnt; - int64_t frame_id; - bool hw_acquired; - struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; - struct cam_custom_dev_ctx_req req_custom[CAM_CTX_REQ_MAX]; + struct cam_context *base; + struct cam_ctx_ops *state_machine; + uint32_t state; + void *hw_ctx; + bool init_received; + uint32_t subscribe_event; + uint32_t active_req_cnt; + int64_t frame_id; + bool hw_acquired; + uint32_t substate_activated; + struct cam_ctx_ops *substate_machine; + struct cam_custom_ctx_irq_ops *substate_machine_irq; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + struct cam_custom_dev_ctx_req req_custom[CAM_CTX_REQ_MAX]; }; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c index 9ac5da2557..96e1d00c92 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.c @@ -283,8 +283,6 @@ irqreturn_t cam_custom_hw_sub_mod_irq(int irq_num, void *data) core_info->device_hw_info->irq_clear); spin_lock(&custom_dev->hw_lock); - cb_args.irq_status = irq_status; - cb_args.req_info = core_info->curr_req; core_info->curr_req = NULL; if (core_info->irq_cb.custom_hw_mgr_cb) core_info->irq_cb.custom_hw_mgr_cb( @@ -315,7 +313,7 @@ int cam_custom_hw_sub_mod_process_cmd(void *hw_priv, uint32_t cmd_type, switch (cmd_type) { case CAM_CUSTOM_SET_IRQ_CB: { struct cam_custom_sub_mod_set_irq_cb *irq_cb = cmd_args; - + /* This can be deprecated */ CAM_DBG(CAM_CUSTOM, "Setting irq cb"); spin_lock_irqsave(&hw->hw_lock, flag); core_info->irq_cb.custom_hw_mgr_cb = irq_cb->custom_hw_mgr_cb; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h index d27d578f6c..88a5ad6619 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw1/cam_custom_sub_mod_core.h @@ -49,6 +49,8 @@ enum cam_custom_hw_resource_type { struct cam_custom_sub_mod_acq { enum cam_custom_hw_resource_type rsrc_type; int32_t acq; + cam_hw_mgr_event_cb_func event_cb; + void *priv; struct cam_custom_resource_node *rsrc_node; }; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index eb42913ea4..91fc1730b0 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -471,6 +471,88 @@ static int cam_custom_mgr_write(void *hw_mgr_priv, void *write_args) return -EPERM; } +static int cam_custom_hw_mgr_notify( + uint32_t evt_id, + struct cam_custom_hw_mgr_ctx *custom_ctx, + struct cam_custom_hw_event_info *evt_info) +{ + int rc = 0; + struct cam_custom_hw_reg_update_event_data reg_upd_data; + struct cam_custom_hw_done_event_data done_evt_data; + struct cam_custom_hw_error_event_data err_evt_data; + + switch (evt_id) { + case CAM_CUSTOM_HW_EVENT_RUP_DONE: + CAM_DBG(CAM_CUSTOM, "Notify RUP for ctx %u", + custom_ctx->ctx_index); + /* fill the evt data struct */ + custom_ctx->event_cb(custom_ctx->cb_priv, + CAM_CUSTOM_HW_EVENT_RUP_DONE, ®_upd_data); + break; + case CAM_CUSTOM_HW_EVENT_RUP_DONE: + CAM_DBG(CAM_CUSTOM, "Notify FRAME DONE for ctx %u", + custom_ctx->ctx_index); + /* fill the evt data struct */ + done_evt_data.num_handles = 1; + done_evt_data.resource_handle = 0; + custom_ctx->event_cb(custom_ctx->cb_priv, + CAM_CUSTOM_HW_EVENT_RUP_DONE, &done_evt_data); + break; + case CAM_CUSTOM_HW_EVENT_RUP_DONE: + CAM_DBG(CAM_CUSTOM, "Notify ERROR for ctx %u", + custom_ctx->ctx_index); + /* fill the evt data struct */ + custom_ctx->event_cb(custom_ctx->cb_priv, + CAM_CUSTOM_HW_EVENT_RUP_DONE, &err_evt_data); + break; + default: + CAM_ERR(CAM_CUSTOM, "Invalid evt_id %u", evt_id); + rc = -EINVAL; + break; + } + + return rc; +} + +static int cam_custom_hw_mgr_evt_handler( + void *priv, uint32_t evt_id, void *hw_evt_info) +{ + int rc = 0; + struct cam_custom_hw_mgr_ctx *custom_ctx = NULL; + struct cam_custom_hw_mgr_ctx *custom_ctx_tmp = NULL; + struct cam_custom_hw_event_info *evt_info = NULL; + struct cam_custom_hw_mgr *hw_mgr = &g_custom_hw_mgr; + bool ctx_found = false; + + if (!hw_evt_info) { + CAM_ERR(CAM_CUSTOM, "invalid evt info"); + return -EINVAL; + } + + CAM_DBG(CAM_CUSTOM, "Invoked for HW Event ID 0x%x", + evt_id); + evt_info = (struct cam_custom_hw_event_info *)hw_evt_info; + + list_for_each_entry_safe(custom_ctx, custom_ctx_tmp, + &hw_mgr->used_ctx_list, list) { + if (custom_ctx->task_type == evt_info->task_type) { + ctx_found = true; + rc = cam_custom_hw_mgr_notify(evt_id, custom_ctx, + evt_info); + if (rc) { + CAM_ERR(CAM_CUSTOM, "Failed to notify"); + return rc; + } + break; + } + } + + if (!ctx_found) + CAM_DBG(CAM_CUSTOM, "Failed to find affected ctx"); + + return rc; +} + static int cam_custom_hw_mgr_put_ctx( struct list_head *src_list, struct cam_custom_hw_mgr_ctx **custom_ctx) @@ -541,7 +623,8 @@ static int cam_custom_hw_mgr_get_res( static enum cam_ife_pix_path_res_id cam_custom_hw_mgr_get_csid_res_type( - uint32_t out_port_type) + uint32_t out_port_type, + struct cam_custom_hw_mgr_ctx *custom_ctx) { enum cam_ife_pix_path_res_id path_id; @@ -553,9 +636,11 @@ static enum cam_ife_pix_path_res_id break; case CAM_CUSTOM_OUT_RES_UDI_1: path_id = CAM_IFE_PIX_PATH_RES_UDI_1; + custom_ctx->task_type = CAM_CUSTOM_EVENT_TASK2; break; case CAM_CUSTOM_OUT_RES_UDI_2: path_id = CAM_IFE_PIX_PATH_RES_UDI_2; + custom_ctx->task_type = CAM_CUSTOM_EVENT_TASK3; break; default: path_id = CAM_IFE_PIX_PATH_RES_MAX; @@ -668,7 +753,7 @@ static int cam_custom_hw_mgr_acquire_csid_res( for (i = 0; i < in_port_info->num_out_res; i++) { out_port = &in_port_info->data[i]; path_res_id = cam_custom_hw_mgr_get_csid_res_type( - out_port->res_type); + out_port->res_type, custom_ctx); if (path_res_id == CAM_IFE_PIX_PATH_RES_MAX) { CAM_WARN(CAM_CUSTOM, "Invalid out port res_type %u", @@ -826,7 +911,9 @@ static int cam_custom_mgr_release_hw(void *hw_mgr_priv, cam_custom_hw_mgr_release_hw_for_ctx(custom_ctx); list_del_init(&custom_ctx->list); + custom_ctx->scratch_buffer_addr = 0; custom_ctx->ctx_in_use = 0; + custom_ctx->task_type = CAM_CUSTOM_EVENT_INVALID; cam_custom_hw_mgr_put_ctx(&g_custom_hw_mgr.free_ctx_list, &custom_ctx); CAM_DBG(CAM_CUSTOM, "Release Exit.."); return rc; @@ -935,6 +1022,8 @@ static int cam_custom_mgr_acquire_hw_for_ctx( if (!hw_intf) continue; + acq.event_cb = cam_custom_hw_mgr_evt_handler; + acq.priv = custom_ctx; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &acq, sizeof(acq)); if (rc) { @@ -1014,6 +1103,7 @@ static int cam_custom_mgr_acquire_hw( } custom_ctx->ctx_in_use = 1; + custom_ctx->scratch_buffer_addr = 0; acquire_args->ctxt_to_hw_map = custom_ctx; cam_custom_hw_mgr_put_ctx(&custom_hw_mgr->used_ctx_list, &custom_ctx); CAM_DBG(CAM_CUSTOM, "Exit...(success)"); @@ -1034,17 +1124,23 @@ static int cam_custom_add_io_buffers( int iommu_hdl, struct cam_hw_prepare_update_args *prepare) { - int rc = 0, i = 0; + int rc = 0, i = 0, num_out_buf = 0; int32_t hdl; uint32_t plane_id; + size_t size; struct cam_buf_io_cfg *io_cfg; + struct cam_hw_fence_map_entry *out_map_entries; + struct cam_custom_prepare_hw_update_data *prepare_hw_data; + bool is_buf_secure; io_cfg = (struct cam_buf_io_cfg *)((uint8_t *) &prepare->packet->payload + prepare->packet->io_configs_offset); + prepare_hw_data = + (struct cam_custom_prepare_hw_update_data *) + prepare->priv; /* Validate hw update entries */ - for (i = 0; i < prepare->packet->num_io_configs; i++) { CAM_DBG(CAM_CUSTOM, "======= io config idx %d ============", i); CAM_DBG(CAM_CUSTOM, @@ -1058,29 +1154,69 @@ static int cam_custom_add_io_buffers( if (io_cfg[i].direction == CAM_BUF_OUTPUT) { CAM_DBG(CAM_CUSTOM, "output fence 0x%x", io_cfg[i].fence); + out_map_entries = + &prepare->out_map_entries[num_out_buf]; + if (num_out_buf < prepare->max_out_map_entries) { + out_map_entries->resource_handle = + io_cfg[i].resource_type; + out_map_entries->sync_id = + io_cfg[i].fence; + num_out_buf++; + } else { + CAM_ERR(CAM_CUSTOM, "out: %d max: %d", + num_out_buf, + prepare->max_out_map_entries); + return -EINVAL; + } } else if (io_cfg[i].direction == CAM_BUF_INPUT) { CAM_DBG(CAM_CUSTOM, "input fence 0x%x", io_cfg[i].fence); + return -EINVAL; } else { CAM_ERR(CAM_CUSTOM, "Invalid io config direction :%d", io_cfg[i].direction); return -EINVAL; } - for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES; - plane_id++) { - if (!io_cfg[i].mem_handle[plane_id]) - continue; + if (io_cfg[i].direction == CAM_BUF_OUTPUT) { + for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES; + plane_id++) { + /* for custom HW it's one plane only */ + if (!io_cfg[i].mem_handle[plane_id]) + continue; - hdl = io_cfg[i].mem_handle[plane_id]; - CAM_DBG(CAM_CUSTOM, "handle 0x%x for plane %d", - hdl, plane_id); - /* Use cam_mem_get_io_buf() to retrieve iova */ + hdl = io_cfg[i].mem_handle[plane_id]; + is_buf_secure = cam_mem_is_secure_buf(hdl); + if (is_buf_secure) { + CAM_ERR(CAM_CUSTOM, + "secure buffer not supported"); + return -EINVAL; + } + + rc = cam_mem_get_io_buf( + io_cfg[i].mem_handle[plane_id], + iommu_hdl, + &prepare_hw_data->io_addr[plane_id], + &size); + if (rc) { + CAM_ERR(CAM_CUSTOM, + "No io addr for plane: %d", + plane_id); + return -EINVAL; + } + + prepare_hw_data->io_addr[plane_id] += + io_cfg[i].offsets[plane_id]; + CAM_DBG(CAM_CUSTOM, + "handle 0x%x for plane %d addr %pK", + hdl, plane_id, + prepare_hw_data->io_addr[plane_id]); + } } - - /* Do other I/O config operations */ } + prepare->num_out_map_entries = num_out_buf; + prepare->num_in_map_entries = 0; return rc; } @@ -1116,6 +1252,10 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv, (prepare->packet->header.op_code & 0xFFF); ctx = (struct cam_custom_hw_mgr_ctx *) prepare->ctxt_to_hw_map; + prepare->num_hw_update_entries = 0; + prepare->num_in_map_entries = 0; + prepare->num_out_map_entries = 0; + /* Test purposes-check the data in cmd buffer */ cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)&prepare->packet->payload + @@ -1130,6 +1270,11 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv, custom_buf_type1->custom_info); } + /* + * Populate scratch buffer addr here based on INIT + */ + ctx->scratch_buffer_addr = 0x0; + prepare_hw_data->num_cfg = 0; cam_custom_add_io_buffers(hw_mgr->img_iommu_hdl, prepare); return 0; } @@ -1218,6 +1363,7 @@ static int cam_custom_mgr_config_hw(void *hw_mgr_priv, struct cam_custom_hw_mgr_res *res; struct cam_hw_config_args *cfg; struct cam_hw_intf *hw_intf = NULL; + struct cam_custom_prepare_hw_update_data *prepare_hw_data; CAM_DBG(CAM_CUSTOM, "Enter"); if (!hw_mgr_priv || !hw_config_args) { @@ -1234,6 +1380,23 @@ static int cam_custom_mgr_config_hw(void *hw_mgr_priv, return -EPERM; } + prepare_hw_data = + (struct cam_custom_prepare_hw_update_data *) + cfg->priv; + for (i = 0; i < prepare_hw_data->num_cfg; i++) { + CAM_DBG(CAM_CUSTOM, "plane %d io_addr %pK", + i, prepare_hw_data->io_addr[i]); + } + + prepare_hw_data = + (struct cam_custom_prepare_hw_update_data *)cfg->priv; + for (i = 0; i < prepare_hw_data->num_cfg; i++) { + CAM_DBG(CAM_CUSTOM, "plane %d io_addr %p cfg %u", i, + prepare_hw_data->io_addr[i], + prepare_hw_data->num_cfg); + /* this will be ZSLBuffer addr */ + } + for (i = 0; i < CAM_CUSTOM_HW_SUB_MOD_MAX; i++) { res = &custom_ctx->sub_hw_list[i]; if (res->hw_res) { @@ -1255,32 +1418,6 @@ static int cam_custom_mgr_config_hw(void *hw_mgr_priv, return rc; } -static int cam_custom_hw_mgr_irq_cb(void *data, - struct cam_custom_hw_cb_args *cb_args) -{ - struct cam_custom_sub_mod_req_to_dev *proc_req; - struct cam_hw_done_event_data evt_data; - struct cam_custom_hw_mgr_ctx *custom_ctx; - uint32_t ctx_idx; - - proc_req = cb_args->req_info; - ctx_idx = proc_req->ctx_idx; - custom_ctx = &g_custom_hw_mgr.ctx_pool[ctx_idx]; - - if (!custom_ctx->ctx_in_use) { - CAM_ERR(CAM_CUSTOM, "ctx %u not in use", ctx_idx); - return 0; - } - - /* Based on irq status notify success/failure */ - - evt_data.request_id = proc_req->req_id; - custom_ctx->event_cb(custom_ctx->cb_priv, - CAM_CUSTOM_EVENT_BUF_DONE, &evt_data); - - return 0; -} - static int cam_custom_mgr_cmd(void *hw_mgr_priv, void *cmd_args) { int rc = 0; @@ -1315,7 +1452,7 @@ static int cam_custom_mgr_cmd(void *hw_mgr_priv, void *cmd_args) switch (custom_hw_cmd_args->cmd_type) { case CAM_CUSTOM_HW_MGR_PROG_DEFAULT_CONFIG: CAM_DBG(CAM_CUSTOM, "configure RUP and scratch buffer"); - /* Handle event accordingly */ + //use custom_ctx->scratch_buffer_addr break; default: CAM_ERR(CAM_CUSTOM, "Invalid HW mgr command:0x%x", @@ -1338,8 +1475,6 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, int rc = 0; int i, j; struct cam_custom_hw_mgr_ctx *ctx_pool; - struct cam_custom_sub_mod_set_irq_cb irq_cb_args; - struct cam_hw_intf *hw_intf = NULL; memset(&g_custom_hw_mgr, 0, sizeof(g_custom_hw_mgr)); mutex_init(&g_custom_hw_mgr.ctx_mutex); @@ -1349,20 +1484,6 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, /* Initialize sub modules */ rc = cam_custom_hw_sub_mod_init( &g_custom_hw_mgr.custom_hw[i], i); - - /* handle in case init fails */ - if (g_custom_hw_mgr.custom_hw[i]) { - hw_intf = g_custom_hw_mgr.custom_hw[i]; - if (hw_intf->hw_ops.process_cmd) { - irq_cb_args.custom_hw_mgr_cb = - cam_custom_hw_mgr_irq_cb; - irq_cb_args.data = - g_custom_hw_mgr.custom_hw[i]->hw_priv; - hw_intf->hw_ops.process_cmd(hw_intf->hw_priv, - CAM_CUSTOM_SET_IRQ_CB, &irq_cb_args, - sizeof(irq_cb_args)); - } - } } for (i = 0; i < CAM_CUSTOM_CSID_HW_MAX; i++) { diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h index 4a9b27be74..bd8a119f25 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.h @@ -75,6 +75,8 @@ struct ctx_base_info { * @num_base: number of valid base data in the base array * @init_done: indicate whether init hw is done * @event_cb: event_cb to ctx + * @scratch_buffer_addr: scratch buffer address + * @task_type: Custom HW task type * @cb_priv: data sent back with event_cb * */ @@ -96,6 +98,8 @@ struct cam_custom_hw_mgr_ctx { uint32_t num_base; bool init_done; cam_hw_event_cb_func event_cb; + uint64_t scratch_buffer_addr; + enum cam_custom_hw_task_type task_type; void *cb_priv; }; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h index c1d6a258cc..33c0ebff77 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw.h @@ -20,6 +20,28 @@ enum cam_custom_hw_resource_state { CAM_CUSTOM_HW_RESOURCE_STATE_STREAMING = 4, }; +enum cam_custom_hw_task_type { + CAM_CUSTOM_EVENT_INVALID, + CAM_CUSTOM_EVENT_TASK1, + CAM_CUSTOM_EVENT_TASK2, + CAM_CUSTOM_EVENT_TASK3, + CAM_CUSTOM_EVENT_MAX, +}; + +/* + * struct cam_custom_hw_event_info: + * + * @Brief: Structure to pass event details to hw mgr + * + * @task_type: Type of CUSTOM HW Task + * @err_type: Error type if any + * + */ +struct cam_custom_hw_event_info { + enum cam_custom_hw_task_type task_type; + uint32_t err_type; +}; + /* * struct cam_custom_resource_node: * diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h index b47ebb5f78..673735d523 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h @@ -13,6 +13,7 @@ #include "cam_hw.h" #include "cam_hw_mgr_intf.h" #include "cam_hw_intf.h" +#include "cam_custom_hw.h" #define CAM_CUSTOM_HW_TYPE_1 1 @@ -22,8 +23,10 @@ #define CAM_CUSTOM_CSID_HW_MAX 1 enum cam_custom_hw_event_type { - CAM_CUSTOM_EVENT_TYPE_ERROR, - CAM_CUSTOM_EVENT_BUF_DONE, + CAM_CUSTOM_HW_EVENT_ERROR, + CAM_CUSTOM_HW_EVENT_RUP_DONE, + CAM_CUSTOM_HW_EVENT_FRAME_DONE, + CAM_CUSTOM_HW_EVENT_MAX }; enum cam_custom_cmd_types { @@ -48,6 +51,52 @@ struct cam_custom_hw_cmd_args { uint32_t reserved; }; +/** + * struct cam_custom_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF + * + * @timestamp: Time stamp for the sof event + * @boot_time: Boot time stamp for the sof event + * + */ +struct cam_custom_hw_sof_event_data { + uint64_t timestamp; + uint64_t boot_time; +}; + +/** + * struct cam_custom_hw_reg_update_event_data - Event payload for + * CAM_HW_EVENT_REG_UPDATE + * + * @timestamp: Time stamp for the reg update event + * + */ +struct cam_custom_hw_reg_update_event_data { + uint64_t timestamp; +}; + +/** + * struct cam_custom_hw_done_event_data - Event payload for CAM_HW_EVENT_DONE + * + * @num_handles: Number of resource handeles + * @resource_handle: Resource handle array + * + */ +struct cam_custom_hw_done_event_data { + uint32_t num_handles; + uint32_t resource_handle[CAM_NUM_OUT_PER_COMP_IRQ_MAX]; +}; + +/** + * struct cam_custom_hw_error_event_data - Event payload for CAM_HW_EVENT_ERROR + * + * @error_type: Error type for the error event + * @timestamp: Timestamp for the error event + */ +struct cam_custom_hw_error_event_data { + uint32_t error_type; + uint64_t timestamp; +}; + /** * struct cam_custom_stop_args - hardware stop arguments * @@ -77,21 +126,24 @@ struct cam_custom_start_args { * @packet_opcode_type: Packet header opcode in the packet header * this opcode defines, packet is init packet or * update packet + * @buffer_addr: IO Buffer address * */ struct cam_custom_prepare_hw_update_data { - uint32_t packet_opcode_type; + uint32_t packet_opcode_type; + uint32_t num_cfg; + uint64_t io_addr[CAM_PACKET_MAX_PLANES]; }; /** * struct cam_custom_hw_cb_args : HW manager callback args * - * @irq_status : irq status - * @req_info : Pointer to the request info associated with the cb + * @res_type : resource type + * @err_type : error type */ struct cam_custom_hw_cb_args { - uint32_t irq_status; - struct cam_custom_sub_mod_req_to_dev *req_info; + uint32_t res_type; + uint32_t err_type; }; /**