From 55e80bfcf78be7d059bb5cc2e1a5f76378b59670 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Mon, 23 Jan 2023 14:47:23 -0800 Subject: [PATCH 1/3] disp: msm: sde: change INTF TE sync height based on 32-bit support Modify the default INTF TE sync threshold config in cmd-mode to 32-bit max based on the INTF TE 32-bit support. Change-Id: I963ffa8ae37bce0e85deb335609857c17e32d6b0 Signed-off-by: Veera Sundaram Sankaran --- msm/sde/sde_encoder_phys_cmd.c | 7 ++++++- msm/sde/sde_hw_intf.c | 8 +++++++- msm/sde/sde_hw_intf.h | 7 ++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index 4ff2ebce2e..955d8a138c 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -1265,7 +1265,12 @@ static void sde_encoder_phys_cmd_tearcheck_config( * disable sde hw generated TE signal, since hw TE will arrive first. * Only caveat is if due to error, we hit wrap-around. */ - tc_cfg.sync_cfg_height = 0xFFF0; + if (phys_enc->hw_intf->ops.is_te_32bit_supported + && phys_enc->hw_intf->ops.is_te_32bit_supported(phys_enc->hw_intf)) + tc_cfg.sync_cfg_height = 0xFFFFFFF0; + else + tc_cfg.sync_cfg_height = 0xFFF0; + tc_cfg.vsync_init_val = mode->vdisplay; tc_cfg.sync_threshold_start = _get_tearcheck_threshold(phys_enc); tc_cfg.sync_threshold_continue = DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE; diff --git a/msm/sde/sde_hw_intf.c b/msm/sde/sde_hw_intf.c index e2bb33de3a..ecfcf50faf 100644 --- a/msm/sde/sde_hw_intf.c +++ b/msm/sde/sde_hw_intf.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -1022,6 +1022,11 @@ static void sde_hw_intf_enable_wide_bus(struct sde_hw_intf *intf, SDE_REG_WRITE(c, INTF_CONFIG2, intf_cfg2); } +static bool sde_hw_intf_is_te_32bit_supported(struct sde_hw_intf *intf) +{ + return (intf->cap->features & BIT(SDE_INTF_TE_32BIT)); +} + static void _setup_intf_ops(struct sde_hw_intf_ops *ops, unsigned long cap) { @@ -1038,6 +1043,7 @@ static void _setup_intf_ops(struct sde_hw_intf_ops *ops, ops->avr_ctrl = sde_hw_intf_avr_ctrl; ops->enable_compressed_input = sde_hw_intf_enable_compressed_input; ops->enable_wide_bus = sde_hw_intf_enable_wide_bus; + ops->is_te_32bit_supported = sde_hw_intf_is_te_32bit_supported; if (cap & BIT(SDE_INTF_STATUS)) ops->get_status = sde_hw_intf_v1_get_status; diff --git a/msm/sde/sde_hw_intf.h b/msm/sde/sde_hw_intf.h index 828351128d..9fccea48e6 100644 --- a/msm/sde/sde_hw_intf.h +++ b/msm/sde/sde_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -267,6 +267,11 @@ struct sde_hw_intf_ops { */ void (*override_tear_rd_ptr_val)(struct sde_hw_intf *intf, u32 adjusted_linecnt); + + /** + * Check if intf supports 32-bit registers for TE + */ + bool (*is_te_32bit_supported)(struct sde_hw_intf *intf); }; struct sde_hw_intf { From 0a0dbc1220abeca0edf2abff3da547afe1e00364 Mon Sep 17 00:00:00 2001 From: Shirisha Kollapuram Date: Mon, 1 Aug 2022 12:35:19 +0530 Subject: [PATCH 2/3] disp: msm: sde: delay frame trigger to match with the EPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Time the flush bit setting to match with the expected frame rate. To achieve this, introduce a new connector property called “Expected_Present_Time”. User space will set it based on the intended content fps and AVR step, relative to the last retire fence timestamp as calculated by user space. Delay the frame trigger to match with the EPT. Change-Id: I0b86caaa53ee2e37671167acdffd22ec62b4e9ae Signed-off-by: Shirisha Kollapuram Signed-off-by: Veera Sundaram Sankaran --- msm/msm_drv.h | 3 +- msm/sde/sde_connector.c | 6 +++- msm/sde/sde_encoder.c | 61 ++++++++++++++++++++++++++++++++++++++-- msm/sde/sde_encoder.h | 2 ++ msm/sde/sde_hw_catalog.h | 2 ++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 7d235538c0..d4d0627c63 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -247,6 +247,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE, CONNECTOR_PROP_SET_PANEL_MODE, CONNECTOR_PROP_AVR_STEP, + CONNECTOR_PROP_EPT, CONNECTOR_PROP_CACHE_STATE, CONNECTOR_PROP_DSC_MODE, CONNECTOR_PROP_WB_USAGE_TYPE, diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index c336e8f595..db39d1e579 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -3175,6 +3175,10 @@ static int _sde_connector_install_properties(struct drm_device *dev, "qsync_mode", 0, 0, e_qsync_mode, ARRAY_SIZE(e_qsync_mode), 0, CONNECTOR_PROP_QSYNC_MODE); + if (test_bit(SDE_FEATURE_EPT, sde_kms->catalog->features)) + msm_property_install_range(&c_conn->property_info, + "EPT", 0x0, 0, U64_MAX, 0, + CONNECTOR_PROP_EPT); if (test_bit(SDE_FEATURE_AVR_STEP, sde_kms->catalog->features)) msm_property_install_range(&c_conn->property_info, "avr_step", 0x0, 0, U32_MAX, 0, diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 72d222734a..48655a7088 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1241,7 +1241,7 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn, { int rc = 0; u32 avr_step; - bool qsync_dirty, has_modeset; + bool qsync_dirty, has_modeset, ept; struct drm_connector_state *conn_state = &sde_conn_state->base; u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base, CONNECTOR_PROP_QSYNC_MODE); @@ -1249,9 +1249,12 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn, has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state, conn_state->crtc); qsync_dirty = msm_property_is_dirty(&sde_conn->property_info, &sde_conn_state->property_state, CONNECTOR_PROP_QSYNC_MODE); + ept = msm_property_is_dirty(&sde_conn->property_info, + &sde_conn_state->property_state, CONNECTOR_PROP_EPT); - if (has_modeset && qsync_dirty && (msm_is_mode_seamless_poms(&sde_conn_state->msm_mode) || - msm_is_mode_seamless_dyn_clk(&sde_conn_state->msm_mode))) { + if (has_modeset && (qsync_dirty || ept) && + (msm_is_mode_seamless_poms(&sde_conn_state->msm_mode) || + msm_is_mode_seamless_dyn_clk(&sde_conn_state->msm_mode))) { SDE_ERROR("invalid qsync update during modeset priv flag:%x\n", sde_conn_state->msm_mode.private_flags); return -EINVAL; @@ -4642,6 +4645,56 @@ static int _sde_encoder_prepare_for_kickoff_processing(struct drm_encoder *drm_e return ret; } +void _sde_encoder_delay_kickoff_processing(struct sde_encoder_virt *sde_enc) +{ + ktime_t current_ts, ept_ts; + u32 avr_step_fps, min_fps = 0, qsync_mode; + u64 timeout_us = 0, ept; + struct drm_connector *drm_conn; + + if (!sde_enc->cur_master || !sde_enc->cur_master->connector) + return; + + drm_conn = sde_enc->cur_master->connector; + ept = sde_connector_get_property(drm_conn->state, CONNECTOR_PROP_EPT); + if (!ept) + return; + + avr_step_fps = sde_connector_get_avr_step(drm_conn); + qsync_mode = sde_connector_get_property(drm_conn->state, CONNECTOR_PROP_QSYNC_MODE); + if (qsync_mode) + _sde_encoder_get_qsync_fps_callback(&sde_enc->base, &min_fps, drm_conn->state); + /* use min qsync fps, if feature is enabled; otherwise min default fps */ + min_fps = min_fps ? min_fps : DEFAULT_MIN_FPS; + + current_ts = ktime_get_ns(); + /* ept is in ns and avr_step is mulitple of refresh rate */ + ept_ts = avr_step_fps ? ept - DIV_ROUND_UP(NSEC_PER_SEC, avr_step_fps) + NSEC_PER_MSEC + : ept - NSEC_PER_MSEC; + + /* ept time already elapsed */ + if (ept_ts <= current_ts) { + SDE_DEBUG("enc:%d, ept elapsed; ept:%llu, ept_ts:%llu, current_ts:%llu\n", + DRMID(&sde_enc->base), ept, ept_ts, current_ts); + return; + } + + timeout_us = DIV_ROUND_UP((ept_ts - current_ts), 1000); + /* validate timeout is not beyond the min fps */ + if (timeout_us > DIV_ROUND_UP(USEC_PER_SEC, min_fps)) { + SDE_ERROR("enc:%d, invalid timeout_us:%llu; ept:%llu, ept_ts:%llu, cur_ts:%llu\n", + DRMID(&sde_enc->base), timeout_us, ept, ept_ts, current_ts); + return; + } + + SDE_ATRACE_BEGIN("schedule_timeout"); + usleep_range(timeout_us, timeout_us + 10); + SDE_ATRACE_END("schedule_timeout"); + + SDE_EVT32(DRMID(&sde_enc->base), qsync_mode, avr_step_fps, min_fps, ktime_to_us(current_ts), + ktime_to_us(ept_ts), timeout_us); +} + int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_encoder_kickoff_params *params) { @@ -4715,6 +4768,8 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, goto end; } + _sde_encoder_delay_kickoff_processing(sde_enc); + ret = _sde_encoder_prepare_for_kickoff_processing(drm_enc, params, sde_enc, sde_kms, needs_hw_reset, is_cmd_mode); diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index 615f5d462d..e720531b4d 100644 --- a/msm/sde/sde_encoder.h +++ b/msm/sde/sde_encoder.h @@ -59,6 +59,8 @@ ((!(phys_enc) || ((idx) < 0) || ((idx) >= INTR_IDX_MAX)) ? \ 0 : ((phys_enc)->irq[(idx)].irq_idx >= 0)) +#define DEFAULT_MIN_FPS 10 + /** * Encoder functions and data types * @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 8181ab17bc..3b05df5d0d 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -767,6 +767,7 @@ enum { * @SDE_FEATURE_SUI_BLENDSTAGE SecureUI Blendstage supported * @SDE_FEATURE_SUI_NS_ALLOWED SecureUI allowed to access non-secure context banks * @SDE_FEATURE_TRUSTED_VM Trusted VM supported + * @SDE_FEATURE_EPT Expected present time supported * @SDE_FEATURE_UBWC_STATS UBWC statistics supported * @SDE_FEATURE_VBIF_CLK_SPLIT VBIF clock split supported * @SDE_FEATURE_CTL_DONE Support for CTL DONE irq @@ -813,6 +814,7 @@ enum sde_mdss_features { SDE_FEATURE_SUI_BLENDSTAGE, SDE_FEATURE_SUI_NS_ALLOWED, SDE_FEATURE_TRUSTED_VM, + SDE_FEATURE_EPT, SDE_FEATURE_UBWC_STATS, SDE_FEATURE_VBIF_CLK_SPLIT, SDE_FEATURE_CTL_DONE, From 7e367f013523a3ceb599a63ab82b75de987d77a5 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 13 Jan 2023 13:44:03 -0800 Subject: [PATCH 3/3] disp: msm: sde: enable EPT feature for pineapple target Enable the Expected Present Time feature in sde catalog for pineapple target. Change-Id: I12a6abb00e8792564fad390be1d49e3217f88517 Signed-off-by: Veera Sundaram Sankaran --- msm/sde/sde_hw_catalog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index bfa132598b..4152f1fe2c 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -5395,6 +5395,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) set_bit(SDE_FEATURE_SYS_CACHE_NSE, sde_cfg->features); set_bit(SDE_FEATURE_SYS_CACHE_STALING, sde_cfg->features); set_bit(SDE_FEATURE_WB_ROTATION, sde_cfg->features); + set_bit(SDE_FEATURE_EPT, sde_cfg->features); sde_cfg->allowed_dsc_reservation_switch = SDE_DP_DSC_RESERVATION_SWITCH; sde_cfg->autorefresh_disable_seq = AUTOREFRESH_DISABLE_SEQ2; sde_cfg->perf.min_prefill_lines = 40;