diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 7f34b8d915..a8a50c92bf 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -155,6 +155,7 @@ ktime_t sde_encoder_calc_last_vsync_timestamp(struct drm_encoder *drm_enc) u64 vsync_counter, qtmr_counter, hw_diff, hw_diff_ns, frametime_ns; ktime_t tvblank, cur_time; struct intf_status intf_status = {0}; + unsigned long features; u32 fps; sde_enc = to_sde_encoder_virt(drm_enc); @@ -167,11 +168,14 @@ ktime_t sde_encoder_calc_last_vsync_timestamp(struct drm_encoder *drm_enc) && !sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE))) return 0; + features = cur_master->hw_intf->cap->features; + /* - * avoid calculation and rely on ktime_get, if programmable fetch is enabled - * as the HW VSYNC timestamp will be updated at panel vsync and not at MDP VSYNC + * if MDP VSYNC HW timestamp is not supported and if programmable fetch is enabled, + * avoid calculation and rely on ktime_get, as the HW vsync timestamp will be updated + * at panel vsync and not at MDP VSYNC */ - if (cur_master->hw_intf->ops.get_status) { + if (!test_bit(SDE_INTF_MDP_VSYNC_TS, &features) && cur_master->hw_intf->ops.get_status) { cur_master->hw_intf->ops.get_status(cur_master->hw_intf, &intf_status); if (intf_status.is_prog_fetch_en) return 0; diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index 2a606a3206..25950db1b7 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -2480,9 +2480,13 @@ static int sde_intf_parse_dt(struct device_node *np, if (SDE_HW_MAJOR(sde_cfg->hw_rev) >= SDE_HW_MAJOR(SDE_HW_VER_810)) { set_bit(SDE_INTF_WD_TIMER, &intf->features); set_bit(SDE_INTF_RESET_COUNTER, &intf->features); - set_bit(SDE_INTF_VSYNC_TIMESTAMP, &intf->features); + set_bit(SDE_INTF_PANEL_VSYNC_TS, &intf->features); set_bit(SDE_INTF_AVR_STATUS, &intf->features); } + + if (SDE_HW_MAJOR(sde_cfg->hw_rev) >= SDE_HW_MAJOR(SDE_HW_VER_900)) { + set_bit(SDE_INTF_MDP_VSYNC_TS, &intf->features); + } } end: diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 8d6a2b5cb7..d0e5e9973e 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -540,7 +540,8 @@ enum { * @SDE_INTF_WD_TIMER INTF block has WD Timer support * @SDE_INTF_STATUS INTF block has INTF_STATUS register * @SDE_INTF_RESET_COUNTER INTF block has frame/line counter reset support - * @SDE_INTF_VSYNC_TIMESTAMP INTF block has vsync timestamp logged + * @SDE_INTF_PANEL_VSYNC_TS INTF block has panel vsync timestamp logged + * @SDE_INTF_MDP_VSYNC_TS INTF block has mdp vsync timestamp logged * @SDE_INTF_AVR_STATUS INTF block has AVR_STATUS field in AVR_CONTROL register * @SDE_INTF_MAX */ @@ -551,7 +552,8 @@ enum { SDE_INTF_WD_TIMER, SDE_INTF_STATUS, SDE_INTF_RESET_COUNTER, - SDE_INTF_VSYNC_TIMESTAMP, + SDE_INTF_PANEL_VSYNC_TS, + SDE_INTF_MDP_VSYNC_TS, SDE_INTF_AVR_STATUS, SDE_INTF_MAX }; diff --git a/msm/sde/sde_hw_intf.c b/msm/sde/sde_hw_intf.c index ffab1fab24..0d80773ec5 100644 --- a/msm/sde/sde_hw_intf.c +++ b/msm/sde/sde_hw_intf.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include @@ -64,6 +65,8 @@ #define INTF_VSYNC_TIMESTAMP_CTRL 0x210 #define INTF_VSYNC_TIMESTAMP0 0x214 #define INTF_VSYNC_TIMESTAMP1 0x218 +#define INTF_MDP_VSYNC_TIMESTAMP0 0x21C +#define INTF_MDP_VSYNC_TIMESTAMP1 0x220 #define INTF_WD_TIMER_0_CTL 0x230 #define INTF_WD_TIMER_0_CTL2 0x234 #define INTF_WD_TIMER_0_LOAD_VALUE 0x238 @@ -221,9 +224,18 @@ static u64 sde_hw_intf_get_vsync_timestamp(struct sde_hw_intf *ctx) struct sde_hw_blk_reg_map *c = &ctx->hw; u32 timestamp_lo, timestamp_hi; u64 timestamp = 0; + u32 reg_ts_0, reg_ts_1; - timestamp_hi = SDE_REG_READ(c, INTF_VSYNC_TIMESTAMP1); - timestamp_lo = SDE_REG_READ(c, INTF_VSYNC_TIMESTAMP0); + if (ctx->cap->features & BIT(SDE_INTF_MDP_VSYNC_TS)) { + reg_ts_0 = INTF_MDP_VSYNC_TIMESTAMP0; + reg_ts_1 = INTF_MDP_VSYNC_TIMESTAMP1; + } else { + reg_ts_0 = INTF_VSYNC_TIMESTAMP0; + reg_ts_1 = INTF_VSYNC_TIMESTAMP1; + } + + timestamp_hi = SDE_REG_READ(c, reg_ts_1); + timestamp_lo = SDE_REG_READ(c, reg_ts_0); timestamp = timestamp_hi; timestamp = (timestamp << 32) | timestamp_lo; @@ -413,7 +425,7 @@ static void sde_hw_intf_enable_timing_engine( /* Note: Display interface select is handled in top block hw layer */ SDE_REG_WRITE(c, INTF_TIMING_ENGINE_EN, enable != 0); - if (enable && (intf->cap->features & BIT(SDE_INTF_VSYNC_TIMESTAMP))) + if (enable && (intf->cap->features & (BIT(SDE_INTF_PANEL_VSYNC_TS) | BIT(SDE_INTF_MDP_VSYNC_TS)))) SDE_REG_WRITE(c, INTF_VSYNC_TIMESTAMP_CTRL, BIT(0)); } @@ -706,7 +718,7 @@ static int sde_hw_intf_enable_te(struct sde_hw_intf *intf, bool enable) c = &intf->hw; SDE_REG_WRITE(c, INTF_TEAR_TEAR_CHECK_EN, enable); - if (enable && (intf->cap->features & BIT(SDE_INTF_VSYNC_TIMESTAMP))) + if (enable && (intf->cap->features & (BIT(SDE_INTF_PANEL_VSYNC_TS) | BIT(SDE_INTF_MDP_VSYNC_TS)))) SDE_REG_WRITE(c, INTF_VSYNC_TIMESTAMP_CTRL, BIT(0)); return 0; @@ -901,7 +913,7 @@ static void _setup_intf_ops(struct sde_hw_intf_ops *ops, if (cap & BIT(SDE_INTF_RESET_COUNTER)) ops->reset_counter = sde_hw_intf_reset_counter; - if (cap & BIT(SDE_INTF_VSYNC_TIMESTAMP)) + if (cap & (BIT(SDE_INTF_PANEL_VSYNC_TS) | BIT(SDE_INTF_MDP_VSYNC_TS))) ops->get_vsync_timestamp = sde_hw_intf_get_vsync_timestamp; }