Merge "msm: camera: custom: Add support for immediate stop" into camera-kernel.lnx.4.0
Bu işleme şunda yer alıyor:
işlemeyi yapan:
Gerrit - the friendly Code Review server
işleme
8b7546e512
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ctx->lock);
|
||||
rc = __cam_custom_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
|
||||
spin_unlock_bh(&ctx->lock);
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -170,34 +256,27 @@ 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)
|
||||
{
|
||||
int rc = 0;
|
||||
uint32_t i;
|
||||
struct cam_custom_context *ctx_custom =
|
||||
(struct cam_custom_context *) ctx->ctx_priv;
|
||||
struct cam_ctx_request *req;
|
||||
struct cam_custom_dev_ctx_req *req_custom;
|
||||
struct cam_hw_stop_args stop;
|
||||
(struct cam_custom_context *) ctx->ctx_priv;
|
||||
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)) {
|
||||
@@ -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;
|
||||
@@ -796,6 +877,44 @@ free_req:
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -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 =
|
||||
@@ -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");
|
||||
@@ -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 = {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
@@ -222,6 +222,7 @@ err:
|
||||
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;
|
||||
@@ -231,6 +232,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;
|
||||
|
||||
@@ -263,6 +265,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) {
|
||||
@@ -284,6 +289,7 @@ static int cam_custom_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
|
||||
|
||||
/* deinit custom rsrc */
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -359,13 +365,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;
|
||||
@@ -377,6 +389,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) {
|
||||
@@ -404,6 +419,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;
|
||||
@@ -434,6 +451,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:
|
||||
@@ -1115,6 +1134,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)
|
||||
{
|
||||
@@ -1281,6 +1375,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;
|
||||
|
Yeni konuda referans
Bir kullanıcı engelle