Merge "msm: camera: custom: Add support for immediate stop" into camera-kernel.lnx.4.0

Bu işleme şunda yer alıyor:
Camera Software Integration
2020-02-04 15:07:26 -08:00
işlemeyi yapan: Gerrit - the friendly Code Review server
işleme 8b7546e512
2 değiştirilmiş dosya ile 267 ekleme ve 57 silme

Dosyayı Görüntüle

@@ -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 = {

Dosyayı Görüntüle

@@ -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;