msm: camera: isp: Add support to obtain frame index

This change captures the frame index as part of the IFE top
register space at every epoch event. The index is then notified
to userspace as part of shutter notification.

CRs-Fixed: 2524308
Change-Id: Iac510c452f9ceda86e9f7d69528f22f81e614974
Signed-off-by: Karthik Anantha Ram <kartanan@codeaurora.org>
This commit is contained in:
Karthik Anantha Ram
2019-09-09 22:54:06 -07:00
committed by Gerrit - the friendly Code Review server
parent 0894c95dda
commit 5ddf0a5cfb
10 changed files with 126 additions and 50 deletions

View File

@@ -470,6 +470,7 @@ static void __cam_isp_ctx_send_sof_boot_timestamp(
req_msg.u.frame_msg.timestamp = ctx_isp->boot_timestamp;
req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl;
req_msg.u.frame_msg.sof_status = sof_event_status;
req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta;
CAM_DBG(CAM_ISP,
"request id:%lld frame number:%lld boot time stamp:0x%llx",
@@ -497,6 +498,7 @@ static void __cam_isp_ctx_send_sof_timestamp(
req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val;
req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl;
req_msg.u.frame_msg.sof_status = sof_event_status;
req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta;
CAM_DBG(CAM_ISP,
"request id:%lld frame number:%lld SOF time stamp:0x%llx",
@@ -863,11 +865,20 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
int rc = 0;
uint64_t request_id = 0;
struct cam_req_mgr_trigger_notify notify;
struct cam_context *ctx = ctx_isp->base;
struct cam_ctx_request *req;
struct cam_isp_ctx_req *req_isp;
uint64_t request_id = 0;
struct cam_isp_hw_epoch_event_data *epoch_done_event_data =
(struct cam_isp_hw_epoch_event_data *)evt_data;
if (!evt_data) {
CAM_ERR(CAM_ISP, "invalid event data");
return -EINVAL;
}
ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta;
/*
* notify reqmgr with sof signal. Note, due to scheduling delay
@@ -1082,11 +1093,19 @@ end:
static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
void *evt_data)
{
struct cam_ctx_request *req;
struct cam_isp_ctx_req *req_isp;
struct cam_context *ctx = ctx_isp->base;
uint64_t request_id = 0;
uint64_t request_id = 0;
struct cam_ctx_request *req;
struct cam_isp_ctx_req *req_isp;
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_hw_epoch_event_data *epoch_done_event_data =
(struct cam_isp_hw_epoch_event_data *)evt_data;
if (!evt_data) {
CAM_ERR(CAM_ISP, "invalid event data");
return -EINVAL;
}
ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta;
if (list_empty(&ctx->wait_req_list)) {
/*
* If no wait req in epoch, this is an error case.
@@ -1248,10 +1267,19 @@ static int __cam_isp_ctx_buf_done_in_bubble(
static int __cam_isp_ctx_epoch_in_bubble_applied(
struct cam_isp_context *ctx_isp, void *evt_data)
{
struct cam_ctx_request *req;
struct cam_isp_ctx_req *req_isp;
struct cam_context *ctx = ctx_isp->base;
uint64_t request_id = 0;
struct cam_ctx_request *req;
struct cam_isp_ctx_req *req_isp;
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_hw_epoch_event_data *epoch_done_event_data =
(struct cam_isp_hw_epoch_event_data *)evt_data;
if (!evt_data) {
CAM_ERR(CAM_ISP, "invalid event data");
return -EINVAL;
}
ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta;
/*
* This means we missed the reg upd ack. So we need to

View File

@@ -166,6 +166,8 @@ struct cam_isp_context_req_id_info {
*
* @base: Common context object pointer
* @frame_id: Frame id tracking for the isp context
* @frame_id_meta: Frame id read every epoch for the ctx
* meta from the sensor
* @substate_actiavted: Current substate for the activated state.
* @process_bubble: Atomic variable to check if ctx is still
* processing bubble.
@@ -195,27 +197,28 @@ struct cam_isp_context_req_id_info {
*
*/
struct cam_isp_context {
struct cam_context *base;
struct cam_context *base;
int64_t frame_id;
enum cam_isp_ctx_activated_substate substate_activated;
atomic_t process_bubble;
uint32_t bubble_frame_cnt;
struct cam_ctx_ops *substate_machine;
struct cam_isp_ctx_irq_ops *substate_machine_irq;
int64_t frame_id;
uint32_t frame_id_meta;
uint32_t substate_activated;
atomic_t process_bubble;
uint32_t bubble_frame_cnt;
struct cam_ctx_ops *substate_machine;
struct cam_isp_ctx_irq_ops *substate_machine_irq;
struct cam_ctx_request req_base[CAM_CTX_REQ_MAX];
struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX];
struct cam_ctx_request req_base[CAM_CTX_REQ_MAX];
struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX];
void *hw_ctx;
uint64_t sof_timestamp_val;
uint64_t boot_timestamp;
int32_t active_req_cnt;
int64_t reported_req_id;
uint32_t subscribe_event;
int64_t last_applied_req_id;
atomic64_t state_monitor_head;
struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[
void *hw_ctx;
uint64_t sof_timestamp_val;
uint64_t boot_timestamp;
int32_t active_req_cnt;
int64_t reported_req_id;
uint32_t subscribe_event;
int64_t last_applied_req_id;
atomic64_t state_monitor_head;
struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[
CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES];
struct cam_isp_context_req_id_info req_info;
bool rdi_only_context;

View File

@@ -4775,29 +4775,36 @@ static int cam_isp_blob_core_cfg_update(
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
clk_rate = 0;
if (!hw_mgr_res->hw_res[i] ||
hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF)
if (!hw_mgr_res->hw_res[i])
continue;
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
if (hw_intf && hw_intf->hw_ops.process_cmd) {
vfe_core_config.node_res =
hw_mgr_res->hw_res[i];
if ((hw_mgr_res->res_id ==
CAM_ISP_HW_VFE_IN_CAMIF) ||
(hw_mgr_res->res_id ==
CAM_ISP_HW_VFE_IN_PDLIB)) {
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
if (hw_intf && hw_intf->hw_ops.process_cmd) {
vfe_core_config.node_res =
hw_mgr_res->hw_res[i];
memcpy(&vfe_core_config.core_config,
core_config,
sizeof(struct cam_isp_core_config));
memcpy(&vfe_core_config.core_config,
core_config,
sizeof(
struct cam_isp_core_config));
rc = hw_intf->hw_ops.process_cmd(
hw_intf->hw_priv,
CAM_ISP_HW_CMD_CORE_CONFIG,
&vfe_core_config,
sizeof(
struct cam_vfe_core_config_args));
if (rc)
CAM_ERR(CAM_ISP, "Core cfg parse fail");
} else {
CAM_WARN(CAM_ISP, "NULL hw_intf!");
rc = hw_intf->hw_ops.process_cmd(
hw_intf->hw_priv,
CAM_ISP_HW_CMD_CORE_CONFIG,
&vfe_core_config,
sizeof(
struct cam_vfe_core_config_args)
);
if (rc)
CAM_ERR(CAM_ISP,
"Core cfg parse fail");
} else {
CAM_WARN(CAM_ISP, "NULL hw_intf!");
}
}
}
}
@@ -6434,6 +6441,9 @@ static int cam_ife_hw_mgr_handle_hw_epoch(
if (!rc) {
if (atomic_read(&ife_hw_mgr_ctx->overflow_pending))
break;
epoch_done_event_data.frame_id_meta =
event_info->th_reg_val;
ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv,
CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data);
}

View File

@@ -170,10 +170,11 @@ struct cam_isp_hw_reg_update_event_data {
* struct cam_isp_hw_epoch_event_data - Event payload for CAM_HW_EVENT_EPOCH
*
* @timestamp: Time stamp for the epoch event
*
* @frame_id_meta: Frame id value corresponding to this frame
*/
struct cam_isp_hw_epoch_event_data {
uint64_t timestamp;
uint32_t frame_id_meta;
};
/**

View File

@@ -174,6 +174,7 @@ struct cam_isp_resource_node {
* @res_id: Unique resource ID
* @hw_idx: IFE hw index
* @err_type: Error type if any
* @th_reg_val: Any critical register value captured during th
*
*/
struct cam_isp_hw_event_info {
@@ -181,6 +182,7 @@ struct cam_isp_hw_event_info {
uint32_t res_id;
uint32_t hw_idx;
uint32_t err_type;
uint32_t th_reg_val;
};
/*

View File

@@ -263,11 +263,15 @@ struct cam_vfe_bw_control_args {
* @list: list_head node for the payload
* @irq_reg_val: IRQ and Error register values, read when IRQ was
* handled
* @th_reg_val: Value of any critical register that needs to be
* read at th to avoid any latencies in bh processing
*
* @ts: Timestamp
*/
struct cam_vfe_top_irq_evt_payload {
struct list_head list;
uint32_t irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX];
uint32_t th_reg_val;
struct cam_isp_timestamp ts;
};

View File

@@ -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.
*/
@@ -77,6 +77,7 @@ static struct cam_vfe_camif_ver3_reg_data vfe_480_camif_reg_data = {
.error_irq_mask0 = 0x82000200,
.error_irq_mask2 = 0x30301F80,
.subscribe_irq_mask1 = 0x00000007,
.frame_id_irq_mask = 0x400,
.enable_diagnostic_hw = 0x1,
.pp_camif_cfg_en_shift = 0,
.pp_camif_cfg_ife_out_en_shift = 8,
@@ -101,7 +102,7 @@ static struct cam_vfe_top_ver3_reg_offset_common vfe480_top_common_reg = {
.ahb_cgc_ovd = 0x00000024,
.noc_cgc_ovd = 0x00000028,
.trigger_cdm_events = 0x00000090,
.sbi_frame_idx = 0x00000110,
.custom_frame_idx = 0x00000110,
.dsp_status = 0x0000007C,
.diag_config = 0x00000064,
.diag_sensor_status_0 = 0x00000068,

View File

@@ -507,6 +507,9 @@ static int cam_vfe_camif_ver3_resource_start(
irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] =
rsrc_data->reg_data->sof_irq_mask;
if (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3)
irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] =
rsrc_data->reg_data->frame_id_irq_mask;
if (!rsrc_data->sof_irq_handle) {
rsrc_data->sof_irq_handle = cam_irq_controller_subscribe_irq(
@@ -1191,10 +1194,21 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id,
}
cam_isp_hw_get_timestamp(&evt_payload->ts);
evt_payload->th_reg_val = 0;
for (i = 0; i < th_payload->num_registers; i++)
evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
/* Read frame_id meta at every epoch if custom hw is enabled */
if (evt_payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1]
& camif_priv->reg_data->epoch0_irq_mask) {
if ((camif_priv->common_reg->custom_frame_idx) &&
(camif_priv->cam_common_cfg.input_mux_sel_pp & 0x3))
evt_payload->th_reg_val = cam_io_r_mb(
camif_priv->mem_base +
camif_priv->common_reg->custom_frame_idx);
}
th_payload->evt_payload_priv = evt_payload;
CAM_DBG(CAM_ISP, "Exit");
@@ -1210,6 +1224,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv,
struct cam_vfe_top_irq_evt_payload *payload;
struct cam_isp_hw_event_info evt_info;
uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0};
uint32_t val = 0;
int i = 0;
if (!handler_priv || !evt_payload_priv) {
@@ -1229,6 +1244,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv,
evt_info.hw_idx = camif_node->hw_intf->hw_idx;
evt_info.res_id = camif_node->res_id;
evt_info.res_type = camif_node->res_type;
evt_info.th_reg_val = 0;
if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1]
& camif_priv->reg_data->sof_irq_mask) {
@@ -1259,6 +1275,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv,
if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1]
& camif_priv->reg_data->epoch0_irq_mask) {
CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx);
evt_info.th_reg_val = payload->th_reg_val;
if (camif_priv->event_cb)
camif_priv->event_cb(camif_priv->priv,
@@ -1294,6 +1311,15 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv,
cam_vfe_camif_ver3_reg_dump(camif_node);
}
if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0]
& camif_priv->reg_data->frame_id_irq_mask) {
val = cam_io_r_mb(camif_priv->mem_base +
camif_priv->common_reg->custom_frame_idx);
CAM_DBG(CAM_ISP,
"VFE:%d Frame id change to: %u", evt_info.hw_idx,
val);
}
if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]) {
CAM_ERR(CAM_ISP, "VFE:%d Violation", evt_info.hw_idx);

View File

@@ -53,6 +53,7 @@ struct cam_vfe_camif_ver3_reg_data {
uint32_t error_irq_mask0;
uint32_t error_irq_mask2;
uint32_t subscribe_irq_mask1;
uint32_t frame_id_irq_mask;
uint32_t enable_diagnostic_hw;
uint32_t pp_camif_cfg_en_shift;

View File

@@ -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.
*/
#ifndef _CAM_VFE_TOP_VER3_H_
@@ -41,7 +41,7 @@ struct cam_vfe_top_ver3_reg_offset_common {
uint32_t reg_update_cmd;
uint32_t trigger_cdm_events;
uint32_t violation_status;
uint32_t sbi_frame_idx;
uint32_t custom_frame_idx;
uint32_t dsp_status;
uint32_t diag_config;
uint32_t diag_sensor_status_0;