Przeglądaj źródła

msm: camera: tfe: Add support to Recover missed SOF timestamp

In case SOF interrupt is not received by the camera driver, we can
recover the missing SOF timestamp for the frame at epoch using the
previous and current SOF timestamp from CSID.

CRs-Fixed: 3232845
Change-Id: Id41860e125c26f2175c5180713c9b3c41741491b
Signed-off-by: Chandan Kumar Jha <[email protected]>
Signed-off-by: Pranav Sanwal <[email protected]>
Chandan Jha 1 rok temu
rodzic
commit
f1cb553de2

+ 19 - 5
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c

@@ -57,6 +57,9 @@ static void *cam_tfe_hw_mgr_get_hw_intf(
 	return hw_mgr->tfe_devices[base->idx]->hw_intf;
 }
 
+static int cam_tfe_mgr_cmd_get_sof_timestamp(struct cam_tfe_hw_mgr_ctx *tfe_ctx,
+	uint64_t *time_stamp, uint64_t *boot_time_stamp, uint64_t *prev_time_stamp);
+
 static int cam_tfe_mgr_regspace_data_cb(uint32_t reg_base_type,
 	void *hw_mgr_ctx, struct cam_hw_soc_info **soc_info_ptr,
 	uint32_t *reg_base_idx)
@@ -5055,9 +5058,15 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 				sizeof(struct cam_tfe_hw_comp_record) *
 				CAM_TFE_BUS_COMP_NUM_MAX);
 			break;
+		case CAM_ISP_HW_MGR_GET_SOF_TS:
+			rc = cam_tfe_mgr_cmd_get_sof_timestamp(ctx,
+				&isp_hw_cmd_args->u.sof_ts.curr,
+				&isp_hw_cmd_args->u.sof_ts.boot,
+				&isp_hw_cmd_args->u.sof_ts.prev);
+			break;
 		default:
-			CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
-				hw_cmd_args->cmd_type);
+			CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x, ISP HW mgr cmd:0x%x",
+				hw_cmd_args->cmd_type, isp_hw_cmd_args->cmd_type);
 			rc = -EINVAL;
 			break;
 		}
@@ -5109,7 +5118,8 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 static int cam_tfe_mgr_cmd_get_sof_timestamp(
 	struct cam_tfe_hw_mgr_ctx            *tfe_ctx,
 	uint64_t                             *time_stamp,
-	uint64_t                             *boot_time_stamp)
+	uint64_t                             *boot_time_stamp,
+	uint64_t                             *prev_time_stamp)
 {
 	int                                        rc = -EINVAL;
 	uint32_t                                   i;
@@ -5142,6 +5152,7 @@ static int cam_tfe_mgr_cmd_get_sof_timestamp(
 
 			csid_get_time.node_res =
 				hw_mgr_res->hw_res[i];
+			csid_get_time.get_prev_timestamp = (prev_time_stamp != NULL);
 			rc = hw_intf->hw_ops.process_cmd(
 				hw_intf->hw_priv,
 				CAM_TFE_CSID_CMD_GET_TIME_STAMP,
@@ -5153,6 +5164,9 @@ static int cam_tfe_mgr_cmd_get_sof_timestamp(
 					csid_get_time.time_stamp_val;
 				*boot_time_stamp =
 					csid_get_time.boot_timestamp;
+				if (prev_time_stamp)
+					*prev_time_stamp =
+						csid_get_time.prev_time_stamp_val;
 				break;
 			}
 		}
@@ -5670,7 +5684,7 @@ static int cam_tfe_hw_mgr_handle_hw_sof(
 	case CAM_ISP_HW_TFE_IN_CAMIF:
 		cam_tfe_mgr_cmd_get_sof_timestamp(tfe_hw_mgr_ctx,
 			&sof_done_event_data.timestamp,
-			&sof_done_event_data.boot_time);
+			&sof_done_event_data.boot_time, NULL);
 
 		if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending))
 			break;
