Loading drivers/cam_cust/cam_custom_context.c +171 −56 Original line number Diff line number Diff line // 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. */ #include <linux/debugfs.h> Loading @@ -24,6 +24,10 @@ static const char custom_dev_name[] = "cam-custom"; static int __cam_custom_ctx_handle_irq_in_activated( void *context, uint32_t evt_id, void *evt_data); 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_enqueue_request_in_order( struct cam_context *ctx, struct cam_ctx_request *req) { Loading Loading @@ -131,22 +135,104 @@ static int __cam_custom_ctx_flush_req(struct cam_context *ctx, return 0; } static int __cam_custom_ctx_unlink_in_acquired(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; return 0; } static int __cam_custom_ctx_unlink_in_ready(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; ctx->state = CAM_CTX_ACQUIRED; return 0; } static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, struct cam_req_mgr_device_info *dev_info) { dev_info->dev_hdl = ctx->dev_hdl; strlcpy(dev_info->name, CAM_CUSTOM_DEV_NAME, sizeof(dev_info->name)); dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; return 0; } static int __cam_custom_ctx_flush_req_in_top_state( struct cam_context *ctx, struct cam_req_mgr_flush_request *flush_req) { int rc = 0; struct cam_custom_context *custom_ctx; struct cam_hw_reset_args reset_args; struct cam_hw_stop_args stop_args; struct cam_custom_stop_args custom_stop; custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; CAM_DBG(CAM_CUSTOM, "Flushing pending list"); spin_lock_bh(&ctx->lock); __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); spin_unlock_bh(&ctx->lock); if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { if (ctx->state <= CAM_CTX_READY) { ctx->state = CAM_CTX_ACQUIRED; goto end; } spin_lock_bh(&ctx->lock); ctx->state = CAM_CTX_FLUSHED; spin_unlock_bh(&ctx->lock); CAM_INFO(CAM_CUSTOM, "Last request id to flush is %lld", flush_req->req_id); ctx->last_flush_req = flush_req->req_id; /* stop hw first */ if (ctx->hw_mgr_intf->hw_stop) { custom_stop.stop_only = true; stop_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; stop_args.args = (void *) &custom_stop; rc = ctx->hw_mgr_intf->hw_stop( ctx->hw_mgr_intf->hw_mgr_priv, &stop_args); if (rc) CAM_ERR(CAM_CUSTOM, "HW stop failed in flush rc %d", rc); } spin_lock_bh(&ctx->lock); rc = __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); if (!list_empty(&ctx->wait_req_list)) __cam_custom_ctx_flush_req(ctx, &ctx->wait_req_list, flush_req); if (!list_empty(&ctx->active_req_list)) __cam_custom_ctx_flush_req(ctx, &ctx->active_req_list, flush_req); custom_ctx->active_req_cnt = 0; spin_unlock_bh(&ctx->lock); reset_args.ctxt_to_hw_map = custom_ctx->hw_ctx; rc = ctx->hw_mgr_intf->hw_reset(ctx->hw_mgr_intf->hw_mgr_priv, &reset_args); if (rc) CAM_ERR(CAM_CUSTOM, "Reset HW failed in flush rc %d", rc); custom_ctx->init_received = false; } end: return rc; } Loading @@ -170,16 +256,6 @@ static int __cam_custom_ctx_flush_req_in_ready( return rc; } static int __cam_custom_ctx_unlink_in_ready(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; ctx->state = CAM_CTX_ACQUIRED; return 0; } static int __cam_custom_stop_dev_core( struct cam_context *ctx, struct cam_start_stop_dev_cmd *stop_cmd) { Loading @@ -190,14 +266,17 @@ static int __cam_custom_stop_dev_core( struct cam_ctx_request *req; struct cam_custom_dev_ctx_req *req_custom; struct cam_hw_stop_args stop; struct cam_custom_stop_args custom_stop; if (ctx_custom->hw_ctx) { if ((ctx->state != CAM_CTX_FLUSHED) && (ctx_custom->hw_ctx) && (ctx->hw_mgr_intf->hw_stop)) { custom_stop.stop_only = false; stop.ctxt_to_hw_map = ctx_custom->hw_ctx; stop.args = NULL; if (ctx->hw_mgr_intf->hw_stop) ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, stop.args = (void *) &custom_stop; rc = ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, &stop); if (rc) CAM_ERR(CAM_CUSTOM, "HW stop failed rc %d", rc); } while (!list_empty(&ctx->pending_req_list)) { Loading Loading @@ -752,7 +831,9 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, CAM_ERR(CAM_CUSTOM, "Recevied INIT pkt in wrong state"); } } else { if (ctx->state >= CAM_CTX_READY && ctx->ctx_crm_intf->add_req) { if ((ctx->state != CAM_CTX_FLUSHED) && (ctx->state >= CAM_CTX_READY) && (ctx->ctx_crm_intf->add_req)) { add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; Loading Loading @@ -796,6 +877,44 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, } static int __cam_custom_ctx_config_dev_in_flushed(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { int rc = 0; struct cam_start_stop_dev_cmd start_cmd; struct cam_custom_context *custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; if (!custom_ctx->hw_acquired) { CAM_ERR(CAM_CUSTOM, "HW is not acquired, reject packet"); rc = -EINVAL; goto end; } rc = __cam_custom_ctx_config_dev(ctx, cmd); if (rc) goto end; if (!custom_ctx->init_received) { CAM_WARN(CAM_CUSTOM, "Received update packet in flushed state, skip start"); goto end; } start_cmd.dev_handle = cmd->dev_handle; start_cmd.session_handle = cmd->session_handle; rc = __cam_custom_ctx_start_dev_in_ready(ctx, &start_cmd); if (rc) CAM_ERR(CAM_CUSTOM, "Failed to re-start HW after flush rc: %d", rc); else CAM_INFO(CAM_CUSTOM, "Received init after flush. Re-start HW complete."); end: return rc; } static int __cam_custom_ctx_config_dev_in_acquired(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { Loading Loading @@ -835,32 +954,11 @@ static int __cam_custom_ctx_link_in_acquired(struct cam_context *ctx, return 0; } static int __cam_custom_ctx_unlink_in_acquired(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; return 0; } static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, struct cam_req_mgr_device_info *dev_info) { dev_info->dev_hdl = ctx->dev_hdl; strlcpy(dev_info->name, CAM_CUSTOM_DEV_NAME, sizeof(dev_info->name)); dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; return 0; } static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd) { int rc = 0; struct cam_hw_config_args hw_config; struct cam_custom_start_args custom_start; struct cam_ctx_request *req; struct cam_custom_dev_ctx_req *req_custom; struct cam_custom_context *ctx_custom = Loading Loading @@ -889,16 +987,20 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, goto end; } hw_config.ctxt_to_hw_map = ctx_custom->hw_ctx; hw_config.request_id = req->request_id; hw_config.hw_update_entries = req_custom->cfg; hw_config.num_hw_update_entries = req_custom->num_cfg; hw_config.priv = &req_custom->hw_update_data; hw_config.init_packet = 1; custom_start.hw_config.ctxt_to_hw_map = ctx_custom->hw_ctx; custom_start.hw_config.request_id = req->request_id; custom_start.hw_config.hw_update_entries = req_custom->cfg; custom_start.hw_config.num_hw_update_entries = req_custom->num_cfg; custom_start.hw_config.priv = &req_custom->hw_update_data; custom_start.hw_config.init_packet = 1; if (ctx->state == CAM_CTX_FLUSHED) custom_start.start_only = true; else custom_start.start_only = false; ctx->state = CAM_CTX_ACTIVATED; rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &hw_config); &custom_start); if (rc) { /* HW failure. User need to clean up the resource */ CAM_ERR(CAM_CUSTOM, "Start HW failed"); Loading Loading @@ -1064,7 +1166,20 @@ static struct cam_ctx_ops .pagefault_ops = NULL, }, /* Flushed */ {}, { .ioctl_ops = { .stop_dev = __cam_custom_stop_dev_in_activated, .release_dev = __cam_custom_ctx_release_dev_in_activated, .config_dev = __cam_custom_ctx_config_dev_in_flushed, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, }, .irq_ops = NULL, }, /* Activated */ { .ioctl_ops = { Loading drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +97 −2 Original line number Diff line number Diff line // 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. */ #include <linux/slab.h> Loading Loading @@ -220,6 +220,7 @@ static int cam_custom_hw_mgr_stop_hw_res( static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) { int rc = 0; struct cam_custom_stop_args *custom_args; struct cam_hw_stop_args *stop_args = stop_hw_args; struct cam_custom_hw_mgr_res *hw_mgr_res; struct cam_custom_hw_mgr_ctx *ctx; Loading @@ -229,6 +230,7 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) return -EINVAL; } custom_args = (struct cam_custom_stop_args *)stop_args->args; ctx = (struct cam_custom_hw_mgr_ctx *) stop_args->ctxt_to_hw_map; Loading Loading @@ -261,6 +263,9 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) /* stop custom hw here */ if (custom_args->stop_only) goto end; /* Deinit custom cid here */ list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_cid, list) { Loading @@ -282,6 +287,7 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) /* deinit custom rsrc */ end: return rc; } Loading Loading @@ -357,13 +363,19 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, struct cam_hw_stop_args stop_args; struct cam_custom_hw_mgr_res *hw_mgr_res; struct cam_custom_hw_mgr_ctx *ctx; struct cam_custom_stop_args custom_stop_args; struct cam_custom_start_args *custom_args; if (!hw_mgr_priv || !start_hw_args) { CAM_ERR(CAM_CUSTOM, "Invalid arguments"); return -EINVAL; } hw_config = (struct cam_hw_config_args *)start_hw_args; custom_args = (struct cam_custom_start_args *)start_hw_args; hw_config = (struct cam_hw_config_args *) &custom_args->hw_config; ctx = (struct cam_custom_hw_mgr_ctx *) hw_config->ctxt_to_hw_map; Loading @@ -375,6 +387,9 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, CAM_DBG(CAM_CUSTOM, "Enter... ctx id:%d", ctx->ctx_index); if (custom_args->start_only) goto start_only; /* Init custom cid */ list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_cid, list) { Loading Loading @@ -402,6 +417,8 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, /* Apply init config */ start_only: /* Start custom HW first */ if (rc < 0) goto err; Loading Loading @@ -432,6 +449,8 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, return 0; err: custom_stop_args.stop_only = false; stop_args.args = (void *) &custom_stop_args; stop_args.ctxt_to_hw_map = hw_config->ctxt_to_hw_map; cam_custom_mgr_stop_hw(hw_mgr_priv, &stop_args); deinit_hw: Loading Loading @@ -1113,6 +1132,81 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv, return 0; } static int cam_custom_hw_mgr_reset_csid_res( struct cam_custom_hw_mgr_res *hw_mgr_res) { int rc = -1; struct cam_csid_reset_cfg_args csid_reset_args; struct cam_isp_resource_node *custom_rsrc_node = NULL; struct cam_hw_intf *hw_intf = NULL; custom_rsrc_node = (struct cam_isp_resource_node *)hw_mgr_res->rsrc_node; if (!custom_rsrc_node) { CAM_ERR(CAM_CUSTOM, "Invalid args"); return -EINVAL; } csid_reset_args.reset_type = CAM_IFE_CSID_RESET_PATH; csid_reset_args.node_res = custom_rsrc_node; hw_intf = custom_rsrc_node->hw_intf; if (hw_intf->hw_ops.reset) { CAM_DBG(CAM_CUSTOM, "RESET HW for res_id:%u", hw_mgr_res->res_id); rc = hw_intf->hw_ops.reset(hw_intf->hw_priv, &csid_reset_args, sizeof(struct cam_csid_reset_cfg_args)); if (rc) goto err; } return 0; err: CAM_ERR(CAM_CUSTOM, "RESET HW failed for res_id:%u", hw_mgr_res->res_id); return rc; } static int cam_custom_hw_mgr_reset( void *hw_mgr_priv, void *hw_reset_args) { struct cam_hw_reset_args *reset_args = hw_reset_args; struct cam_custom_hw_mgr_ctx *ctx; struct cam_custom_hw_mgr_res *hw_mgr_res; int rc = 0; if (!hw_mgr_priv || !hw_reset_args) { CAM_ERR(CAM_CUSTOM, "Invalid arguments"); return -EINVAL; } ctx = (struct cam_custom_hw_mgr_ctx *) reset_args->ctxt_to_hw_map; if (!ctx || !ctx->ctx_in_use) { CAM_ERR(CAM_CUSTOM, "Invalid context is used"); return -EPERM; } CAM_DBG(CAM_CUSTOM, "Reset SBI CSID and SBI core"); list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_csid, list) { rc = cam_custom_hw_mgr_reset_csid_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_CUSTOM, "Failed to reset CSID:%d rc: %d", hw_mgr_res->res_id, rc); goto end; } } /* Reset SBI HW */ end: return rc; } static int cam_custom_mgr_config_hw(void *hw_mgr_priv, void *hw_config_args) { Loading Loading @@ -1279,6 +1373,7 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, hw_mgr_intf->hw_release = cam_custom_mgr_release_hw; hw_mgr_intf->hw_prepare_update = cam_custom_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_custom_mgr_config_hw; hw_mgr_intf->hw_reset = cam_custom_hw_mgr_reset; if (iommu_hdl) *iommu_hdl = g_custom_hw_mgr.img_iommu_hdl; Loading Loading
drivers/cam_cust/cam_custom_context.c +171 −56 Original line number Diff line number Diff line // 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. */ #include <linux/debugfs.h> Loading @@ -24,6 +24,10 @@ static const char custom_dev_name[] = "cam-custom"; static int __cam_custom_ctx_handle_irq_in_activated( void *context, uint32_t evt_id, void *evt_data); 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_enqueue_request_in_order( struct cam_context *ctx, struct cam_ctx_request *req) { Loading Loading @@ -131,22 +135,104 @@ static int __cam_custom_ctx_flush_req(struct cam_context *ctx, return 0; } static int __cam_custom_ctx_unlink_in_acquired(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; return 0; } static int __cam_custom_ctx_unlink_in_ready(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; ctx->state = CAM_CTX_ACQUIRED; return 0; } static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, struct cam_req_mgr_device_info *dev_info) { dev_info->dev_hdl = ctx->dev_hdl; strlcpy(dev_info->name, CAM_CUSTOM_DEV_NAME, sizeof(dev_info->name)); dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; return 0; } static int __cam_custom_ctx_flush_req_in_top_state( struct cam_context *ctx, struct cam_req_mgr_flush_request *flush_req) { int rc = 0; struct cam_custom_context *custom_ctx; struct cam_hw_reset_args reset_args; struct cam_hw_stop_args stop_args; struct cam_custom_stop_args custom_stop; custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; CAM_DBG(CAM_CUSTOM, "Flushing pending list"); spin_lock_bh(&ctx->lock); __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); spin_unlock_bh(&ctx->lock); if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { if (ctx->state <= CAM_CTX_READY) { ctx->state = CAM_CTX_ACQUIRED; goto end; } spin_lock_bh(&ctx->lock); ctx->state = CAM_CTX_FLUSHED; spin_unlock_bh(&ctx->lock); CAM_INFO(CAM_CUSTOM, "Last request id to flush is %lld", flush_req->req_id); ctx->last_flush_req = flush_req->req_id; /* stop hw first */ if (ctx->hw_mgr_intf->hw_stop) { custom_stop.stop_only = true; stop_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; stop_args.args = (void *) &custom_stop; rc = ctx->hw_mgr_intf->hw_stop( ctx->hw_mgr_intf->hw_mgr_priv, &stop_args); if (rc) CAM_ERR(CAM_CUSTOM, "HW stop failed in flush rc %d", rc); } spin_lock_bh(&ctx->lock); rc = __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); if (!list_empty(&ctx->wait_req_list)) __cam_custom_ctx_flush_req(ctx, &ctx->wait_req_list, flush_req); if (!list_empty(&ctx->active_req_list)) __cam_custom_ctx_flush_req(ctx, &ctx->active_req_list, flush_req); custom_ctx->active_req_cnt = 0; spin_unlock_bh(&ctx->lock); reset_args.ctxt_to_hw_map = custom_ctx->hw_ctx; rc = ctx->hw_mgr_intf->hw_reset(ctx->hw_mgr_intf->hw_mgr_priv, &reset_args); if (rc) CAM_ERR(CAM_CUSTOM, "Reset HW failed in flush rc %d", rc); custom_ctx->init_received = false; } end: return rc; } Loading @@ -170,16 +256,6 @@ static int __cam_custom_ctx_flush_req_in_ready( return rc; } static int __cam_custom_ctx_unlink_in_ready(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; ctx->state = CAM_CTX_ACQUIRED; return 0; } static int __cam_custom_stop_dev_core( struct cam_context *ctx, struct cam_start_stop_dev_cmd *stop_cmd) { Loading @@ -190,14 +266,17 @@ static int __cam_custom_stop_dev_core( struct cam_ctx_request *req; struct cam_custom_dev_ctx_req *req_custom; struct cam_hw_stop_args stop; struct cam_custom_stop_args custom_stop; if (ctx_custom->hw_ctx) { if ((ctx->state != CAM_CTX_FLUSHED) && (ctx_custom->hw_ctx) && (ctx->hw_mgr_intf->hw_stop)) { custom_stop.stop_only = false; stop.ctxt_to_hw_map = ctx_custom->hw_ctx; stop.args = NULL; if (ctx->hw_mgr_intf->hw_stop) ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, stop.args = (void *) &custom_stop; rc = ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, &stop); if (rc) CAM_ERR(CAM_CUSTOM, "HW stop failed rc %d", rc); } while (!list_empty(&ctx->pending_req_list)) { Loading Loading @@ -752,7 +831,9 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, CAM_ERR(CAM_CUSTOM, "Recevied INIT pkt in wrong state"); } } else { if (ctx->state >= CAM_CTX_READY && ctx->ctx_crm_intf->add_req) { if ((ctx->state != CAM_CTX_FLUSHED) && (ctx->state >= CAM_CTX_READY) && (ctx->ctx_crm_intf->add_req)) { add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; Loading Loading @@ -796,6 +877,44 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, } static int __cam_custom_ctx_config_dev_in_flushed(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { int rc = 0; struct cam_start_stop_dev_cmd start_cmd; struct cam_custom_context *custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; if (!custom_ctx->hw_acquired) { CAM_ERR(CAM_CUSTOM, "HW is not acquired, reject packet"); rc = -EINVAL; goto end; } rc = __cam_custom_ctx_config_dev(ctx, cmd); if (rc) goto end; if (!custom_ctx->init_received) { CAM_WARN(CAM_CUSTOM, "Received update packet in flushed state, skip start"); goto end; } start_cmd.dev_handle = cmd->dev_handle; start_cmd.session_handle = cmd->session_handle; rc = __cam_custom_ctx_start_dev_in_ready(ctx, &start_cmd); if (rc) CAM_ERR(CAM_CUSTOM, "Failed to re-start HW after flush rc: %d", rc); else CAM_INFO(CAM_CUSTOM, "Received init after flush. Re-start HW complete."); end: return rc; } static int __cam_custom_ctx_config_dev_in_acquired(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { Loading Loading @@ -835,32 +954,11 @@ static int __cam_custom_ctx_link_in_acquired(struct cam_context *ctx, return 0; } static int __cam_custom_ctx_unlink_in_acquired(struct cam_context *ctx, struct cam_req_mgr_core_dev_link_setup *unlink) { ctx->link_hdl = -1; ctx->ctx_crm_intf = NULL; return 0; } static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, struct cam_req_mgr_device_info *dev_info) { dev_info->dev_hdl = ctx->dev_hdl; strlcpy(dev_info->name, CAM_CUSTOM_DEV_NAME, sizeof(dev_info->name)); dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; return 0; } static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd) { int rc = 0; struct cam_hw_config_args hw_config; struct cam_custom_start_args custom_start; struct cam_ctx_request *req; struct cam_custom_dev_ctx_req *req_custom; struct cam_custom_context *ctx_custom = Loading Loading @@ -889,16 +987,20 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, goto end; } hw_config.ctxt_to_hw_map = ctx_custom->hw_ctx; hw_config.request_id = req->request_id; hw_config.hw_update_entries = req_custom->cfg; hw_config.num_hw_update_entries = req_custom->num_cfg; hw_config.priv = &req_custom->hw_update_data; hw_config.init_packet = 1; custom_start.hw_config.ctxt_to_hw_map = ctx_custom->hw_ctx; custom_start.hw_config.request_id = req->request_id; custom_start.hw_config.hw_update_entries = req_custom->cfg; custom_start.hw_config.num_hw_update_entries = req_custom->num_cfg; custom_start.hw_config.priv = &req_custom->hw_update_data; custom_start.hw_config.init_packet = 1; if (ctx->state == CAM_CTX_FLUSHED) custom_start.start_only = true; else custom_start.start_only = false; ctx->state = CAM_CTX_ACTIVATED; rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &hw_config); &custom_start); if (rc) { /* HW failure. User need to clean up the resource */ CAM_ERR(CAM_CUSTOM, "Start HW failed"); Loading Loading @@ -1064,7 +1166,20 @@ static struct cam_ctx_ops .pagefault_ops = NULL, }, /* Flushed */ {}, { .ioctl_ops = { .stop_dev = __cam_custom_stop_dev_in_activated, .release_dev = __cam_custom_ctx_release_dev_in_activated, .config_dev = __cam_custom_ctx_config_dev_in_flushed, .release_hw = __cam_custom_ctx_release_hw_in_activated_state, }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, }, .irq_ops = NULL, }, /* Activated */ { .ioctl_ops = { Loading
drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +97 −2 Original line number Diff line number Diff line // 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. */ #include <linux/slab.h> Loading Loading @@ -220,6 +220,7 @@ static int cam_custom_hw_mgr_stop_hw_res( static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) { int rc = 0; struct cam_custom_stop_args *custom_args; struct cam_hw_stop_args *stop_args = stop_hw_args; struct cam_custom_hw_mgr_res *hw_mgr_res; struct cam_custom_hw_mgr_ctx *ctx; Loading @@ -229,6 +230,7 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) return -EINVAL; } custom_args = (struct cam_custom_stop_args *)stop_args->args; ctx = (struct cam_custom_hw_mgr_ctx *) stop_args->ctxt_to_hw_map; Loading Loading @@ -261,6 +263,9 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) /* stop custom hw here */ if (custom_args->stop_only) goto end; /* Deinit custom cid here */ list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_cid, list) { Loading @@ -282,6 +287,7 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) /* deinit custom rsrc */ end: return rc; } Loading Loading @@ -357,13 +363,19 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, struct cam_hw_stop_args stop_args; struct cam_custom_hw_mgr_res *hw_mgr_res; struct cam_custom_hw_mgr_ctx *ctx; struct cam_custom_stop_args custom_stop_args; struct cam_custom_start_args *custom_args; if (!hw_mgr_priv || !start_hw_args) { CAM_ERR(CAM_CUSTOM, "Invalid arguments"); return -EINVAL; } hw_config = (struct cam_hw_config_args *)start_hw_args; custom_args = (struct cam_custom_start_args *)start_hw_args; hw_config = (struct cam_hw_config_args *) &custom_args->hw_config; ctx = (struct cam_custom_hw_mgr_ctx *) hw_config->ctxt_to_hw_map; Loading @@ -375,6 +387,9 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, CAM_DBG(CAM_CUSTOM, "Enter... ctx id:%d", ctx->ctx_index); if (custom_args->start_only) goto start_only; /* Init custom cid */ list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_cid, list) { Loading Loading @@ -402,6 +417,8 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, /* Apply init config */ start_only: /* Start custom HW first */ if (rc < 0) goto err; Loading Loading @@ -432,6 +449,8 @@ static int cam_custom_mgr_start_hw(void *hw_mgr_priv, return 0; err: custom_stop_args.stop_only = false; stop_args.args = (void *) &custom_stop_args; stop_args.ctxt_to_hw_map = hw_config->ctxt_to_hw_map; cam_custom_mgr_stop_hw(hw_mgr_priv, &stop_args); deinit_hw: Loading Loading @@ -1113,6 +1132,81 @@ static int cam_custom_mgr_prepare_hw_update(void *hw_mgr_priv, return 0; } static int cam_custom_hw_mgr_reset_csid_res( struct cam_custom_hw_mgr_res *hw_mgr_res) { int rc = -1; struct cam_csid_reset_cfg_args csid_reset_args; struct cam_isp_resource_node *custom_rsrc_node = NULL; struct cam_hw_intf *hw_intf = NULL; custom_rsrc_node = (struct cam_isp_resource_node *)hw_mgr_res->rsrc_node; if (!custom_rsrc_node) { CAM_ERR(CAM_CUSTOM, "Invalid args"); return -EINVAL; } csid_reset_args.reset_type = CAM_IFE_CSID_RESET_PATH; csid_reset_args.node_res = custom_rsrc_node; hw_intf = custom_rsrc_node->hw_intf; if (hw_intf->hw_ops.reset) { CAM_DBG(CAM_CUSTOM, "RESET HW for res_id:%u", hw_mgr_res->res_id); rc = hw_intf->hw_ops.reset(hw_intf->hw_priv, &csid_reset_args, sizeof(struct cam_csid_reset_cfg_args)); if (rc) goto err; } return 0; err: CAM_ERR(CAM_CUSTOM, "RESET HW failed for res_id:%u", hw_mgr_res->res_id); return rc; } static int cam_custom_hw_mgr_reset( void *hw_mgr_priv, void *hw_reset_args) { struct cam_hw_reset_args *reset_args = hw_reset_args; struct cam_custom_hw_mgr_ctx *ctx; struct cam_custom_hw_mgr_res *hw_mgr_res; int rc = 0; if (!hw_mgr_priv || !hw_reset_args) { CAM_ERR(CAM_CUSTOM, "Invalid arguments"); return -EINVAL; } ctx = (struct cam_custom_hw_mgr_ctx *) reset_args->ctxt_to_hw_map; if (!ctx || !ctx->ctx_in_use) { CAM_ERR(CAM_CUSTOM, "Invalid context is used"); return -EPERM; } CAM_DBG(CAM_CUSTOM, "Reset SBI CSID and SBI core"); list_for_each_entry(hw_mgr_res, &ctx->res_list_custom_csid, list) { rc = cam_custom_hw_mgr_reset_csid_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_CUSTOM, "Failed to reset CSID:%d rc: %d", hw_mgr_res->res_id, rc); goto end; } } /* Reset SBI HW */ end: return rc; } static int cam_custom_mgr_config_hw(void *hw_mgr_priv, void *hw_config_args) { Loading Loading @@ -1279,6 +1373,7 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, hw_mgr_intf->hw_release = cam_custom_mgr_release_hw; hw_mgr_intf->hw_prepare_update = cam_custom_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_custom_mgr_config_hw; hw_mgr_intf->hw_reset = cam_custom_hw_mgr_reset; if (iommu_hdl) *iommu_hdl = g_custom_hw_mgr.img_iommu_hdl; Loading