msm: camera: isp: Add per frame support for scratch buffers

If CRM skips applying settings on a given frame, in case of sHDR
program scratch buffers along with RUP/AUP to ensure
continuity with respect to sensor frames.

CRs-Fixed: 2841729
Change-Id: I296dbc713f49db54681043415b6ad1499dc13de4
Signed-off-by: Karthik Anantha Ram <kartanan@codeaurora.org>
This commit is contained in:
Karthik Anantha Ram
2020-12-01 18:30:50 -08:00
committed by Gerrit - the friendly Code Review server
parent 131c340861
commit fa9a698aa1
14 changed files with 565 additions and 58 deletions

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_HW_MGR_INTF_H_
@@ -113,9 +113,8 @@ struct cam_hw_done_event_data {
* @acquire_info: Acquired resource array pointer
* @ctxt_to_hw_map: HW context (returned)
* @hw_mgr_ctx_id HWMgr context id(returned)
* @custom_enabled: ctx has custom enabled
* @use_frame_header_ts: Use frame header for qtimer ts
* @support_consumed_addr: The platform has last consumed addr register
* @op_flags: Used as bitwise params from hw_mgr to ctx
* See xxx_hw_mgr_intf.h for definitions
* @acquired_hw_id: Acquired hardware mask
* @acquired_hw_path: Acquired path mask for an input
* if input splits into multiple paths,
@@ -132,9 +131,7 @@ struct cam_hw_acquire_args {
uintptr_t acquire_info;
void *ctxt_to_hw_map;
uint32_t hw_mgr_ctx_id;
bool custom_enabled;
bool use_frame_header_ts;
bool support_consumed_addr;
uint32_t op_flags;
uint32_t acquired_hw_id[CAM_MAX_ACQ_RES];
uint32_t acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT];

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/debugfs.h>
@@ -3275,6 +3275,32 @@ static int __cam_isp_ctx_apply_req_in_bubble(
return rc;
}
static int __cam_isp_ctx_apply_default_req_settings(
struct cam_context *ctx, struct cam_req_mgr_apply_request *apply)
{
int rc = 0;
struct cam_isp_context *isp_ctx =
(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;
hw_cmd_args.ctxt_to_hw_map = isp_ctx->hw_ctx;
hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
isp_hw_cmd_args.cmd_type =
CAM_ISP_HW_MGR_CMD_PROG_DEFAULT_CFG;
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,
"Failed to apply default settings rc %d", rc);
else
CAM_DBG(CAM_ISP, "Applied default settings rc %d", rc);
return rc;
}
static int __cam_isp_ctx_dump_req_info(
struct cam_context *ctx,
struct cam_ctx_request *req,
@@ -3670,6 +3696,8 @@ static struct cam_ctx_ops
.ioctl_ops = {},
.crm_ops = {
.apply_req = __cam_isp_ctx_apply_req_in_sof,
.notify_frame_skip =
__cam_isp_ctx_apply_default_req_settings,
},
.irq_ops = NULL,
},
@@ -3684,6 +3712,8 @@ static struct cam_ctx_ops
.ioctl_ops = {},
.crm_ops = {
.apply_req = __cam_isp_ctx_apply_req_in_epoch,
.notify_frame_skip =
__cam_isp_ctx_apply_default_req_settings,
},
.irq_ops = NULL,
},
@@ -3692,6 +3722,8 @@ static struct cam_ctx_ops
.ioctl_ops = {},
.crm_ops = {
.apply_req = __cam_isp_ctx_apply_req_in_bubble,
.notify_frame_skip =
__cam_isp_ctx_apply_default_req_settings,
},
.irq_ops = NULL,
},
@@ -4306,6 +4338,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
ctx->last_flush_req = 0;
ctx_isp->custom_enabled = false;
ctx_isp->use_frame_header_ts = false;
ctx_isp->use_default_apply = false;
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
ctx_isp->reported_req_id = 0;
@@ -4928,7 +4961,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
}
ctx_isp->support_consumed_addr =
param.support_consumed_addr;
(param.op_flags & CAM_IFE_CTX_FRAME_HEADER_EN);
/* Query the context has rdi only resource */
hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
@@ -5077,13 +5110,18 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
goto free_res;
}
/* Set custom flag if applicable
/*
* Set feature flag if applicable
* custom hw is supported only on v2
*/
ctx_isp->custom_enabled = param.custom_enabled;
ctx_isp->use_frame_header_ts = param.use_frame_header_ts;
ctx_isp->custom_enabled =
(param.op_flags & CAM_IFE_CTX_CUSTOM_EN);
ctx_isp->use_frame_header_ts =
(param.op_flags & CAM_IFE_CTX_FRAME_HEADER_EN);
ctx_isp->use_default_apply =
(param.op_flags & CAM_IFE_CTX_APPLY_DEFAULT_CFG);
ctx_isp->support_consumed_addr =
param.support_consumed_addr;
(param.op_flags & CAM_IFE_CTX_CONSUME_ADDR_EN);
/* Query the context has rdi only resource */
hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
@@ -5761,6 +5799,39 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx,
return rc;
}
static int __cam_isp_ctx_apply_default_settings(
struct cam_context *ctx,
struct cam_req_mgr_apply_request *apply)
{
int rc = 0;
struct cam_ctx_ops *ctx_ops = NULL;
struct cam_isp_context *ctx_isp =
(struct cam_isp_context *) ctx->ctx_priv;
if (!ctx_isp->use_default_apply)
return 0;
CAM_DBG(CAM_ISP,
"Enter: apply req in Substate %d request _id:%lld",
ctx_isp->substate_activated, apply->request_id);
ctx_ops = &ctx_isp->substate_machine[
ctx_isp->substate_activated];
if (ctx_ops->crm_ops.notify_frame_skip) {
rc = ctx_ops->crm_ops.notify_frame_skip(ctx, apply);
} else {
CAM_WARN_RATE_LIMIT(CAM_ISP,
"No handle function in activated substate %d",
ctx_isp->substate_activated);
rc = -EFAULT;
}
if (rc)
CAM_WARN_RATE_LIMIT(CAM_ISP,
"Apply default failed in active substate %d rc %d",
ctx_isp->substate_activated, rc);
return rc;
}
static int __cam_isp_ctx_handle_irq_in_activated(void *context,
@@ -5878,6 +5949,8 @@ static struct cam_ctx_ops
.crm_ops = {
.unlink = __cam_isp_ctx_unlink_in_activated,
.apply_req = __cam_isp_ctx_apply_req,
.notify_frame_skip =
__cam_isp_ctx_apply_default_settings,
.flush_req = __cam_isp_ctx_flush_req_in_top_state,
.process_evt = __cam_isp_ctx_process_evt,
.dump_req = __cam_isp_ctx_dump_in_top_state,
@@ -6078,6 +6151,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx,
ctx->frame_id = 0;
ctx->custom_enabled = false;
ctx->use_frame_header_ts = false;
ctx->use_default_apply = false;
ctx->active_req_cnt = 0;
ctx->reported_req_id = 0;
ctx->bubble_frame_cnt = 0;

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_ISP_CONTEXT_H_
@@ -270,6 +270,7 @@ struct cam_isp_context_event_record {
* @use_frame_header_ts: Use frame header for qtimer ts
* @support_consumed_addr: Indicate whether HW has last consumed addr reg
* @apply_in_progress Whether request apply is in progress
* @use_default_apply: Use default settings in case of frame skip
* @init_timestamp: Timestamp at which this context is initialized
* @isp_device_type: ISP device type
* @rxd_epoch: Indicate whether epoch has been received. Used to
@@ -318,6 +319,7 @@ struct cam_isp_context {
bool use_frame_header_ts;
bool support_consumed_addr;
atomic_t apply_in_progress;
bool use_default_apply;
unsigned int init_timestamp;
uint32_t isp_device_type;
atomic_t rxd_epoch;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/slab.h>
@@ -4047,6 +4047,9 @@ skip_csid_pxl:
}
}
if (in_port->dynamic_sensor_switch_en)
ife_ctx->ctx_config |= CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON;
return 0;
err:
/* release resource at the acquire entry funciton */
@@ -4357,7 +4360,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
}
cam_cpas_get_cpas_hw_version(&ife_ctx->hw_version);
ife_ctx->custom_config = 0;
ife_ctx->ctx_config = 0;
ife_ctx->cdm_handle = 0;
ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_NONE;
@@ -4420,10 +4423,10 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
if (in_port[i].cust_node) {
ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_CUSTOM;
/* These can be obtained from uapi */
ife_ctx->custom_config |=
CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS;
ife_ctx->custom_config |=
CAM_IFE_CUSTOM_CFG_SW_SYNC_ON;
ife_ctx->ctx_config |=
CAM_IFE_CTX_CFG_FRAME_HEADER_TS;
ife_ctx->ctx_config |=
CAM_IFE_CTX_CFG_SW_SYNC_ON;
} else if (in_port[i].sfe_in_path_type) {
ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_SFE;
}
@@ -4517,16 +4520,26 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
atomic_set(&ife_ctx->cdm_done, 1);
ife_ctx->last_cdm_done_req = 0;
acquire_args->support_consumed_addr =
g_ife_hw_mgr.support_consumed_addr;
if (g_ife_hw_mgr.support_consumed_addr)
acquire_args->op_flags |=
CAM_IFE_CTX_CONSUME_ADDR_EN;
if ((ife_ctx->ctx_type == CAM_IFE_CTX_TYPE_SFE) &&
ife_ctx->is_fe_enabled) {
ife_ctx->ctx_config |= CAM_IFE_CTX_CFG_SFE_FE_MODE;
acquire_args->op_flags |=
CAM_IFE_CTX_APPLY_DEFAULT_CFG;
}
acquire_args->ctxt_to_hw_map = ife_ctx;
acquire_args->custom_enabled = false;
if (ife_ctx->ctx_type == CAM_IFE_CTX_TYPE_CUSTOM)
acquire_args->custom_enabled = true;
acquire_args->use_frame_header_ts =
(ife_ctx->custom_config &
CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS);
acquire_args->op_flags |= CAM_IFE_CTX_CUSTOM_EN;
if (ife_ctx->ctx_config &
CAM_IFE_CTX_CFG_FRAME_HEADER_TS)
acquire_args->op_flags |=
CAM_IFE_CTX_FRAME_HEADER_EN;
ife_ctx->ctx_in_use = 1;
ife_ctx->num_reg_dump_buf = 0;
memset(&ife_ctx->scratch_config, 0,
@@ -5374,7 +5387,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
}
if (cfg->init_packet || hw_update_data->mup_en ||
(ctx->custom_config & CAM_IFE_CUSTOM_CFG_SW_SYNC_ON)) {
(ctx->ctx_config & CAM_IFE_CTX_CFG_SW_SYNC_ON)) {
rem_jiffies = wait_for_completion_timeout(
&ctx->config_done_complete,
msecs_to_jiffies(60));
@@ -6272,7 +6285,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
ctx->cdm_ops = NULL;
ctx->num_reg_dump_buf = 0;
ctx->ctx_type = CAM_IFE_CTX_TYPE_NONE;
ctx->custom_config = 0;
ctx->ctx_config = 0;
ctx->num_reg_dump_buf = 0;
ctx->is_dual = false;
ctx->dsp_enabled = false;
@@ -8313,6 +8326,21 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
CAM_ERR(CAM_ISP, "FS Update Failed rc: %d", rc);
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH: {
struct cam_isp_mode_switch_info *mup_config;
if (blob_size < sizeof(struct cam_isp_mode_switch_info)) {
CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
blob_size,
sizeof(struct cam_isp_mode_switch_info));
return -EINVAL;
}
mup_config = (struct cam_isp_mode_switch_info *)blob_data;
ife_mgr_ctx->scratch_config.curr_num_exp =
mup_config->num_expoures;
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG:
case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG:
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG:
@@ -8350,7 +8378,7 @@ static int cam_isp_sfe_send_scratch_buf_upd(
memset(io_addr, 0, sizeof(io_addr));
update_buf.res = hw_res;
update_buf.cmd_type = CAM_ISP_HW_CMD_GET_BUF_UPDATE;
update_buf.cmd_type = cmd_type;
update_buf.cmd.cmd_buf_addr = cpu_addr;
update_buf.use_scratch_cfg = true;
@@ -8380,7 +8408,11 @@ static int cam_isp_sfe_send_scratch_buf_upd(
CAM_DBG(CAM_ISP, "Scratch buf configured for: 0x%x",
hw_res->res_id);
/* Update used bytes if update is via CDM */
if ((cmd_type == CAM_ISP_HW_CMD_GET_BUF_UPDATE) ||
(cmd_type == CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM))
*used_bytes = update_buf.cmd.used_bytes;
return rc;
}
@@ -8441,6 +8473,14 @@ static int cam_isp_sfe_add_scratch_buffer_cfg(
}
res_id = hw_mgr_res->hw_res[j]->res_id;
/* check for num exposures */
if ((ctx->ctx_config &
CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
((res_id - CAM_ISP_SFE_OUT_RES_RDI_0) >=
ctx->scratch_config.curr_num_exp))
continue;
cpu_addr = kmd_buf_info->cpu_addr +
kmd_buf_info->used_bytes / 4 +
io_cfg_used_bytes / 4;
@@ -8487,6 +8527,14 @@ static int cam_isp_sfe_add_scratch_buffer_cfg(
}
res_id = hw_mgr_res->hw_res[j]->res_id;
/* check for num exposures */
if ((ctx->ctx_config &
CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
((res_id - CAM_ISP_HW_SFE_IN_RD0) >=
ctx->scratch_config.curr_num_exp))
continue;
cpu_addr = kmd_buf_info->cpu_addr +
kmd_buf_info->used_bytes / 4 +
io_cfg_used_bytes / 4;
@@ -8707,7 +8755,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
if (rc)
return rc;
if (ctx->custom_config & CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) {
if (ctx->ctx_config & CAM_IFE_CTX_CFG_FRAME_HEADER_TS) {
rc = cam_ife_mgr_util_insert_frame_header(&kmd_buf,
prepare_hw_data);
if (rc)
@@ -8825,7 +8873,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
}
sfe_fe_chk_cfg.sfe_fe_enabled = false;
if ((ctx->is_fe_enabled) &&
if ((!ctx->is_offline) && (ctx->is_fe_enabled) &&
(ctx->base[i].hw_type == CAM_ISP_HW_TYPE_SFE)) {
sfe_fe_chk_cfg.sfe_fe_enabled = true;
sfe_fe_chk_cfg.sfe_rdi_cfg_mask = 0;
@@ -8899,7 +8947,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
}
/* Check if frame header was enabled for any WM */
if ((ctx->custom_config & CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) &&
if ((ctx->ctx_config & CAM_IFE_CTX_CFG_FRAME_HEADER_TS) &&
(prepare->num_out_map_entries) &&
(!prepare_hw_data->frame_header_res_id)) {
CAM_ERR(CAM_ISP, "Failed to configure frame header");
@@ -9290,6 +9338,159 @@ outportlog:
}
int cam_isp_config_csid_rup_aup(
struct cam_ife_hw_mgr_ctx *ctx)
{
int rc = 0, i, j, hw_idx;
struct cam_isp_hw_mgr_res *hw_mgr_res;
struct list_head *res_list;
struct cam_isp_resource_node *res;
struct cam_isp_csid_reg_update_args
rup_args[CAM_IFE_CSID_HW_NUM_MAX] = {0};
res_list = &ctx->res_list_ife_csid;
for (j = 0; j < ctx->num_base; j++) {
if (ctx->base[j].hw_type != CAM_ISP_HW_TYPE_CSID)
continue;
list_for_each_entry(hw_mgr_res, res_list, list) {
if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT)
continue;
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
if (!hw_mgr_res->hw_res[i])
continue;
res = hw_mgr_res->hw_res[i];
if (res->hw_intf->hw_idx != ctx->base[j].idx)
continue;
hw_idx = res->hw_intf->hw_idx;
rup_args[hw_idx].res[rup_args[hw_idx].num_res] = res;
rup_args[hw_idx].num_res++;
CAM_DBG(CAM_ISP,
"Reg update for res %d hw_id %d cdm_idx %d",
res->res_id, res->hw_intf->hw_idx, ctx->base[j].idx);
}
}
}
for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
if (!rup_args[i].num_res)
continue;
rup_args[i].cmd.cmd_buf_addr = NULL;
rup_args[i].cmd.size = 0;
rup_args[i].reg_write = true;
res = rup_args[i].res[0];
rc = res->hw_intf->hw_ops.process_cmd(
res->hw_intf->hw_priv,
CAM_ISP_HW_CMD_GET_REG_UPDATE, &rup_args[i],
sizeof(struct cam_isp_csid_reg_update_args));
if (rc)
return rc;
CAM_DBG(CAM_ISP,
"Reg update for res %d hw_id %d ",
res->res_id, res->hw_intf->hw_idx);
}
return rc;
}
/*
* Scratch buffer is for sHDR usescases involing SFE RDI0-2
* There is no possibility of dual in this case, hence
* using the scratch buffer provided during INIT corresponding
* to each left RDIs
*/
static int cam_ife_mgr_prog_default_settings(
struct cam_ife_hw_mgr_ctx *ctx)
{
int i, j, res_id, rc = 0;
struct cam_isp_hw_mgr_res *hw_mgr_res;
struct cam_sfe_scratch_buf_info *buf_info;
struct list_head *res_list_in_rd = NULL;
struct cam_isp_hw_mgr_res *res_list_sfe_out = NULL;
res_list_in_rd = &ctx->res_list_ife_in_rd;
res_list_sfe_out = ctx->res_list_sfe_out;
for (i = 0; i < CAM_SFE_FE_RDI_NUM_MAX; i++) {
hw_mgr_res = &res_list_sfe_out[i];
for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
/* j = 1 is not valid for this use-case */
if (!hw_mgr_res->hw_res[j])
continue;
res_id = hw_mgr_res->hw_res[j]->res_id;
/* check for num exposures */
if ((ctx->ctx_config &
CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
((res_id - CAM_ISP_SFE_OUT_RES_RDI_0) >=
ctx->scratch_config.curr_num_exp))
continue;
buf_info = &ctx->scratch_config.buf_info[
res_id - CAM_ISP_SFE_OUT_RES_RDI_0];
CAM_DBG(CAM_ISP,
"RDI%d res_id 0x%x idx %u io_addr %pK",
i,
hw_mgr_res->hw_res[j]->res_id,
(res_id - CAM_ISP_SFE_OUT_RES_RDI_0),
buf_info->io_addr);
rc = cam_isp_sfe_send_scratch_buf_upd(0x0,
CAM_ISP_HW_CMD_BUF_UPDATE,
hw_mgr_res->hw_res[j], buf_info,
NULL, NULL);
if (rc)
return rc;
}
}
list_for_each_entry(hw_mgr_res, res_list_in_rd, list) {
for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
if (!hw_mgr_res->hw_res[j])
continue;
res_id = hw_mgr_res->hw_res[j]->res_id;
/* check for num exposures */
if ((ctx->ctx_config &
CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
((res_id - CAM_ISP_HW_SFE_IN_RD0) >=
ctx->scratch_config.curr_num_exp))
continue;
buf_info = &ctx->scratch_config.buf_info
[res_id - CAM_ISP_HW_SFE_IN_RD0];
CAM_DBG(CAM_ISP,
"RD res_id 0x%x idx %u io_addr %pK",
hw_mgr_res->hw_res[j]->res_id,
(res_id - CAM_ISP_HW_SFE_IN_RD0),
buf_info->io_addr);
rc = cam_isp_sfe_send_scratch_buf_upd(0x0,
CAM_ISP_HW_CMD_BUF_UPDATE_RM,
hw_mgr_res->hw_res[j], buf_info,
NULL, NULL);
if (rc)
return rc;
}
}
/* Program rup & aup */
rc = cam_isp_config_csid_rup_aup(ctx);
if (rc)
CAM_ERR(CAM_ISP,
"RUP/AUP update failed for scratch buffers");
return rc;
}
static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
{
int rc = 0;
@@ -9359,6 +9560,9 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
isp_hw_cmd_args->u.last_cdm_done =
ctx->last_cdm_done_req;
break;
case CAM_ISP_HW_MGR_CMD_PROG_DEFAULT_CFG:
rc = cam_ife_mgr_prog_default_settings(ctx);
break;
default:
CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
hw_cmd_args->cmd_type);
@@ -10248,8 +10452,8 @@ static int cam_ife_hw_mgr_handle_hw_sof(
case CAM_ISP_HW_VFE_IN_CAMIF:
case CAM_ISP_HW_VFE_IN_RD:
/* if frame header is enabled reset qtimer ts */
if (ife_hw_mgr_ctx->custom_config &
CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) {
if (ife_hw_mgr_ctx->ctx_config &
CAM_IFE_CTX_CFG_FRAME_HEADER_TS) {
sof_done_event_data.timestamp = 0x0;
ktime_get_boottime_ts64(&ts);
sof_done_event_data.boot_time =
@@ -10417,7 +10621,8 @@ static int cam_ife_hw_mgr_handle_hw_buf_done(
buf_done_event_data.last_consumed_addr[0] =
event_info->reg_val;
if ((ife_hw_mgr_ctx->ctx_type == CAM_IFE_CTX_TYPE_SFE) &&
if ((!ife_hw_mgr_ctx->is_offline) &&
(ife_hw_mgr_ctx->ctx_type == CAM_IFE_CTX_TYPE_SFE) &&
(ife_hw_mgr_ctx->is_fe_enabled)) {
rc = cam_ife_hw_mgr_check_rdi_scratch_buf_done(
ife_hw_mgr_ctx, event_info->res_id,

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_IFE_HW_MGR_H_
@@ -33,9 +33,11 @@ enum cam_ife_ctx_master_type {
#define CAM_SFE_HW_OUT_RES_MAX (CAM_ISP_SFE_OUT_RES_MAX & 0xFF)
#define CAM_IFE_HW_RES_POOL_MAX 64
/* IFE_HW_MGR custom config */
#define CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS BIT(0)
#define CAM_IFE_CUSTOM_CFG_SW_SYNC_ON BIT(1)
/* IFE_HW_MGR ctx config */
#define CAM_IFE_CTX_CFG_FRAME_HEADER_TS BIT(0)
#define CAM_IFE_CTX_CFG_SW_SYNC_ON BIT(1)
#define CAM_IFE_CTX_CFG_SFE_FE_MODE BIT(2)
#define CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON BIT(3)
#define CAM_IFE_UBWC_COMP_EN BIT(1)
@@ -89,12 +91,14 @@ struct cam_sfe_scratch_buf_info {
*
* @config_done: To indicate if stream received it's scratch cfg
* @num_configs: Number of buffer configs [max of 3 currently]
* @curr_num_exp: Current num of exposures
* @buf_info: Info on each of the buffers
*
*/
struct cam_sfe_scratch_buf_cfg {
bool config_done;
uint32_t num_config;
uint32_t curr_num_exp;
struct cam_sfe_scratch_buf_info buf_info[
CAM_SFE_FE_RDI_NUM_MAX];
};
@@ -212,7 +216,7 @@ struct cam_ife_hw_mgr_ctx {
bool is_fe_enabled;
bool is_dual;
enum cam_ife_ctx_master_type ctx_type;
uint32_t custom_config;
uint32_t ctx_config;
struct timespec64 ts;
bool is_tpg;
bool is_offline;

View File

@@ -2037,8 +2037,9 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
tfe_ctx->ctx_in_use = 1;
tfe_ctx->num_reg_dump_buf = 0;
acquire_args->support_consumed_addr =
g_tfe_hw_mgr.support_consumed_addr;
if (g_tfe_hw_mgr.support_consumed_addr)
acquire_args->op_flags |=
CAM_IFE_CTX_CONSUME_ADDR_EN;
cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx);

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <media/cam_defs.h>
@@ -1723,6 +1723,7 @@ int cam_isp_add_csid_reg_update(
kmd_buf_info->used_bytes/4 +
reg_update_size/4;
rup_args->cmd.size = kmd_buf_remain_size;
rup_args->reg_write = false;
res = rup_args->res[0];
rc = res->hw_intf->hw_ops.process_cmd(

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_ISP_HW_MGR_INTF_H_
@@ -32,6 +32,12 @@
/* Appliacble vote paths for dual ife, based on no. of UAPI definitions */
#define CAM_ISP_MAX_PER_PATH_VOTES 40
/* Output params for acquire from hw_mgr to ctx */
#define CAM_IFE_CTX_CUSTOM_EN BIT(0)
#define CAM_IFE_CTX_FRAME_HEADER_EN BIT(1)
#define CAM_IFE_CTX_CONSUME_ADDR_EN BIT(2)
#define CAM_IFE_CTX_APPLY_DEFAULT_CFG BIT(3)
/**
* enum cam_isp_hw_event_type - Collection of the ISP hardware events
*/
@@ -240,6 +246,7 @@ enum cam_isp_hw_mgr_command {
CAM_ISP_HW_MGR_CMD_CTX_TYPE,
CAM_ISP_HW_MGR_GET_PACKET_OPCODE,
CAM_ISP_HW_MGR_GET_LAST_CDM_DONE,
CAM_ISP_HW_MGR_CMD_PROG_DEFAULT_CFG,
CAM_ISP_HW_MGR_CMD_MAX,
};

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/iopoll.h>
@@ -3334,6 +3334,7 @@ static int cam_ife_csid_ver2_reg_update(
struct cam_isp_csid_reg_update_args *rup_args = cmd_args;
struct cam_cdm_utils_ops *cdm_util_ops;
struct cam_ife_csid_ver2_reg_info *csid_reg;
struct cam_hw_soc_info *soc_info;
uint32_t size, i;
uint32_t reg_val_pair[2];
uint32_t rup_aup_mask = 0;
@@ -3366,7 +3367,7 @@ static int cam_ife_csid_ver2_reg_update(
size = cdm_util_ops->cdm_required_size_reg_random(1);
/* since cdm returns dwords, we need to convert it into bytes */
if ((size * 4) > rup_args->cmd.size) {
if ((!rup_args->reg_write) && ((size * 4) > rup_args->cmd.size)) {
CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
rup_args->cmd.size, (size*4));
return -EINVAL;
@@ -3420,10 +3421,16 @@ static int cam_ife_csid_ver2_reg_update(
csid_hw->hw_intf->hw_idx,
reg_val_pair[1], reg_val_pair[0]);
if (rup_args->reg_write) {
soc_info = &csid_hw->hw_info->soc_info;
cam_io_w_mb(reg_val_pair[1],
soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base +
reg_val_pair[0]);
} else {
cdm_util_ops->cdm_write_regrandom(rup_args->cmd.cmd_buf_addr,
1, reg_val_pair);
rup_args->cmd.used_bytes = size * 4;
}
return rc;
err:

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CSID_HW_INTF_H_
@@ -353,11 +353,13 @@ struct cam_ife_csid_dual_sync_args {
* @cmd: cmd buf update args
* @node_res: Node res pointer
* @num_res: Num of resources
* @reg_write: if set use AHB to config rup/aup
*/
struct cam_isp_csid_reg_update_args {
struct cam_isp_hw_cmd_buf_update cmd;
struct cam_isp_resource_node *res[CAM_IFE_PIX_PATH_RES_MAX];
uint32_t num_res;
bool reg_write;
};
/*

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_ISP_HW_H_
@@ -145,6 +145,8 @@ enum cam_isp_hw_cmd_type {
CAM_IFE_CSID_PROGRAM_OFFLINE_CMD,
CAM_IFE_CSID_SET_DUAL_SYNC_CONFIG,
CAM_ISP_HW_CMD_CSID_MUP_UPDATE,
CAM_ISP_HW_CMD_BUF_UPDATE,
CAM_ISP_HW_CMD_BUF_UPDATE_RM,
CAM_ISP_HW_CMD_MAX,
};

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/slab.h>
@@ -327,6 +327,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
cmd_args, arg_size);
break;
case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
case CAM_ISP_HW_CMD_BUF_UPDATE:
case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
case CAM_ISP_HW_CMD_STRIPE_UPDATE:
case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE:
@@ -337,6 +338,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
break;
case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
case CAM_ISP_HW_CMD_BUF_UPDATE_RM:
case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
rc = core_info->sfe_bus_rd->hw_ops.process_cmd(
core_info->sfe_bus_rd->bus_priv, cmd_type,

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/ratelimit.h>
@@ -1118,6 +1118,88 @@ static int cam_sfe_bus_deinit_sfe_bus_rd_resource(
return 0;
}
/*
* API similar to cam_sfe_bus_rd_update_rm() with the
* only change being config is done via AHB instead of CDM
*/
static int cam_sfe_bus_rd_config_rm(void *priv, void *cmd_args,
uint32_t arg_size)
{
struct cam_sfe_bus_rd_priv *bus_priv;
struct cam_isp_hw_get_cmd_update *update_buf;
struct cam_sfe_bus_rd_data *sfe_bus_rd_data = NULL;
struct cam_sfe_bus_rd_rm_resource_data *rm_data = NULL;
uint32_t width = 0, height = 0, stride = 0;
uint32_t i;
bus_priv = (struct cam_sfe_bus_rd_priv *) priv;
update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args;
sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *)
update_buf->res->res_priv;
if (!sfe_bus_rd_data || !sfe_bus_rd_data->cdm_util_ops) {
CAM_ERR(CAM_SFE, "Failed! Invalid data");
return -EINVAL;
}
CAM_DBG(CAM_SFE, "num of RM: %d scratch_buf_cfg: %s",
sfe_bus_rd_data->num_rm,
update_buf->use_scratch_cfg ? "true" : "false");
if (update_buf->rm_update->num_buf != sfe_bus_rd_data->num_rm) {
CAM_ERR(CAM_SFE,
"Failed! Invalid number buffers:%d required:%d",
update_buf->rm_update->num_buf,
sfe_bus_rd_data->num_rm);
return -EINVAL;
}
for (i = 0; i < sfe_bus_rd_data->num_rm; i++) {
rm_data = sfe_bus_rd_data->rm_res[i]->res_priv;
stride = update_buf->rm_update->stride;
width = update_buf->rm_update->width;
height = update_buf->rm_update->height;
/* update size register */
cam_sfe_bus_rd_pxls_to_bytes(width,
rm_data->unpacker_cfg, &rm_data->width);
rm_data->height = height;
cam_io_w_mb(rm_data->width,
rm_data->common_data->mem_base +
rm_data->hw_regs->buf_width);
cam_io_w_mb(rm_data->height,
rm_data->common_data->mem_base +
rm_data->hw_regs->buf_height);
CAM_DBG(CAM_SFE, "SFE:%d RM:%d width:0x%X height:0x%X",
rm_data->common_data->core_index,
rm_data->index, rm_data->width,
rm_data->height);
rm_data->stride = stride;
cam_io_w_mb(stride,
rm_data->common_data->mem_base +
rm_data->hw_regs->stride);
CAM_DBG(CAM_SFE, "SFE:%d RM:%d image_stride:0x%X",
rm_data->common_data->core_index,
rm_data->index, stride);
cam_io_w_mb(update_buf->rm_update->image_buf[i],
rm_data->common_data->mem_base +
rm_data->hw_regs->image_addr);
CAM_DBG(CAM_SFE, "SFE:%d RM:%d image_address:0x%X",
rm_data->common_data->core_index,
rm_data->index,
update_buf->rm_update->image_buf[i]);
rm_data->img_addr =
update_buf->rm_update->image_buf[i];
}
return 0;
}
static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
uint32_t arg_size)
{
@@ -1320,6 +1402,9 @@ static int cam_sfe_bus_rd_process_cmd(
case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
rc = cam_sfe_bus_rd_update_rm(priv, cmd_args, arg_size);
break;
case CAM_ISP_HW_CMD_BUF_UPDATE_RM:
rc = cam_sfe_bus_rd_config_rm(priv, cmd_args, arg_size);
break;
case CAM_ISP_HW_CMD_GET_SECURE_MODE:
rc = cam_sfe_bus_rd_get_secure_mode(priv, cmd_args, arg_size);
break;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
@@ -2074,6 +2074,121 @@ static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
return 0;
}
/*
* API similar to cam_sfe_bus_wr_update_wm() with the
* only change being config is done via AHB instead of CDM
*/
static int cam_sfe_bus_wr_config_wm(void *priv, void *cmd_args,
uint32_t arg_size)
{
struct cam_sfe_bus_wr_priv *bus_priv;
struct cam_isp_hw_get_cmd_update *update_buf;
struct cam_sfe_bus_wr_out_data *sfe_out_data = NULL;
struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL;
uint32_t i, k;
uint32_t frame_inc = 0, val;
uint32_t loop_size = 0, stride = 0, slice_h = 0;
bus_priv = (struct cam_sfe_bus_wr_priv *) priv;
update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args;
sfe_out_data = (struct cam_sfe_bus_wr_out_data *)
update_buf->res->res_priv;
if (!sfe_out_data || !sfe_out_data->cdm_util_ops) {
CAM_ERR(CAM_SFE, "Failed! Invalid data");
return -EINVAL;
}
if (update_buf->wm_update->num_buf != sfe_out_data->num_wm) {
CAM_ERR(CAM_SFE,
"Failed! Invalid number buffers:%d required:%d",
update_buf->wm_update->num_buf, sfe_out_data->num_wm);
return -EINVAL;
}
for (i = 0; i < sfe_out_data->num_wm; i++) {
wm_data = (struct cam_sfe_bus_wr_wm_resource_data *)
sfe_out_data->wm_res[i].res_priv;
val = (wm_data->height << 16) | wm_data->width;
cam_io_w_mb(val,
wm_data->common_data->mem_base +
wm_data->hw_regs->image_cfg_0);
CAM_DBG(CAM_SFE, "WM:%d image height and width 0x%X",
wm_data->index, val);
/* For initial configuration program all bus registers */
stride = update_buf->wm_update->stride;
slice_h = update_buf->wm_update->slice_height;
val = stride;
CAM_DBG(CAM_SFE, "before stride %d", val);
val = ALIGNUP(val, 16);
if (val != stride &&
val != wm_data->stride)
CAM_WARN(CAM_SFE, "Warning stride %u expected %u",
stride, val);
if (wm_data->stride != val || !wm_data->init_cfg_done) {
cam_io_w_mb(stride,
wm_data->common_data->mem_base +
wm_data->hw_regs->image_cfg_2);
wm_data->stride = val;
CAM_DBG(CAM_SFE, "WM:%d image stride 0x%X",
wm_data->index, val);
}
frame_inc = stride * slice_h;
if (!(wm_data->en_cfg & (0x3 << 16))) {
cam_io_w_mb(wm_data->h_init,
wm_data->common_data->mem_base +
wm_data->hw_regs->image_cfg_1);
CAM_DBG(CAM_SFE, "WM:%d h_init 0x%X",
wm_data->index, wm_data->h_init);
}
if (wm_data->index > 7)
loop_size = wm_data->irq_subsample_period + 1;
else
loop_size = 1;
/* WM Image address */
for (k = 0; k < loop_size; k++) {
if (wm_data->en_cfg & (0x3 << 16))
cam_io_w_mb((update_buf->wm_update->image_buf[i] +
wm_data->offset + k * frame_inc),
wm_data->common_data->mem_base +
wm_data->hw_regs->image_addr);
else
cam_io_w_mb((update_buf->wm_update->image_buf[i] +
k * frame_inc),
wm_data->common_data->mem_base +
wm_data->hw_regs->image_addr);
}
cam_io_w_mb(frame_inc,
wm_data->common_data->mem_base +
wm_data->hw_regs->frame_incr);
CAM_DBG(CAM_SFE, "WM:%d frame_inc %d",
wm_data->index, frame_inc);
/* enable the WM */
cam_io_w_mb(wm_data->en_cfg,
wm_data->common_data->mem_base +
wm_data->hw_regs->cfg);
CAM_DBG(CAM_SFE, "WM:%d en_cfg 0x%X",
wm_data->index, wm_data->en_cfg);
/* set initial configuration done */
if (!wm_data->init_cfg_done)
wm_data->init_cfg_done = true;
}
return 0;
}
static int cam_sfe_bus_wr_update_hfr(void *priv, void *cmd_args,
uint32_t arg_size)
{
@@ -2330,6 +2445,9 @@ static int cam_sfe_bus_wr_process_cmd(
case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
rc = cam_sfe_bus_wr_update_wm(priv, cmd_args, arg_size);
break;
case CAM_ISP_HW_CMD_BUF_UPDATE:
rc = cam_sfe_bus_wr_config_wm(priv, cmd_args, arg_size);
break;
case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
rc = cam_sfe_bus_wr_update_hfr(priv, cmd_args, arg_size);
break;