disp: msm: sde: add support for mdp vsync timestamp

MDSS.9.0 adds support for mdp vsync based HW timestamps
on top the existing support for panel vsync based timestamps.

This allows us to enable vsync timestamp calculations for all the
use cases including a few corner cases (e.g. programmable fetch)
which we couldn't support with the existing HW.

This change adds the new HW register support and modifies the
timestamp read logic to use mdp vsync on supporting targets.

Change-Id: I2cb1b56ca9154174331c4fc1d8f82319b6989247
Signed-off-by: Michael Ru <mru@codeaurora.org>
Signed-off-by: Jeykumar Sankaran <quic_jeykumar@quicinc.com>
这个提交包含在:
Jeykumar Sankaran
2021-10-04 22:04:38 -07:00
父节点 24aa389edc
当前提交 fe83c42f56
修改 4 个文件,包含 33 行新增11 行删除

查看文件

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

查看文件

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

查看文件

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

查看文件

@@ -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 <linux/iopoll.h>
@@ -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;
}