Merge "msm: camera: tfe: Handle sof monotonic boot time stamp" into camera-kernel.lnx.4.0

This commit is contained in:
Camera Software Integration 2020-09-25 16:52:51 -07:00 • committed by Gerrit - the friendly Code Review server
commit 10729c8cf2
3 changed files with 107 additions and 50 deletions

View file

@ -4690,41 +4690,43 @@ 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) {
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
if (!hw_mgr_res->hw_res[i])
continue;
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;
/*
* Get the SOF time stamp from left resource only.
* Left resource is master for dual tfe case and
* Rdi only context case left resource only hold
* the RDI resource
*/
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
if (hw_intf->hw_ops.process_cmd) {
/*
* Get the SOF time stamp from left resource only.
* Left resource is master for dual tfe case and
* Rdi only context case left resource only hold
* the RDI resource
* Single TFE case, Get the time stamp from
* available one csid hw in the context
* Dual TFE case, get the time stamp from
* master(left) would be sufficient
*/
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
if (hw_intf->hw_ops.process_cmd) {
/*
* Single TFE case, Get the time stamp from
* available one csid hw in the context
* Dual TFE case, get the time stamp from
* master(left) would be sufficient
*/
csid_get_time.node_res =
hw_mgr_res->hw_res[i];
rc = hw_intf->hw_ops.process_cmd(
hw_intf->hw_priv,
CAM_TFE_CSID_CMD_GET_TIME_STAMP,
&csid_get_time,
sizeof(struct
cam_tfe_csid_get_time_stamp_args));
if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) {
*time_stamp =
csid_get_time.time_stamp_val;
*boot_time_stamp =
csid_get_time.boot_timestamp;
}
csid_get_time.node_res =
hw_mgr_res->hw_res[i];
rc = hw_intf->hw_ops.process_cmd(
hw_intf->hw_priv,
CAM_TFE_CSID_CMD_GET_TIME_STAMP,
&csid_get_time,
sizeof(struct
cam_tfe_csid_get_time_stamp_args));
if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) {
*time_stamp =
csid_get_time.time_stamp_val;
*boot_time_stamp =
csid_get_time.boot_timestamp;
break;
}
}
}

View file

@ -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;
}
@ -1669,16 +1671,36 @@ 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)
{
struct cam_tfe_csid_get_time_stamp_args *time_stamp;
struct cam_tfe_csid_get_time_stamp_args *time_stamp;
struct cam_isp_resource_node *res;
const struct cam_tfe_csid_reg_offset *csid_reg;
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;
@ -1701,33 +1723,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);
ktime_get_boottime_ts64(&ts);
time_stamp->boot_timestamp = (uint64_t)((ts.tv_sec * 1000000000) +
ts.tv_nsec);
if (!csid_hw->prev_boot_timestamp) {
ktime_get_boottime_ts64(&ts);
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;
}
@ -3142,6 +3192,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);

View file

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