Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1beadb14 authored by Ravikishore Pampana's avatar Ravikishore Pampana
Browse files

msm: camera: tfe: Handle sof monotonic boot time stamp



Modify the sof monotonic boot timestamp logic. Boot time
stamp difference between two frames should not change,
it should be same as qtime csid time stamp difference.
So modified logic to give proper boot time stamp with no
difference in the successive frames, the difference of sof
time stamp taken from qtime stamp value.
Delayed IRQ handling can lead to torn read of timestamp
register (LSB from nth frame and MSB from n+1th frame).
This change tries to detect torn read cases and corrects
timestamp close to the actual value.

CRs-Fixed: 2688271
Change-Id: I1dc75629887cfcf971d51a7dae6ea28624d272f1
Signed-off-by: default avatarRavikishore Pampana <rpampana@codeaurora.org>
parent 526970e7
Loading
Loading
Loading
Loading
+33 −31
Original line number Diff line number Diff line
@@ -4467,7 +4467,9 @@ static int cam_tfe_mgr_cmd_get_sof_timestamp(
	struct cam_hw_intf                        *hw_intf;
	struct cam_tfe_csid_get_time_stamp_args    csid_get_time;

	list_for_each_entry(hw_mgr_res, &tfe_ctx->res_list_tfe_csid, list) {
	hw_mgr_res = list_first_entry(&tfe_ctx->res_list_tfe_csid,
		struct cam_isp_hw_mgr_res, list);

	for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
		if (!hw_mgr_res->hw_res[i])
			continue;
@@ -4501,7 +4503,7 @@ static int cam_tfe_mgr_cmd_get_sof_timestamp(
					csid_get_time.time_stamp_val;
				*boot_time_stamp =
					csid_get_time.boot_timestamp;
				}
				break;
			}
		}
	}
+70 −19
Original line number Diff line number Diff line
@@ -345,6 +345,7 @@ static int cam_tfe_csid_global_reset(struct cam_tfe_csid_hw *csid_hw)
		CAM_ERR(CAM_ISP, "CSID:%d IRQ value after reset rc = %d",
			csid_hw->hw_intf->hw_idx, val);
	csid_hw->error_irq_count = 0;
	csid_hw->prev_boot_timestamp = 0;

	return rc;
}
@@ -998,6 +999,7 @@ static int cam_tfe_csid_disable_hw(struct cam_tfe_csid_hw *csid_hw)
	spin_unlock_irqrestore(&csid_hw->spin_lock, flags);
	csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
	csid_hw->error_irq_count = 0;
	csid_hw->prev_boot_timestamp = 0;

	return rc;
}
@@ -1612,6 +1614,25 @@ static int cam_tfe_csid_poll_stop_status(
	return rc;
}

static int __cam_tfe_csid_read_timestamp(void __iomem *base,
	uint32_t msb_offset, uint32_t lsb_offset, uint64_t *timestamp)
{
	uint32_t lsb, msb, tmp, torn = 0;

	msb = cam_io_r_mb(base + msb_offset);
	do {
		tmp = msb;
		torn++;
		lsb = cam_io_r_mb(base + lsb_offset);
		msb = cam_io_r_mb(base + msb_offset);
	} while (tmp != msb);

	*timestamp = msb;
	*timestamp = (*timestamp << 32) | lsb;

	return (torn > 1);
}

static int cam_tfe_csid_get_time_stamp(
		struct cam_tfe_csid_hw   *csid_hw, void *cmd_args)
{
@@ -1621,7 +1642,8 @@ 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  time_32, id;
	uint32_t  id, torn;
	uint64_t  time_delta;

	time_stamp = (struct cam_tfe_csid_get_time_stamp_args  *)cmd_args;
	res = time_stamp->node_res;
@@ -1644,33 +1666,61 @@ static int cam_tfe_csid_get_time_stamp(
	}

