Explorar el Código

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 <[email protected]>
Karthik Anantha Ram hace 5 años
padre
commit
5ddf0a5cfb

+ 36 - 8
drivers/cam_isp/cam_isp_context.c

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

+ 21 - 18
drivers/cam_isp/cam_isp_context.h

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

+ 31 - 21
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -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];
-
-				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!");
+			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));
+
+					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);
 		}

+ 2 - 1
drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h

@@ -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;
 };
 
 /**

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h

@@ -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;
 };
 
 /*

+ 4 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h

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

+ 3 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h

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

+ 26 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c

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

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h

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

+ 2 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h

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