Loading drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +81 −10 Original line number Diff line number Diff line Loading @@ -1368,12 +1368,56 @@ static int __cam_isp_ctx_flush_req_in_top_state( struct cam_context *ctx, struct cam_req_mgr_flush_request *flush_req) { struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_isp_stop_args stop_isp; struct cam_hw_stop_args stop_args; struct cam_isp_start_args start_isp; int rc = 0; CAM_DBG(CAM_ISP, "try to flush pending list"); spin_lock_bh(&ctx->lock); rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); spin_unlock_bh(&ctx->lock); if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { /* if active and wait list are empty, return */ spin_lock_bh(&ctx->lock); if ((list_empty(&ctx->wait_req_list)) && (list_empty(&ctx->active_req_list))) { spin_unlock_bh(&ctx->lock); CAM_DBG(CAM_ISP, "active and wait list are empty"); goto end; } spin_unlock_bh(&ctx->lock); /* Stop hw first before active list flush */ stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx; stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; stop_isp.stop_only = true; stop_args.args = (void *)&stop_isp; ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, &stop_args); spin_lock_bh(&ctx->lock); CAM_DBG(CAM_ISP, "try to flush wait list"); rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list, flush_req); CAM_DBG(CAM_ISP, "try to flush active list"); rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list, flush_req); spin_unlock_bh(&ctx->lock); /* Start hw */ start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; start_isp.start_only = true; start_isp.hw_config.priv = NULL; rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &start_isp); } end: CAM_DBG(CAM_ISP, "Flush request in top state %d", ctx->state); return rc; Loading Loading @@ -2294,7 +2338,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd) { int rc = 0; struct cam_hw_config_args arg; struct cam_isp_start_args start_isp; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; struct cam_isp_context *ctx_isp = Loading Loading @@ -2323,12 +2367,13 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, goto end; } arg.ctxt_to_hw_map = ctx_isp->hw_ctx; arg.request_id = req->request_id; arg.hw_update_entries = req_isp->cfg; arg.num_hw_update_entries = req_isp->num_cfg; arg.priv = &req_isp->hw_update_data; arg.init_packet = 1; start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; start_isp.hw_config.request_id = req->request_id; start_isp.hw_config.hw_update_entries = req_isp->cfg; start_isp.hw_config.num_hw_update_entries = req_isp->num_cfg; start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; start_isp.start_only = false; ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; Loading @@ -2345,7 +2390,8 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, */ ctx->state = CAM_CTX_ACTIVATED; trace_cam_context_state("ISP", ctx); rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &arg); rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &start_isp); if (rc) { /* HW failure. user need to clean up the resource */ CAM_ERR(CAM_ISP, "Start HW failed"); Loading Loading @@ -2386,6 +2432,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( struct cam_isp_ctx_req *req_isp; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_isp_stop_args stop_isp; /* Mask off all the incoming hardware events */ spin_lock_bh(&ctx->lock); Loading @@ -2396,7 +2443,15 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( /* stop hw first */ if (ctx_isp->hw_ctx) { stop.ctxt_to_hw_map = ctx_isp->hw_ctx; stop.args = stop_cmd; if (stop_cmd) stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; else stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; stop_isp.stop_only = false; stop.args = (void *) &stop_isp; ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, &stop); } Loading @@ -2417,6 +2472,22 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( list_add_tail(&req->list, &ctx->free_req_list); } while (!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_isp = (struct cam_isp_ctx_req *) req->req_priv; CAM_DBG(CAM_ISP, "signal fence in wait list. fence num %d", req_isp->num_fence_map_out); for (i = 0; i < req_isp->num_fence_map_out; i++) if (req_isp->fence_map_out[i].sync_id != -1) { 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); } while (!list_empty(&ctx->active_req_list)) { req = list_first_entry(&ctx->active_req_list, struct cam_ctx_request, list); Loading drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +145 −86 Original line number Diff line number Diff line Loading @@ -284,6 +284,100 @@ static void cam_ife_hw_mgr_deinit_hw_res( } } static int cam_ife_hw_mgr_init_hw( struct cam_ife_hw_mgr_ctx *ctx) { struct cam_ife_hw_mgr_res *hw_mgr_res; int rc = 0, i; CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d", ctx->ctx_index); /* INIT IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)", hw_mgr_res->res_id); return rc; } } CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d", ctx->ctx_index); /* INIT IFE csid */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)", hw_mgr_res->res_id); return rc; } } /* INIT IFE SRC */ CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d", ctx->ctx_index); list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)", hw_mgr_res->res_id); return rc; } } /* INIT IFE OUT */ CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d", ctx->ctx_index); for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)", ctx->res_list_ife_out[i].res_id); return rc; } } return rc; } static void cam_ife_hw_mgr_deinit_hw( struct cam_ife_hw_mgr_ctx *ctx) { struct cam_ife_hw_mgr_res *hw_mgr_res; int i = 0; if (!ctx->init_done) { CAM_WARN(CAM_ISP, "ctx is not in init state"); return; } /* Deinit IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__); cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deinit IFE CSID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__); cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deint IFE MUX(SRC) */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deinit IFE OUT */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]); ctx->init_done = false; } static int cam_ife_hw_mgr_put_res( struct list_head *src_list, struct cam_ife_hw_mgr_res **res) Loading Loading @@ -1917,6 +2011,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) { int rc = 0; struct cam_hw_stop_args *stop_args = stop_hw_args; struct cam_isp_stop_args *stop_isp; struct cam_ife_hw_mgr_res *hw_mgr_res; struct cam_ife_hw_mgr_ctx *ctx; enum cam_ife_csid_halt_cmd csid_halt_type; Loading @@ -1926,6 +2021,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) CAM_ERR(CAM_ISP, "Invalid arguments"); return -EINVAL; } ctx = (struct cam_ife_hw_mgr_ctx *)stop_args->ctxt_to_hw_map; if (!ctx || !ctx->ctx_in_use) { CAM_ERR(CAM_ISP, "Invalid context is used"); Loading @@ -1933,12 +2029,20 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) } CAM_DBG(CAM_ISP, " Enter...ctx id:%d", ctx->ctx_index); stop_isp = (struct cam_isp_stop_args *)stop_args->args; if ((stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_IMMEDIATELY) && (stop_isp->stop_only)) { CAM_ERR(CAM_ISP, "Invalid params hw_stop_cmd:%d stop_only:%d", stop_isp->hw_stop_cmd, stop_isp->stop_only); return -EPERM; } /* Set the csid halt command */ if (!stop_args->args) csid_halt_type = CAM_CSID_HALT_IMMEDIATELY; else if (stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY) csid_halt_type = CAM_CSID_HALT_AT_FRAME_BOUNDARY; else csid_halt_type = CAM_CSID_HALT_IMMEDIATELY; /* Note:stop resource will remove the irq mask from the hardware */ Loading Loading @@ -2014,30 +2118,15 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) ctx->base[i].idx, csid_halt_type); } /* Deinit IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__); cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deinit IFE CSID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__); cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deint IFE MUX(SRC) */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deinit IFE OUT */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]); if (stop_isp->stop_only) goto end; cam_ife_hw_mgr_deinit_hw(ctx); CAM_DBG(CAM_ISP, "Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc); end: mutex_lock(&g_ife_hw_mgr.ctx_mutex); if (!atomic_dec_return(&g_ife_hw_mgr.active_ctx_cnt)) { rc = cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_DISABLE); Loading Loading @@ -2149,19 +2238,20 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args) static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) { int rc = -1; struct cam_hw_config_args *start_args = start_hw_args; struct cam_isp_start_args *start_isp = start_hw_args; struct cam_hw_stop_args stop_args; struct cam_isp_stop_hw_method stop_hw_method; struct cam_isp_stop_args stop_isp; struct cam_ife_hw_mgr_ctx *ctx; struct cam_ife_hw_mgr_res *hw_mgr_res; uint32_t i; if (!hw_mgr_priv || !start_hw_args) { if (!hw_mgr_priv || !start_isp) { CAM_ERR(CAM_ISP, "Invalid arguments"); return -EINVAL; } ctx = (struct cam_ife_hw_mgr_ctx *)start_args->ctxt_to_hw_map; ctx = (struct cam_ife_hw_mgr_ctx *) start_isp->hw_config.ctxt_to_hw_map; if (!ctx || !ctx->ctx_in_use) { CAM_ERR(CAM_ISP, "Invalid context is used"); return -EPERM; Loading @@ -2174,6 +2264,9 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) cam_tasklet_start(ctx->common.tasklet_info); if (ctx->init_done && start_isp->start_only) goto start_only; /* set current csid debug information to CSID HW */ for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { if (g_ife_hw_mgr.csid_devices[i]) Loading @@ -2184,58 +2277,13 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) sizeof(g_ife_hw_mgr.debug_cfg.csid_debug)); } /* INIT IFE Root: do nothing */ CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d", ctx->ctx_index); /* INIT IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)", hw_mgr_res->res_id); goto err; } } CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d", ctx->ctx_index); /* INIT IFE csid */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); rc = cam_ife_hw_mgr_init_hw(ctx); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)", hw_mgr_res->res_id); CAM_ERR(CAM_ISP, "Init failed"); goto err; } } /* INIT IFE SRC */ CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d", ctx->ctx_index); list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)", hw_mgr_res->res_id); goto err; } } /* INIT IFE OUT */ CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d", ctx->ctx_index); for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)", ctx->res_list_ife_out[i].res_id); goto err; } } start_only: mutex_lock(&g_ife_hw_mgr.ctx_mutex); if (!atomic_fetch_inc(&g_ife_hw_mgr.active_ctx_cnt)) { Loading @@ -2256,13 +2304,16 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) goto err; } if (!start_isp->start_only) { /* Apply initial configuration */ CAM_DBG(CAM_ISP, "Config HW"); rc = cam_ife_mgr_config_hw(hw_mgr_priv, start_hw_args); rc = cam_ife_mgr_config_hw(hw_mgr_priv, &start_isp->hw_config); if (rc) { CAM_ERR(CAM_ISP, "Config HW failed"); goto err; } } CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index); Loading Loading @@ -2313,13 +2364,18 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) } } ctx->init_done = true; /* Start IFE root node: do nothing */ CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index); return 0; err: stop_hw_method.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; stop_args.ctxt_to_hw_map = start_args->ctxt_to_hw_map; stop_args.args = (void *)(&stop_hw_method); stop_isp.stop_only = false; stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; stop_args.ctxt_to_hw_map = start_isp->hw_config.ctxt_to_hw_map; stop_args.args = (void *)(&stop_isp); cam_ife_mgr_stop_hw(hw_mgr_priv, &stop_args); CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); return rc; Loading Loading @@ -2358,6 +2414,9 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, CAM_DBG(CAM_ISP, "Enter...ctx id:%d", ctx->ctx_index); if (ctx->init_done) cam_ife_hw_mgr_deinit_hw(ctx); /* we should called the stop hw before this already */ cam_ife_hw_mgr_release_hw_for_ctx(ctx); Loading drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +2 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ struct cam_ife_hw_mgr_debug { * context * @is_rdi_only_context flag to specify the context has only rdi resource * @config_done_complete indicator for configuration complete * @init_done indicate whether init hw is done */ struct cam_ife_hw_mgr_ctx { struct list_head list; Loading Loading @@ -156,6 +157,7 @@ struct cam_ife_hw_mgr_ctx { atomic_t overflow_pending; uint32_t is_rdi_only_context; struct completion config_done_complete; bool init_done; }; /** Loading drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +18 −2 Original line number Diff line number Diff line Loading @@ -60,13 +60,29 @@ enum cam_isp_hw_stop_cmd { }; /** * struct cam_isp_stop_hw_method - hardware stop method * struct cam_isp_stop_args - hardware stop arguments * * @hw_stop_cmd: Hardware stop command type information * @stop_only Send stop only to hw drivers. No Deinit to be * done. * */ struct cam_isp_stop_hw_method { struct cam_isp_stop_args { enum cam_isp_hw_stop_cmd hw_stop_cmd; bool stop_only; }; /** * struct cam_isp_start_args - isp hardware start arguments * * @config_args: Hardware configuration commands. * @start_only Send start only to hw drivers. No init to * be done. * */ struct cam_isp_start_args { struct cam_hw_config_args hw_config; bool start_only; }; /** Loading drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +4 −1 Original line number Diff line number Diff line Loading @@ -1250,7 +1250,10 @@ static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res) struct cam_vfe_bus_ver2_common_data *common_data = rsrc_data->common_data; /* disable WM */ /* Disable WM */ cam_io_w_mb(0x0, common_data->mem_base + rsrc_data->hw_regs->cfg); /* Disable all register access, reply on global reset */ CAM_DBG(CAM_ISP, "WM res %d irq_enabled %d", rsrc_data->index, rsrc_data->irq_enabled); Loading Loading
drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +81 −10 Original line number Diff line number Diff line Loading @@ -1368,12 +1368,56 @@ static int __cam_isp_ctx_flush_req_in_top_state( struct cam_context *ctx, struct cam_req_mgr_flush_request *flush_req) { struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_isp_stop_args stop_isp; struct cam_hw_stop_args stop_args; struct cam_isp_start_args start_isp; int rc = 0; CAM_DBG(CAM_ISP, "try to flush pending list"); spin_lock_bh(&ctx->lock); rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); spin_unlock_bh(&ctx->lock); if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { /* if active and wait list are empty, return */ spin_lock_bh(&ctx->lock); if ((list_empty(&ctx->wait_req_list)) && (list_empty(&ctx->active_req_list))) { spin_unlock_bh(&ctx->lock); CAM_DBG(CAM_ISP, "active and wait list are empty"); goto end; } spin_unlock_bh(&ctx->lock); /* Stop hw first before active list flush */ stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx; stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; stop_isp.stop_only = true; stop_args.args = (void *)&stop_isp; ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, &stop_args); spin_lock_bh(&ctx->lock); CAM_DBG(CAM_ISP, "try to flush wait list"); rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list, flush_req); CAM_DBG(CAM_ISP, "try to flush active list"); rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list, flush_req); spin_unlock_bh(&ctx->lock); /* Start hw */ start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; start_isp.start_only = true; start_isp.hw_config.priv = NULL; rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &start_isp); } end: CAM_DBG(CAM_ISP, "Flush request in top state %d", ctx->state); return rc; Loading Loading @@ -2294,7 +2338,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd) { int rc = 0; struct cam_hw_config_args arg; struct cam_isp_start_args start_isp; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; struct cam_isp_context *ctx_isp = Loading Loading @@ -2323,12 +2367,13 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, goto end; } arg.ctxt_to_hw_map = ctx_isp->hw_ctx; arg.request_id = req->request_id; arg.hw_update_entries = req_isp->cfg; arg.num_hw_update_entries = req_isp->num_cfg; arg.priv = &req_isp->hw_update_data; arg.init_packet = 1; start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; start_isp.hw_config.request_id = req->request_id; start_isp.hw_config.hw_update_entries = req_isp->cfg; start_isp.hw_config.num_hw_update_entries = req_isp->num_cfg; start_isp.hw_config.priv = &req_isp->hw_update_data; start_isp.hw_config.init_packet = 1; start_isp.start_only = false; ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; Loading @@ -2345,7 +2390,8 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, */ ctx->state = CAM_CTX_ACTIVATED; trace_cam_context_state("ISP", ctx); rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &arg); rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &start_isp); if (rc) { /* HW failure. user need to clean up the resource */ CAM_ERR(CAM_ISP, "Start HW failed"); Loading Loading @@ -2386,6 +2432,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( struct cam_isp_ctx_req *req_isp; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_isp_stop_args stop_isp; /* Mask off all the incoming hardware events */ spin_lock_bh(&ctx->lock); Loading @@ -2396,7 +2443,15 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( /* stop hw first */ if (ctx_isp->hw_ctx) { stop.ctxt_to_hw_map = ctx_isp->hw_ctx; stop.args = stop_cmd; if (stop_cmd) stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; else stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; stop_isp.stop_only = false; stop.args = (void *) &stop_isp; ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, &stop); } Loading @@ -2417,6 +2472,22 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( list_add_tail(&req->list, &ctx->free_req_list); } while (!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_isp = (struct cam_isp_ctx_req *) req->req_priv; CAM_DBG(CAM_ISP, "signal fence in wait list. fence num %d", req_isp->num_fence_map_out); for (i = 0; i < req_isp->num_fence_map_out; i++) if (req_isp->fence_map_out[i].sync_id != -1) { 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); } while (!list_empty(&ctx->active_req_list)) { req = list_first_entry(&ctx->active_req_list, struct cam_ctx_request, list); Loading
drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +145 −86 Original line number Diff line number Diff line Loading @@ -284,6 +284,100 @@ static void cam_ife_hw_mgr_deinit_hw_res( } } static int cam_ife_hw_mgr_init_hw( struct cam_ife_hw_mgr_ctx *ctx) { struct cam_ife_hw_mgr_res *hw_mgr_res; int rc = 0, i; CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d", ctx->ctx_index); /* INIT IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)", hw_mgr_res->res_id); return rc; } } CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d", ctx->ctx_index); /* INIT IFE csid */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)", hw_mgr_res->res_id); return rc; } } /* INIT IFE SRC */ CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d", ctx->ctx_index); list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)", hw_mgr_res->res_id); return rc; } } /* INIT IFE OUT */ CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d", ctx->ctx_index); for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)", ctx->res_list_ife_out[i].res_id); return rc; } } return rc; } static void cam_ife_hw_mgr_deinit_hw( struct cam_ife_hw_mgr_ctx *ctx) { struct cam_ife_hw_mgr_res *hw_mgr_res; int i = 0; if (!ctx->init_done) { CAM_WARN(CAM_ISP, "ctx is not in init state"); return; } /* Deinit IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__); cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deinit IFE CSID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__); cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deint IFE MUX(SRC) */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deinit IFE OUT */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]); ctx->init_done = false; } static int cam_ife_hw_mgr_put_res( struct list_head *src_list, struct cam_ife_hw_mgr_res **res) Loading Loading @@ -1917,6 +2011,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) { int rc = 0; struct cam_hw_stop_args *stop_args = stop_hw_args; struct cam_isp_stop_args *stop_isp; struct cam_ife_hw_mgr_res *hw_mgr_res; struct cam_ife_hw_mgr_ctx *ctx; enum cam_ife_csid_halt_cmd csid_halt_type; Loading @@ -1926,6 +2021,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) CAM_ERR(CAM_ISP, "Invalid arguments"); return -EINVAL; } ctx = (struct cam_ife_hw_mgr_ctx *)stop_args->ctxt_to_hw_map; if (!ctx || !ctx->ctx_in_use) { CAM_ERR(CAM_ISP, "Invalid context is used"); Loading @@ -1933,12 +2029,20 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) } CAM_DBG(CAM_ISP, " Enter...ctx id:%d", ctx->ctx_index); stop_isp = (struct cam_isp_stop_args *)stop_args->args; if ((stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_IMMEDIATELY) && (stop_isp->stop_only)) { CAM_ERR(CAM_ISP, "Invalid params hw_stop_cmd:%d stop_only:%d", stop_isp->hw_stop_cmd, stop_isp->stop_only); return -EPERM; } /* Set the csid halt command */ if (!stop_args->args) csid_halt_type = CAM_CSID_HALT_IMMEDIATELY; else if (stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY) csid_halt_type = CAM_CSID_HALT_AT_FRAME_BOUNDARY; else csid_halt_type = CAM_CSID_HALT_IMMEDIATELY; /* Note:stop resource will remove the irq mask from the hardware */ Loading Loading @@ -2014,30 +2118,15 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) ctx->base[i].idx, csid_halt_type); } /* Deinit IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__); cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deinit IFE CSID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__); cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deint IFE MUX(SRC) */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res); } /* Deinit IFE OUT */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]); if (stop_isp->stop_only) goto end; cam_ife_hw_mgr_deinit_hw(ctx); CAM_DBG(CAM_ISP, "Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc); end: mutex_lock(&g_ife_hw_mgr.ctx_mutex); if (!atomic_dec_return(&g_ife_hw_mgr.active_ctx_cnt)) { rc = cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_DISABLE); Loading Loading @@ -2149,19 +2238,20 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args) static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) { int rc = -1; struct cam_hw_config_args *start_args = start_hw_args; struct cam_isp_start_args *start_isp = start_hw_args; struct cam_hw_stop_args stop_args; struct cam_isp_stop_hw_method stop_hw_method; struct cam_isp_stop_args stop_isp; struct cam_ife_hw_mgr_ctx *ctx; struct cam_ife_hw_mgr_res *hw_mgr_res; uint32_t i; if (!hw_mgr_priv || !start_hw_args) { if (!hw_mgr_priv || !start_isp) { CAM_ERR(CAM_ISP, "Invalid arguments"); return -EINVAL; } ctx = (struct cam_ife_hw_mgr_ctx *)start_args->ctxt_to_hw_map; ctx = (struct cam_ife_hw_mgr_ctx *) start_isp->hw_config.ctxt_to_hw_map; if (!ctx || !ctx->ctx_in_use) { CAM_ERR(CAM_ISP, "Invalid context is used"); return -EPERM; Loading @@ -2174,6 +2264,9 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) cam_tasklet_start(ctx->common.tasklet_info); if (ctx->init_done && start_isp->start_only) goto start_only; /* set current csid debug information to CSID HW */ for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { if (g_ife_hw_mgr.csid_devices[i]) Loading @@ -2184,58 +2277,13 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) sizeof(g_ife_hw_mgr.debug_cfg.csid_debug)); } /* INIT IFE Root: do nothing */ CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d", ctx->ctx_index); /* INIT IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)", hw_mgr_res->res_id); goto err; } } CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d", ctx->ctx_index); /* INIT IFE csid */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); rc = cam_ife_hw_mgr_init_hw(ctx); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)", hw_mgr_res->res_id); CAM_ERR(CAM_ISP, "Init failed"); goto err; } } /* INIT IFE SRC */ CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d", ctx->ctx_index); list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)", hw_mgr_res->res_id); goto err; } } /* INIT IFE OUT */ CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d", ctx->ctx_index); for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]); if (rc) { CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)", ctx->res_list_ife_out[i].res_id); goto err; } } start_only: mutex_lock(&g_ife_hw_mgr.ctx_mutex); if (!atomic_fetch_inc(&g_ife_hw_mgr.active_ctx_cnt)) { Loading @@ -2256,13 +2304,16 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) goto err; } if (!start_isp->start_only) { /* Apply initial configuration */ CAM_DBG(CAM_ISP, "Config HW"); rc = cam_ife_mgr_config_hw(hw_mgr_priv, start_hw_args); rc = cam_ife_mgr_config_hw(hw_mgr_priv, &start_isp->hw_config); if (rc) { CAM_ERR(CAM_ISP, "Config HW failed"); goto err; } } CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index); Loading Loading @@ -2313,13 +2364,18 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) } } ctx->init_done = true; /* Start IFE root node: do nothing */ CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index); return 0; err: stop_hw_method.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; stop_args.ctxt_to_hw_map = start_args->ctxt_to_hw_map; stop_args.args = (void *)(&stop_hw_method); stop_isp.stop_only = false; stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY; stop_args.ctxt_to_hw_map = start_isp->hw_config.ctxt_to_hw_map; stop_args.args = (void *)(&stop_isp); cam_ife_mgr_stop_hw(hw_mgr_priv, &stop_args); CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc); return rc; Loading Loading @@ -2358,6 +2414,9 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, CAM_DBG(CAM_ISP, "Enter...ctx id:%d", ctx->ctx_index); if (ctx->init_done) cam_ife_hw_mgr_deinit_hw(ctx); /* we should called the stop hw before this already */ cam_ife_hw_mgr_release_hw_for_ctx(ctx); Loading
drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +2 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ struct cam_ife_hw_mgr_debug { * context * @is_rdi_only_context flag to specify the context has only rdi resource * @config_done_complete indicator for configuration complete * @init_done indicate whether init hw is done */ struct cam_ife_hw_mgr_ctx { struct list_head list; Loading Loading @@ -156,6 +157,7 @@ struct cam_ife_hw_mgr_ctx { atomic_t overflow_pending; uint32_t is_rdi_only_context; struct completion config_done_complete; bool init_done; }; /** Loading
drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +18 −2 Original line number Diff line number Diff line Loading @@ -60,13 +60,29 @@ enum cam_isp_hw_stop_cmd { }; /** * struct cam_isp_stop_hw_method - hardware stop method * struct cam_isp_stop_args - hardware stop arguments * * @hw_stop_cmd: Hardware stop command type information * @stop_only Send stop only to hw drivers. No Deinit to be * done. * */ struct cam_isp_stop_hw_method { struct cam_isp_stop_args { enum cam_isp_hw_stop_cmd hw_stop_cmd; bool stop_only; }; /** * struct cam_isp_start_args - isp hardware start arguments * * @config_args: Hardware configuration commands. * @start_only Send start only to hw drivers. No init to * be done. * */ struct cam_isp_start_args { struct cam_hw_config_args hw_config; bool start_only; }; /** Loading
drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +4 −1 Original line number Diff line number Diff line Loading @@ -1250,7 +1250,10 @@ static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res) struct cam_vfe_bus_ver2_common_data *common_data = rsrc_data->common_data; /* disable WM */ /* Disable WM */ cam_io_w_mb(0x0, common_data->mem_base + rsrc_data->hw_regs->cfg); /* Disable all register access, reply on global reset */ CAM_DBG(CAM_ISP, "WM res %d irq_enabled %d", rsrc_data->index, rsrc_data->irq_enabled); Loading