	if (res->res_id == CAM_TFE_CSID_PATH_RES_IPP) {
		time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
			csid_reg->ipp_reg->csid_pxl_timestamp_curr1_sof_addr);
		time_stamp->time_stamp_val = (uint64_t) time_32;
		time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32;
		time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
			csid_reg->ipp_reg->csid_pxl_timestamp_curr0_sof_addr);
		torn = __cam_tfe_csid_read_timestamp(
			soc_info->reg_map[0].mem_base,
			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);
	} else {
		id = res->res_id;
		rdi_reg = csid_reg->rdi_reg[id];
		time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
			rdi_reg->csid_rdi_timestamp_curr1_sof_addr);
		time_stamp->time_stamp_val = (uint64_t) time_32;
		time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32;

		time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
			rdi_reg->csid_rdi_timestamp_curr0_sof_addr);
		torn = __cam_tfe_csid_read_timestamp(
			soc_info->reg_map[0].mem_base,
			rdi_reg->csid_rdi_timestamp_curr1_sof_addr,
			rdi_reg->csid_rdi_timestamp_curr0_sof_addr,
			&time_stamp->time_stamp_val);
	}

	time_stamp->time_stamp_val |= (uint64_t) time_32;
	time_stamp->time_stamp_val = mul_u64_u32_div(
		time_stamp->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 = (uint64_t)((ts.tv_sec * 1000000000) +
		time_stamp->boot_timestamp =
			(uint64_t)((ts.tv_sec * 1000000000) +
			ts.tv_nsec);
		csid_hw->prev_qtimer_ts = 0;
		CAM_DBG(CAM_ISP, "timestamp:%lld",
			time_stamp->boot_timestamp);
	} else {
		time_delta = time_stamp->time_stamp_val -
			csid_hw->prev_qtimer_ts;

		if (csid_hw->prev_boot_timestamp >
			U64_MAX - time_delta) {
			CAM_WARN(CAM_ISP, "boottimestamp overflowed");
			CAM_INFO(CAM_ISP,
			"currQTimer %lx prevQTimer %lx prevBootTimer %lx torn %d",
				time_stamp->time_stamp_val,
				csid_hw->prev_qtimer_ts,
				csid_hw->prev_boot_timestamp, torn);
			return -EINVAL;
		}

		time_stamp->boot_timestamp =
			csid_hw->prev_boot_timestamp + time_delta;
	}

	CAM_DBG(CAM_ISP,
	"currQTimer %lx prevQTimer %lx currBootTimer %lx prevBootTimer %lx torn %d",
		time_stamp->time_stamp_val,
		csid_hw->prev_qtimer_ts, time_stamp->boot_timestamp,
		csid_hw->prev_boot_timestamp, torn);

	csid_hw->prev_qtimer_ts = time_stamp->time_stamp_val;
	csid_hw->prev_boot_timestamp = time_stamp->boot_timestamp;

	return 0;
}
@@ -2997,6 +3047,7 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,

	tfe_csid_hw->csid_debug = 0;
	tfe_csid_hw->error_irq_count = 0;
	tfe_csid_hw->prev_boot_timestamp = 0;

	rc = cam_tfe_csid_disable_soc_resources(
		&tfe_csid_hw->hw_info->soc_info);
+4 −0
Original line number Diff line number Diff line
@@ -387,6 +387,8 @@ struct cam_tfe_csid_path_cfg {
 * @ppi_hw_intf               interface to ppi hardware
 * @ppi_enabled               flag to specify if the hardware has ppi bridge
 *                            or not
 * @prev_boot_timestamp       previous frame bootime stamp
 * @prev_qtimer_ts            previous frame qtimer csid timestamp
 *
 */
struct cam_tfe_csid_hw {
@@ -415,6 +417,8 @@ struct cam_tfe_csid_hw {
	void                               *event_cb_priv;
	struct cam_hw_intf                 *ppi_hw_intf[CAM_CSID_PPI_HW_MAX];
	bool                                ppi_enable;
	uint64_t                            prev_boot_timestamp;
	uint64_t                            prev_qtimer_ts;
};

int cam_tfe_csid_hw_probe_init(struct cam_hw_intf  *csid_hw_intf,