@@ -5687,7 +5701,7 @@ static int cam_tfe_hw_mgr_handle_hw_sof(
 			break;
 		cam_tfe_mgr_cmd_get_sof_timestamp(tfe_hw_mgr_ctx,
 			&sof_done_event_data.timestamp,
-			&sof_done_event_data.boot_time);
+			&sof_done_event_data.boot_time, NULL);
 		if (atomic_read(&tfe_hw_mgr_ctx->overflow_pending))
 			break;
 		tfe_hw_irq_sof_cb(tfe_hw_mgr_ctx->common.cb_priv,

+ 7 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CAM_TFE_CSID_HW_INTF_H_
@@ -215,13 +216,17 @@ struct cam_tfe_csid_reset_cfg_args {
 /**
  * struct cam_csid_get_time_stamp_args-  time stamp capture arguments
  * @res_node :       Resource to get the time stamp
- * @time_stamp_val : Captured time stamp
- * @boot_timestamp : Boot time stamp
+ * @time_stamp_val      : Captured time stamp
+ * @boot_timestamp      : Boot time stamp
+ * @prev_time_stamp_val : previous captured time stamp
+ * @get_prev_timestamp  : flag to fetch previous captured time stamp from hardware
  */
 struct cam_tfe_csid_get_time_stamp_args {
 	struct cam_isp_resource_node      *node_res;
 	uint64_t                           time_stamp_val;
 	uint64_t                           boot_timestamp;
+	uint64_t                           prev_time_stamp_val;
+	bool                               get_prev_timestamp;
 };
 
 /**

+ 22 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c

@@ -2078,7 +2078,7 @@ static int cam_tfe_csid_get_time_stamp(
 	struct cam_hw_soc_info                     *soc_info;
 	const struct cam_tfe_csid_rdi_reg_offset   *rdi_reg;
 	struct timespec64 ts;
-	uint32_t  id, torn;
+	uint32_t  id, torn, prev_torn;
 	uint64_t  time_delta;
 
 	time_stamp = (struct cam_tfe_csid_get_time_stamp_args  *)cmd_args;
@@ -2107,6 +2107,13 @@ static int cam_tfe_csid_get_time_stamp(
 			csid_reg->ipp_reg->csid_pxl_timestamp_curr1_sof_addr,
 			csid_reg->ipp_reg->csid_pxl_timestamp_curr0_sof_addr,
 			&time_stamp->time_stamp_val);
+		if (time_stamp->get_prev_timestamp) {
+			prev_torn = __cam_tfe_csid_read_timestamp(
+				soc_info->reg_map[0].mem_base,
+				csid_reg->ipp_reg->csid_pxl_timestamp_perv1_sof_addr,
+				csid_reg->ipp_reg->csid_pxl_timestamp_perv0_sof_addr,
+				&time_stamp->prev_time_stamp_val);
+		}
 	} else {
 		id = res->res_id;
 		rdi_reg = csid_reg->rdi_reg[id];
@@ -2115,6 +2122,13 @@ static int cam_tfe_csid_get_time_stamp(
 			rdi_reg->csid_rdi_timestamp_curr1_sof_addr,
 			rdi_reg->csid_rdi_timestamp_curr0_sof_addr,
 			&time_stamp->time_stamp_val);
+		if (time_stamp->get_prev_timestamp) {
+			prev_torn = __cam_tfe_csid_read_timestamp(
+				soc_info->reg_map[0].mem_base,
+				rdi_reg->csid_rdi_timestamp_prev1_sof_addr,
+				rdi_reg->csid_rdi_timestamp_prev0_sof_addr,
+				&time_stamp->prev_time_stamp_val);
+		}
 	}
 
 	time_stamp->time_stamp_val = mul_u64_u32_div(
@@ -2122,6 +2136,13 @@ static int cam_tfe_csid_get_time_stamp(
 		CAM_TFE_CSID_QTIMER_MUL_FACTOR,
 		CAM_TFE_CSID_QTIMER_DIV_FACTOR);
 
+	if (time_stamp->get_prev_timestamp) {
+		time_stamp->prev_time_stamp_val = mul_u64_u32_div(
+			time_stamp->prev_time_stamp_val,
+			CAM_TFE_CSID_QTIMER_MUL_FACTOR,
+			CAM_TFE_CSID_QTIMER_DIV_FACTOR);
+	}
+
 	if (!csid_hw->prev_boot_timestamp) {
 		ktime_get_boottime_ts64(&ts);
 		time_stamp->boot_timestamp =