Loading drivers/media/platform/msm/camera/cam_core/cam_context.c +59 −0 Original line number Diff line number Diff line Loading @@ -287,6 +287,36 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx, return rc; } int cam_context_handle_acquire_hw(struct cam_context *ctx, void *args) { int rc; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (!args) { CAM_ERR(CAM_CORE, "Invalid acquire device hw command payload"); return -EINVAL; } mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.acquire_hw) { rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_hw( ctx, args); } else { CAM_ERR(CAM_CORE, "No acquire hw for dev %s, state %d", ctx->dev_name, ctx->state); rc = -EPROTO; } mutex_unlock(&ctx->ctx_mutex); return rc; } int cam_context_handle_release_dev(struct cam_context *ctx, struct cam_release_dev_cmd *cmd) { Loading Loading @@ -316,6 +346,35 @@ int cam_context_handle_release_dev(struct cam_context *ctx, return rc; } int cam_context_handle_release_hw(struct cam_context *ctx, void *args) { int rc; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (!args) { CAM_ERR(CAM_CORE, "Invalid release HW command payload"); return -EINVAL; } mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.release_hw) { rc = ctx->state_machine[ctx->state].ioctl_ops.release_hw( ctx, args); } else { CAM_ERR(CAM_CORE, "No release hw for dev %s, state %d", ctx->dev_name, ctx->state); rc = -EPROTO; } mutex_unlock(&ctx->ctx_mutex); return rc; } int cam_context_handle_flush_dev(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { Loading drivers/media/platform/msm/camera/cam_core/cam_context.h +28 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,8 @@ struct cam_ctx_request { * @start_dev: Function pointer for start device * @stop_dev: Function pointer for stop device * @flush_dev: Function pointer for flush device * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * */ struct cam_ctx_ioctl_ops { Loading @@ -102,6 +104,8 @@ struct cam_ctx_ioctl_ops { struct cam_start_stop_dev_cmd *cmd); int (*flush_dev)(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd); int (*acquire_hw)(struct cam_context *ctx, void *args); int (*release_hw)(struct cam_context *ctx, void *args); }; /** Loading Loading @@ -320,6 +324,18 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd); /** * cam_context_handle_acquire_hw() * * @brief: Handle acquire HW command * * @ctx: Object pointer for cam_context * @cmd: Acquire HW command payload * */ int cam_context_handle_acquire_hw(struct cam_context *ctx, void *cmd); /** * cam_context_handle_release_dev() * Loading @@ -332,6 +348,18 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx, int cam_context_handle_release_dev(struct cam_context *ctx, struct cam_release_dev_cmd *cmd); /** * cam_context_handle_release_hw() * * @brief: Handle release HW command * * @ctx: Object pointer for cam_context * @cmd: Release HW command payload * */ int cam_context_handle_release_hw(struct cam_context *ctx, void *cmd); /** * cam_context_handle_config_dev() * Loading drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h +1 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ struct cam_hw_acquire_args { void *context_data; cam_hw_event_cb_func event_cb; uint32_t num_acq; uint32_t acquire_info_size; uint64_t acquire_info; void *ctxt_to_hw_map; }; Loading drivers/media/platform/msm/camera/cam_core/cam_node.c +170 −0 Original line number Diff line number Diff line Loading @@ -128,6 +128,45 @@ static int __cam_node_handle_acquire_dev(struct cam_node *node, return rc; } static int __cam_node_handle_acquire_hw_v1(struct cam_node *node, struct cam_acquire_hw_cmd_v1 *acquire) { int rc = 0; struct cam_context *ctx = NULL; if (!acquire) return -EINVAL; if (acquire->dev_handle <= 0) { CAM_ERR(CAM_CORE, "Invalid device handle for context"); return -EINVAL; } if (acquire->session_handle <= 0) { CAM_ERR(CAM_CORE, "Invalid session handle for context"); return -EINVAL; } ctx = (struct cam_context *)cam_get_device_priv(acquire->dev_handle); if (!ctx) { CAM_ERR(CAM_CORE, "Can not get context for handle %d", acquire->dev_handle); return -EINVAL; } rc = cam_context_handle_acquire_hw(ctx, acquire); if (rc) { CAM_ERR(CAM_CORE, "Acquire device failed for node %s", node->name); return rc; } CAM_DBG(CAM_CORE, "[%s] Acquire ctx_id %d", node->name, ctx->ctx_id); return 0; } static int __cam_node_handle_start_dev(struct cam_node *node, struct cam_start_stop_dev_cmd *start) { Loading Loading @@ -313,6 +352,43 @@ static int __cam_node_handle_release_dev(struct cam_node *node, return rc; } static int __cam_node_handle_release_hw_v1(struct cam_node *node, struct cam_release_hw_cmd_v1 *release) { int rc = 0; struct cam_context *ctx = NULL; if (!release) return -EINVAL; if (release->dev_handle <= 0) { CAM_ERR(CAM_CORE, "Invalid device handle for context"); return -EINVAL; } if (release->session_handle <= 0) { CAM_ERR(CAM_CORE, "Invalid session handle for context"); return -EINVAL; } ctx = (struct cam_context *)cam_get_device_priv(release->dev_handle); if (!ctx) { CAM_ERR(CAM_CORE, "Can not get context for handle %d node %s", release->dev_handle, node->name); return -EINVAL; } rc = cam_context_handle_release_hw(ctx, release); if (rc) CAM_ERR(CAM_CORE, "context release failed node %s", node->name); CAM_DBG(CAM_CORE, "[%s] Release ctx_id=%d, refcount=%d", node->name, ctx->ctx_id, atomic_read(&(ctx->refcount.refcount.refs))); return rc; } static int __cam_node_crm_get_dev_info(struct cam_req_mgr_device_info *info) { struct cam_context *ctx = NULL; Loading Loading @@ -542,6 +618,56 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) rc = -EFAULT; break; } case CAM_ACQUIRE_HW: { uint32_t api_version; void *acquire_ptr = NULL; size_t acquire_size; if (copy_from_user(&api_version, (void __user *)cmd->handle, sizeof(api_version))) { rc = -EFAULT; break; } if (api_version == 1) { acquire_size = sizeof(struct cam_acquire_hw_cmd_v1); } else { CAM_ERR(CAM_CORE, "Unsupported api version %d", api_version); rc = -EINVAL; break; } acquire_ptr = kzalloc(acquire_size, GFP_KERNEL); if (!acquire_ptr) { CAM_ERR(CAM_CORE, "No memory for acquire HW"); rc = -ENOMEM; break; } if (copy_from_user(acquire_ptr, (void __user *)cmd->handle, acquire_size)) { rc = -EFAULT; goto acquire_kfree; } if (api_version == 1) { rc = __cam_node_handle_acquire_hw_v1(node, acquire_ptr); if (rc) { CAM_ERR(CAM_CORE, "acquire device failed(rc = %d)", rc); goto acquire_kfree; } } if (copy_to_user((void __user *)cmd->handle, acquire_ptr, acquire_size)) rc = -EFAULT; acquire_kfree: kfree(acquire_ptr); break; } case CAM_START_DEV: { struct cam_start_stop_dev_cmd start; Loading Loading @@ -598,6 +724,50 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) } break; } case CAM_RELEASE_HW: { uint32_t api_version; size_t release_size; void *release_ptr = NULL; if (copy_from_user(&api_version, (void __user *)cmd->handle, sizeof(api_version))) { rc = -EFAULT; break; } if (api_version == 1) { release_size = sizeof(struct cam_release_hw_cmd_v1); } else { CAM_ERR(CAM_CORE, "Unsupported api version %d", api_version); rc = -EINVAL; break; } release_ptr = kzalloc(release_size, GFP_KERNEL); if (!release_ptr) { CAM_ERR(CAM_CORE, "No memory for release HW"); rc = -ENOMEM; break; } if (copy_from_user(release_ptr, (void __user *)cmd->handle, release_size)) { rc = -EFAULT; goto release_kfree; } if (api_version == 1) { rc = __cam_node_handle_release_hw_v1(node, release_ptr); if (rc) CAM_ERR(CAM_CORE, "release device failed(rc = %d)", rc); } release_kfree: kfree(release_ptr); break; } case CAM_FLUSH_REQ: { struct cam_flush_dev_cmd flush; Loading drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +247 −8 Original line number Diff line number Diff line Loading @@ -1984,6 +1984,11 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, (struct cam_isp_context *) ctx->ctx_priv; struct cam_req_mgr_flush_request flush_req; if (cmd && ctx_isp->hw_ctx && ctx_isp->split_acquire) { CAM_ERR(CAM_ISP, "ctx expects release HW before release dev"); return rc; } if (ctx_isp->hw_ctx) { rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx; ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, Loading @@ -1998,6 +2003,8 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; /* * Ideally, we should never have any active request here. Loading @@ -2023,6 +2030,54 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, return rc; } static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, void *cmd) { int rc = 0; struct cam_hw_release_args rel_arg; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_req_mgr_flush_request flush_req; if (ctx_isp->hw_ctx) { rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx; ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &rel_arg); ctx_isp->hw_ctx = NULL; } else { CAM_ERR(CAM_ISP, "No hw resources acquired for this ctx"); } ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; /* * Ideally, we should never have any active request here. * But we still add some sanity check code here to help the debug */ if (!list_empty(&ctx->active_req_list)) CAM_WARN(CAM_ISP, "Active list is not empty"); /* Flush all the pending request list */ flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; flush_req.link_hdl = ctx->link_hdl; flush_req.dev_hdl = ctx->dev_hdl; 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); ctx->state = CAM_CTX_ACQUIRED; trace_cam_context_state("ISP", ctx); CAM_DBG(CAM_ISP, "Release device success[%u] next state %d", ctx->ctx_id, ctx->state); return rc; } static int __cam_isp_ctx_config_dev_in_top_state( struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { Loading Loading @@ -2130,6 +2185,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( rc = __cam_isp_ctx_enqueue_init_request(ctx, req); if (rc) CAM_ERR(CAM_ISP, "Enqueue INIT pkt failed"); ctx_isp->init_received = true; } else { rc = -EINVAL; CAM_ERR(CAM_ISP, "Recevied INIT pkt in wrong state"); Loading Loading @@ -2201,6 +2257,12 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, cmd->session_handle, cmd->num_resources, cmd->handle_type, cmd->resource_hdl); if (cmd->num_resources == CAM_API_COMPAT_CONSTANT) { ctx_isp->split_acquire = true; CAM_DBG(CAM_ISP, "Acquire dev handle"); goto get_dev_handle; } if (cmd->num_resources > CAM_ISP_CTX_RES_MAX) { CAM_ERR(CAM_ISP, "Too much resources in the acquire"); rc = -ENOMEM; Loading Loading @@ -2276,8 +2338,15 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context; ctx_isp->hw_ctx = param.ctxt_to_hw_map; ctx_isp->hw_acquired = true; ctx_isp->split_acquire = false; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; kfree(isp_res); isp_res = NULL; get_dev_handle: req_hdl_param.session_hdl = cmd->session_handle; /* bridge is not ready for these flags. so false for now */ req_hdl_param.v4l2_sub_dev_flag = 0; Loading @@ -2296,31 +2365,178 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, /* store session information */ ctx->session_hdl = cmd->session_handle; ctx->state = CAM_CTX_ACQUIRED; trace_cam_context_state("ISP", ctx); CAM_DBG(CAM_ISP, "Acquire success on session_hdl 0x%x num_rsrces %d RDI only %d ctx %u", cmd->session_handle, cmd->num_resources, (isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id); "Acquire success on session_hdl 0x%x num_rsrces %d ctx %u", cmd->session_handle, cmd->num_resources, ctx->ctx_id); return rc; free_hw: release.ctxt_to_hw_map = ctx_isp->hw_ctx; if (ctx_isp->hw_acquired) ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release); ctx_isp->hw_ctx = NULL; ctx_isp->hw_acquired = false; free_res: kfree(isp_res); end: return rc; } static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, void *args) { int rc = 0; struct cam_acquire_hw_cmd_v1 *cmd = (struct cam_acquire_hw_cmd_v1 *)args; struct cam_hw_acquire_args param; struct cam_hw_release_args release; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_hw_cmd_args hw_cmd_args; struct cam_isp_hw_cmd_args isp_hw_cmd_args; struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; if (!ctx->hw_mgr_intf) { CAM_ERR(CAM_ISP, "HW interface is not ready"); rc = -EFAULT; goto end; } CAM_DBG(CAM_ISP, "session_hdl 0x%x, hdl type %d, res %lld", cmd->session_handle, cmd->handle_type, cmd->resource_hdl); /* for now we only support user pointer */ if (cmd->handle_type != 1) { CAM_ERR(CAM_ISP, "Only user pointer is supported"); rc = -EINVAL; goto end; } if (cmd->data_size < sizeof(*acquire_hw_info)) { CAM_ERR(CAM_ISP, "data_size is not a valid value"); goto end; } acquire_hw_info = kzalloc(cmd->data_size, GFP_KERNEL); if (!acquire_hw_info) { rc = -ENOMEM; goto end; } CAM_DBG(CAM_ISP, "start copy resources from user"); if (copy_from_user(acquire_hw_info, (void __user *)cmd->resource_hdl, cmd->data_size)) { rc = -EFAULT; goto free_res; } param.context_data = ctx; param.event_cb = ctx->irq_cb_intf; param.num_acq = CAM_API_COMPAT_CONSTANT; param.acquire_info_size = cmd->data_size; param.acquire_info = (uint64_t) acquire_hw_info; /* call HW manager to reserve the resource */ rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, ¶m); if (rc != 0) { CAM_ERR(CAM_ISP, "Acquire device failed"); goto free_res; } /* Query the context has rdi only resource */ hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map; hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT; hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); if (rc) { CAM_ERR(CAM_ISP, "HW command failed"); goto free_hw; } if (isp_hw_cmd_args.u.is_rdi_only_context) { /* * this context has rdi only resource assign rdi only * state machine */ CAM_DBG(CAM_ISP, "RDI only session Context"); ctx_isp->substate_machine_irq = cam_isp_ctx_rdi_only_activated_state_machine_irq; ctx_isp->substate_machine = cam_isp_ctx_rdi_only_activated_state_machine; } else { CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); ctx_isp->substate_machine_irq = cam_isp_ctx_activated_state_machine_irq; ctx_isp->substate_machine = cam_isp_ctx_activated_state_machine; } ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context; ctx_isp->hw_ctx = param.ctxt_to_hw_map; ctx_isp->hw_acquired = true; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; trace_cam_context_state("ISP", ctx); CAM_DBG(CAM_ISP, "Acquire success on session_hdl 0x%xs RDI only %d ctx %u", ctx->session_hdl, (isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id); kfree(acquire_hw_info); return rc; free_hw: release.ctxt_to_hw_map = ctx_isp->hw_ctx; ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release); ctx_isp->hw_ctx = NULL; ctx_isp->hw_acquired = false; free_res: kfree(isp_res); kfree(acquire_hw_info); end: return rc; } static int __cam_isp_ctx_acquire_hw_in_acquired(struct cam_context *ctx, void *args) { int rc = -EINVAL; uint32_t api_version; if (!ctx || !args) { CAM_ERR(CAM_ISP, "Invalid input pointer"); return rc; } api_version = *((uint32_t *)args); if (api_version == 1) rc = __cam_isp_ctx_acquire_hw_v1(ctx, args); else CAM_ERR(CAM_ISP, "Unsupported api version %d", api_version); return rc; } static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { int rc = 0; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; if (!ctx_isp->hw_acquired) { CAM_ERR(CAM_ISP, "HW is not acquired, reject packet"); return -EINVAL; } rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd); Loading @@ -2347,7 +2563,7 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx, ctx_isp->subscribe_event = link->subscribe_event; /* change state only if we had the init config */ if (!list_empty(&ctx->pending_req_list)) { if (ctx_isp->init_received) { ctx->state = CAM_CTX_READY; trace_cam_context_state("ISP", ctx); } Loading Loading @@ -2568,8 +2784,11 @@ static int __cam_isp_ctx_stop_dev_in_activated(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd) { int rc = 0; struct cam_isp_context *ctx_isp = (struct cam_isp_context *)ctx->ctx_priv; __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, cmd); ctx_isp->init_received = false; ctx->state = CAM_CTX_ACQUIRED; trace_cam_context_state("ISP", ctx); return rc; Loading @@ -2591,6 +2810,22 @@ static int __cam_isp_ctx_release_dev_in_activated(struct cam_context *ctx, return rc; } static int __cam_isp_ctx_release_hw_in_activated(struct cam_context *ctx, void *cmd) { int rc = 0; rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, NULL); if (rc) CAM_ERR(CAM_ISP, "Stop device failed rc=%d", rc); rc = __cam_isp_ctx_release_hw_in_top_state(ctx, cmd); if (rc) CAM_ERR(CAM_ISP, "Release hw failed rc=%d", rc); return rc; } static int __cam_isp_ctx_link_pause(struct cam_context *ctx) { int rc = 0; Loading Loading @@ -2772,8 +3007,10 @@ static struct cam_ctx_ops /* Acquired */ { .ioctl_ops = { .acquire_hw = __cam_isp_ctx_acquire_hw_in_acquired, .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_acquired, .release_hw = __cam_isp_ctx_release_hw_in_top_state, }, .crm_ops = { .link = __cam_isp_ctx_link_in_acquired, Loading @@ -2790,6 +3027,7 @@ static struct cam_ctx_ops .start_dev = __cam_isp_ctx_start_dev_in_ready, .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_top_state, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, Loading @@ -2804,6 +3042,7 @@ static struct cam_ctx_ops .stop_dev = __cam_isp_ctx_stop_dev_in_activated, .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_activated, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_activated, Loading Loading
drivers/media/platform/msm/camera/cam_core/cam_context.c +59 −0 Original line number Diff line number Diff line Loading @@ -287,6 +287,36 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx, return rc; } int cam_context_handle_acquire_hw(struct cam_context *ctx, void *args) { int rc; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (!args) { CAM_ERR(CAM_CORE, "Invalid acquire device hw command payload"); return -EINVAL; } mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.acquire_hw) { rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_hw( ctx, args); } else { CAM_ERR(CAM_CORE, "No acquire hw for dev %s, state %d", ctx->dev_name, ctx->state); rc = -EPROTO; } mutex_unlock(&ctx->ctx_mutex); return rc; } int cam_context_handle_release_dev(struct cam_context *ctx, struct cam_release_dev_cmd *cmd) { Loading Loading @@ -316,6 +346,35 @@ int cam_context_handle_release_dev(struct cam_context *ctx, return rc; } int cam_context_handle_release_hw(struct cam_context *ctx, void *args) { int rc; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (!args) { CAM_ERR(CAM_CORE, "Invalid release HW command payload"); return -EINVAL; } mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.release_hw) { rc = ctx->state_machine[ctx->state].ioctl_ops.release_hw( ctx, args); } else { CAM_ERR(CAM_CORE, "No release hw for dev %s, state %d", ctx->dev_name, ctx->state); rc = -EPROTO; } mutex_unlock(&ctx->ctx_mutex); return rc; } int cam_context_handle_flush_dev(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { Loading
drivers/media/platform/msm/camera/cam_core/cam_context.h +28 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,8 @@ struct cam_ctx_request { * @start_dev: Function pointer for start device * @stop_dev: Function pointer for stop device * @flush_dev: Function pointer for flush device * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * */ struct cam_ctx_ioctl_ops { Loading @@ -102,6 +104,8 @@ struct cam_ctx_ioctl_ops { struct cam_start_stop_dev_cmd *cmd); int (*flush_dev)(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd); int (*acquire_hw)(struct cam_context *ctx, void *args); int (*release_hw)(struct cam_context *ctx, void *args); }; /** Loading Loading @@ -320,6 +324,18 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd); /** * cam_context_handle_acquire_hw() * * @brief: Handle acquire HW command * * @ctx: Object pointer for cam_context * @cmd: Acquire HW command payload * */ int cam_context_handle_acquire_hw(struct cam_context *ctx, void *cmd); /** * cam_context_handle_release_dev() * Loading @@ -332,6 +348,18 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx, int cam_context_handle_release_dev(struct cam_context *ctx, struct cam_release_dev_cmd *cmd); /** * cam_context_handle_release_hw() * * @brief: Handle release HW command * * @ctx: Object pointer for cam_context * @cmd: Release HW command payload * */ int cam_context_handle_release_hw(struct cam_context *ctx, void *cmd); /** * cam_context_handle_config_dev() * Loading
drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h +1 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ struct cam_hw_acquire_args { void *context_data; cam_hw_event_cb_func event_cb; uint32_t num_acq; uint32_t acquire_info_size; uint64_t acquire_info; void *ctxt_to_hw_map; }; Loading
drivers/media/platform/msm/camera/cam_core/cam_node.c +170 −0 Original line number Diff line number Diff line Loading @@ -128,6 +128,45 @@ static int __cam_node_handle_acquire_dev(struct cam_node *node, return rc; } static int __cam_node_handle_acquire_hw_v1(struct cam_node *node, struct cam_acquire_hw_cmd_v1 *acquire) { int rc = 0; struct cam_context *ctx = NULL; if (!acquire) return -EINVAL; if (acquire->dev_handle <= 0) { CAM_ERR(CAM_CORE, "Invalid device handle for context"); return -EINVAL; } if (acquire->session_handle <= 0) { CAM_ERR(CAM_CORE, "Invalid session handle for context"); return -EINVAL; } ctx = (struct cam_context *)cam_get_device_priv(acquire->dev_handle); if (!ctx) { CAM_ERR(CAM_CORE, "Can not get context for handle %d", acquire->dev_handle); return -EINVAL; } rc = cam_context_handle_acquire_hw(ctx, acquire); if (rc) { CAM_ERR(CAM_CORE, "Acquire device failed for node %s", node->name); return rc; } CAM_DBG(CAM_CORE, "[%s] Acquire ctx_id %d", node->name, ctx->ctx_id); return 0; } static int __cam_node_handle_start_dev(struct cam_node *node, struct cam_start_stop_dev_cmd *start) { Loading Loading @@ -313,6 +352,43 @@ static int __cam_node_handle_release_dev(struct cam_node *node, return rc; } static int __cam_node_handle_release_hw_v1(struct cam_node *node, struct cam_release_hw_cmd_v1 *release) { int rc = 0; struct cam_context *ctx = NULL; if (!release) return -EINVAL; if (release->dev_handle <= 0) { CAM_ERR(CAM_CORE, "Invalid device handle for context"); return -EINVAL; } if (release->session_handle <= 0) { CAM_ERR(CAM_CORE, "Invalid session handle for context"); return -EINVAL; } ctx = (struct cam_context *)cam_get_device_priv(release->dev_handle); if (!ctx) { CAM_ERR(CAM_CORE, "Can not get context for handle %d node %s", release->dev_handle, node->name); return -EINVAL; } rc = cam_context_handle_release_hw(ctx, release); if (rc) CAM_ERR(CAM_CORE, "context release failed node %s", node->name); CAM_DBG(CAM_CORE, "[%s] Release ctx_id=%d, refcount=%d", node->name, ctx->ctx_id, atomic_read(&(ctx->refcount.refcount.refs))); return rc; } static int __cam_node_crm_get_dev_info(struct cam_req_mgr_device_info *info) { struct cam_context *ctx = NULL; Loading Loading @@ -542,6 +618,56 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) rc = -EFAULT; break; } case CAM_ACQUIRE_HW: { uint32_t api_version; void *acquire_ptr = NULL; size_t acquire_size; if (copy_from_user(&api_version, (void __user *)cmd->handle, sizeof(api_version))) { rc = -EFAULT; break; } if (api_version == 1) { acquire_size = sizeof(struct cam_acquire_hw_cmd_v1); } else { CAM_ERR(CAM_CORE, "Unsupported api version %d", api_version); rc = -EINVAL; break; } acquire_ptr = kzalloc(acquire_size, GFP_KERNEL); if (!acquire_ptr) { CAM_ERR(CAM_CORE, "No memory for acquire HW"); rc = -ENOMEM; break; } if (copy_from_user(acquire_ptr, (void __user *)cmd->handle, acquire_size)) { rc = -EFAULT; goto acquire_kfree; } if (api_version == 1) { rc = __cam_node_handle_acquire_hw_v1(node, acquire_ptr); if (rc) { CAM_ERR(CAM_CORE, "acquire device failed(rc = %d)", rc); goto acquire_kfree; } } if (copy_to_user((void __user *)cmd->handle, acquire_ptr, acquire_size)) rc = -EFAULT; acquire_kfree: kfree(acquire_ptr); break; } case CAM_START_DEV: { struct cam_start_stop_dev_cmd start; Loading Loading @@ -598,6 +724,50 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) } break; } case CAM_RELEASE_HW: { uint32_t api_version; size_t release_size; void *release_ptr = NULL; if (copy_from_user(&api_version, (void __user *)cmd->handle, sizeof(api_version))) { rc = -EFAULT; break; } if (api_version == 1) { release_size = sizeof(struct cam_release_hw_cmd_v1); } else { CAM_ERR(CAM_CORE, "Unsupported api version %d", api_version); rc = -EINVAL; break; } release_ptr = kzalloc(release_size, GFP_KERNEL); if (!release_ptr) { CAM_ERR(CAM_CORE, "No memory for release HW"); rc = -ENOMEM; break; } if (copy_from_user(release_ptr, (void __user *)cmd->handle, release_size)) { rc = -EFAULT; goto release_kfree; } if (api_version == 1) { rc = __cam_node_handle_release_hw_v1(node, release_ptr); if (rc) CAM_ERR(CAM_CORE, "release device failed(rc = %d)", rc); } release_kfree: kfree(release_ptr); break; } case CAM_FLUSH_REQ: { struct cam_flush_dev_cmd flush; Loading
drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +247 −8 Original line number Diff line number Diff line Loading @@ -1984,6 +1984,11 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, (struct cam_isp_context *) ctx->ctx_priv; struct cam_req_mgr_flush_request flush_req; if (cmd && ctx_isp->hw_ctx && ctx_isp->split_acquire) { CAM_ERR(CAM_ISP, "ctx expects release HW before release dev"); return rc; } if (ctx_isp->hw_ctx) { rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx; ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, Loading @@ -1998,6 +2003,8 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; /* * Ideally, we should never have any active request here. Loading @@ -2023,6 +2030,54 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, return rc; } static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, void *cmd) { int rc = 0; struct cam_hw_release_args rel_arg; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_req_mgr_flush_request flush_req; if (ctx_isp->hw_ctx) { rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx; ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &rel_arg); ctx_isp->hw_ctx = NULL; } else { CAM_ERR(CAM_ISP, "No hw resources acquired for this ctx"); } ctx_isp->frame_id = 0; ctx_isp->active_req_cnt = 0; ctx_isp->reported_req_id = 0; ctx_isp->hw_acquired = false; ctx_isp->init_received = false; /* * Ideally, we should never have any active request here. * But we still add some sanity check code here to help the debug */ if (!list_empty(&ctx->active_req_list)) CAM_WARN(CAM_ISP, "Active list is not empty"); /* Flush all the pending request list */ flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL; flush_req.link_hdl = ctx->link_hdl; flush_req.dev_hdl = ctx->dev_hdl; 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); ctx->state = CAM_CTX_ACQUIRED; trace_cam_context_state("ISP", ctx); CAM_DBG(CAM_ISP, "Release device success[%u] next state %d", ctx->ctx_id, ctx->state); return rc; } static int __cam_isp_ctx_config_dev_in_top_state( struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { Loading Loading @@ -2130,6 +2185,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( rc = __cam_isp_ctx_enqueue_init_request(ctx, req); if (rc) CAM_ERR(CAM_ISP, "Enqueue INIT pkt failed"); ctx_isp->init_received = true; } else { rc = -EINVAL; CAM_ERR(CAM_ISP, "Recevied INIT pkt in wrong state"); Loading Loading @@ -2201,6 +2257,12 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, cmd->session_handle, cmd->num_resources, cmd->handle_type, cmd->resource_hdl); if (cmd->num_resources == CAM_API_COMPAT_CONSTANT) { ctx_isp->split_acquire = true; CAM_DBG(CAM_ISP, "Acquire dev handle"); goto get_dev_handle; } if (cmd->num_resources > CAM_ISP_CTX_RES_MAX) { CAM_ERR(CAM_ISP, "Too much resources in the acquire"); rc = -ENOMEM; Loading Loading @@ -2276,8 +2338,15 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context; ctx_isp->hw_ctx = param.ctxt_to_hw_map; ctx_isp->hw_acquired = true; ctx_isp->split_acquire = false; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; kfree(isp_res); isp_res = NULL; get_dev_handle: req_hdl_param.session_hdl = cmd->session_handle; /* bridge is not ready for these flags. so false for now */ req_hdl_param.v4l2_sub_dev_flag = 0; Loading @@ -2296,31 +2365,178 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, /* store session information */ ctx->session_hdl = cmd->session_handle; ctx->state = CAM_CTX_ACQUIRED; trace_cam_context_state("ISP", ctx); CAM_DBG(CAM_ISP, "Acquire success on session_hdl 0x%x num_rsrces %d RDI only %d ctx %u", cmd->session_handle, cmd->num_resources, (isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id); "Acquire success on session_hdl 0x%x num_rsrces %d ctx %u", cmd->session_handle, cmd->num_resources, ctx->ctx_id); return rc; free_hw: release.ctxt_to_hw_map = ctx_isp->hw_ctx; if (ctx_isp->hw_acquired) ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release); ctx_isp->hw_ctx = NULL; ctx_isp->hw_acquired = false; free_res: kfree(isp_res); end: return rc; } static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, void *args) { int rc = 0; struct cam_acquire_hw_cmd_v1 *cmd = (struct cam_acquire_hw_cmd_v1 *)args; struct cam_hw_acquire_args param; struct cam_hw_release_args release; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; struct cam_hw_cmd_args hw_cmd_args; struct cam_isp_hw_cmd_args isp_hw_cmd_args; struct cam_isp_acquire_hw_info *acquire_hw_info = NULL; if (!ctx->hw_mgr_intf) { CAM_ERR(CAM_ISP, "HW interface is not ready"); rc = -EFAULT; goto end; } CAM_DBG(CAM_ISP, "session_hdl 0x%x, hdl type %d, res %lld", cmd->session_handle, cmd->handle_type, cmd->resource_hdl); /* for now we only support user pointer */ if (cmd->handle_type != 1) { CAM_ERR(CAM_ISP, "Only user pointer is supported"); rc = -EINVAL; goto end; } if (cmd->data_size < sizeof(*acquire_hw_info)) { CAM_ERR(CAM_ISP, "data_size is not a valid value"); goto end; } acquire_hw_info = kzalloc(cmd->data_size, GFP_KERNEL); if (!acquire_hw_info) { rc = -ENOMEM; goto end; } CAM_DBG(CAM_ISP, "start copy resources from user"); if (copy_from_user(acquire_hw_info, (void __user *)cmd->resource_hdl, cmd->data_size)) { rc = -EFAULT; goto free_res; } param.context_data = ctx; param.event_cb = ctx->irq_cb_intf; param.num_acq = CAM_API_COMPAT_CONSTANT; param.acquire_info_size = cmd->data_size; param.acquire_info = (uint64_t) acquire_hw_info; /* call HW manager to reserve the resource */ rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv, ¶m); if (rc != 0) { CAM_ERR(CAM_ISP, "Acquire device failed"); goto free_res; } /* Query the context has rdi only resource */ hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map; hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT; hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, &hw_cmd_args); if (rc) { CAM_ERR(CAM_ISP, "HW command failed"); goto free_hw; } if (isp_hw_cmd_args.u.is_rdi_only_context) { /* * this context has rdi only resource assign rdi only * state machine */ CAM_DBG(CAM_ISP, "RDI only session Context"); ctx_isp->substate_machine_irq = cam_isp_ctx_rdi_only_activated_state_machine_irq; ctx_isp->substate_machine = cam_isp_ctx_rdi_only_activated_state_machine; } else { CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); ctx_isp->substate_machine_irq = cam_isp_ctx_activated_state_machine_irq; ctx_isp->substate_machine = cam_isp_ctx_activated_state_machine; } ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context; ctx_isp->hw_ctx = param.ctxt_to_hw_map; ctx_isp->hw_acquired = true; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; trace_cam_context_state("ISP", ctx); CAM_DBG(CAM_ISP, "Acquire success on session_hdl 0x%xs RDI only %d ctx %u", ctx->session_hdl, (isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id); kfree(acquire_hw_info); return rc; free_hw: release.ctxt_to_hw_map = ctx_isp->hw_ctx; ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release); ctx_isp->hw_ctx = NULL; ctx_isp->hw_acquired = false; free_res: kfree(isp_res); kfree(acquire_hw_info); end: return rc; } static int __cam_isp_ctx_acquire_hw_in_acquired(struct cam_context *ctx, void *args) { int rc = -EINVAL; uint32_t api_version; if (!ctx || !args) { CAM_ERR(CAM_ISP, "Invalid input pointer"); return rc; } api_version = *((uint32_t *)args); if (api_version == 1) rc = __cam_isp_ctx_acquire_hw_v1(ctx, args); else CAM_ERR(CAM_ISP, "Unsupported api version %d", api_version); return rc; } static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx, struct cam_config_dev_cmd *cmd) { int rc = 0; struct cam_isp_context *ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; if (!ctx_isp->hw_acquired) { CAM_ERR(CAM_ISP, "HW is not acquired, reject packet"); return -EINVAL; } rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd); Loading @@ -2347,7 +2563,7 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx, ctx_isp->subscribe_event = link->subscribe_event; /* change state only if we had the init config */ if (!list_empty(&ctx->pending_req_list)) { if (ctx_isp->init_received) { ctx->state = CAM_CTX_READY; trace_cam_context_state("ISP", ctx); } Loading Loading @@ -2568,8 +2784,11 @@ static int __cam_isp_ctx_stop_dev_in_activated(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd) { int rc = 0; struct cam_isp_context *ctx_isp = (struct cam_isp_context *)ctx->ctx_priv; __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, cmd); ctx_isp->init_received = false; ctx->state = CAM_CTX_ACQUIRED; trace_cam_context_state("ISP", ctx); return rc; Loading @@ -2591,6 +2810,22 @@ static int __cam_isp_ctx_release_dev_in_activated(struct cam_context *ctx, return rc; } static int __cam_isp_ctx_release_hw_in_activated(struct cam_context *ctx, void *cmd) { int rc = 0; rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, NULL); if (rc) CAM_ERR(CAM_ISP, "Stop device failed rc=%d", rc); rc = __cam_isp_ctx_release_hw_in_top_state(ctx, cmd); if (rc) CAM_ERR(CAM_ISP, "Release hw failed rc=%d", rc); return rc; } static int __cam_isp_ctx_link_pause(struct cam_context *ctx) { int rc = 0; Loading Loading @@ -2772,8 +3007,10 @@ static struct cam_ctx_ops /* Acquired */ { .ioctl_ops = { .acquire_hw = __cam_isp_ctx_acquire_hw_in_acquired, .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_acquired, .release_hw = __cam_isp_ctx_release_hw_in_top_state, }, .crm_ops = { .link = __cam_isp_ctx_link_in_acquired, Loading @@ -2790,6 +3027,7 @@ static struct cam_ctx_ops .start_dev = __cam_isp_ctx_start_dev_in_ready, .release_dev = __cam_isp_ctx_release_dev_in_top_state, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_top_state, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_ready, Loading @@ -2804,6 +3042,7 @@ static struct cam_ctx_ops .stop_dev = __cam_isp_ctx_stop_dev_in_activated, .release_dev = __cam_isp_ctx_release_dev_in_activated, .config_dev = __cam_isp_ctx_config_dev_in_top_state, .release_hw = __cam_isp_ctx_release_hw_in_activated, }, .crm_ops = { .unlink = __cam_isp_ctx_unlink_in_activated, Loading