disp: msm: sde: delay frame trigger to match with the EPT
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 <quic_kshirish@quicinc.com> Signed-off-by: Veera Sundaram Sankaran <quic_veeras@quicinc.com>
This commit is contained in:

committed by
Veera Sundaram Sankaran

parent
55e80bfcf7
commit
0a0dbc1220
@@ -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) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
@@ -247,6 +247,7 @@ enum msm_mdp_conn_property {
|
|||||||
CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
|
CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
|
||||||
CONNECTOR_PROP_SET_PANEL_MODE,
|
CONNECTOR_PROP_SET_PANEL_MODE,
|
||||||
CONNECTOR_PROP_AVR_STEP,
|
CONNECTOR_PROP_AVR_STEP,
|
||||||
|
CONNECTOR_PROP_EPT,
|
||||||
CONNECTOR_PROP_CACHE_STATE,
|
CONNECTOR_PROP_CACHE_STATE,
|
||||||
CONNECTOR_PROP_DSC_MODE,
|
CONNECTOR_PROP_DSC_MODE,
|
||||||
CONNECTOR_PROP_WB_USAGE_TYPE,
|
CONNECTOR_PROP_WB_USAGE_TYPE,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// 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.
|
* 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,
|
"qsync_mode", 0, 0, e_qsync_mode,
|
||||||
ARRAY_SIZE(e_qsync_mode), 0,
|
ARRAY_SIZE(e_qsync_mode), 0,
|
||||||
CONNECTOR_PROP_QSYNC_MODE);
|
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))
|
if (test_bit(SDE_FEATURE_AVR_STEP, sde_kms->catalog->features))
|
||||||
msm_property_install_range(&c_conn->property_info,
|
msm_property_install_range(&c_conn->property_info,
|
||||||
"avr_step", 0x0, 0, U32_MAX, 0,
|
"avr_step", 0x0, 0, U32_MAX, 0,
|
||||||
|
@@ -1241,7 +1241,7 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn,
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
u32 avr_step;
|
u32 avr_step;
|
||||||
bool qsync_dirty, has_modeset;
|
bool qsync_dirty, has_modeset, ept;
|
||||||
struct drm_connector_state *conn_state = &sde_conn_state->base;
|
struct drm_connector_state *conn_state = &sde_conn_state->base;
|
||||||
u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base,
|
u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base,
|
||||||
CONNECTOR_PROP_QSYNC_MODE);
|
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);
|
has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state, conn_state->crtc);
|
||||||
qsync_dirty = msm_property_is_dirty(&sde_conn->property_info,
|
qsync_dirty = msm_property_is_dirty(&sde_conn->property_info,
|
||||||
&sde_conn_state->property_state, CONNECTOR_PROP_QSYNC_MODE);
|
&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) ||
|
if (has_modeset && (qsync_dirty || ept) &&
|
||||||
msm_is_mode_seamless_dyn_clk(&sde_conn_state->msm_mode))) {
|
(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_ERROR("invalid qsync update during modeset priv flag:%x\n",
|
||||||
sde_conn_state->msm_mode.private_flags);
|
sde_conn_state->msm_mode.private_flags);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -4642,6 +4645,56 @@ static int _sde_encoder_prepare_for_kickoff_processing(struct drm_encoder *drm_e
|
|||||||
return ret;
|
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,
|
int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
|
||||||
struct sde_encoder_kickoff_params *params)
|
struct sde_encoder_kickoff_params *params)
|
||||||
{
|
{
|
||||||
@@ -4715,6 +4768,8 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_sde_encoder_delay_kickoff_processing(sde_enc);
|
||||||
|
|
||||||
ret = _sde_encoder_prepare_for_kickoff_processing(drm_enc, params, sde_enc, sde_kms,
|
ret = _sde_encoder_prepare_for_kickoff_processing(drm_enc, params, sde_enc, sde_kms,
|
||||||
needs_hw_reset, is_cmd_mode);
|
needs_hw_reset, is_cmd_mode);
|
||||||
|
|
||||||
|
@@ -59,6 +59,8 @@
|
|||||||
((!(phys_enc) || ((idx) < 0) || ((idx) >= INTR_IDX_MAX)) ? \
|
((!(phys_enc) || ((idx) < 0) || ((idx) >= INTR_IDX_MAX)) ? \
|
||||||
0 : ((phys_enc)->irq[(idx)].irq_idx >= 0))
|
0 : ((phys_enc)->irq[(idx)].irq_idx >= 0))
|
||||||
|
|
||||||
|
#define DEFAULT_MIN_FPS 10
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encoder functions and data types
|
* Encoder functions and data types
|
||||||
* @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
|
* @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
|
||||||
|
@@ -767,6 +767,7 @@ enum {
|
|||||||
* @SDE_FEATURE_SUI_BLENDSTAGE SecureUI Blendstage supported
|
* @SDE_FEATURE_SUI_BLENDSTAGE SecureUI Blendstage supported
|
||||||
* @SDE_FEATURE_SUI_NS_ALLOWED SecureUI allowed to access non-secure context banks
|
* @SDE_FEATURE_SUI_NS_ALLOWED SecureUI allowed to access non-secure context banks
|
||||||
* @SDE_FEATURE_TRUSTED_VM Trusted VM supported
|
* @SDE_FEATURE_TRUSTED_VM Trusted VM supported
|
||||||
|
* @SDE_FEATURE_EPT Expected present time supported
|
||||||
* @SDE_FEATURE_UBWC_STATS UBWC statistics supported
|
* @SDE_FEATURE_UBWC_STATS UBWC statistics supported
|
||||||
* @SDE_FEATURE_VBIF_CLK_SPLIT VBIF clock split supported
|
* @SDE_FEATURE_VBIF_CLK_SPLIT VBIF clock split supported
|
||||||
* @SDE_FEATURE_CTL_DONE Support for CTL DONE irq
|
* @SDE_FEATURE_CTL_DONE Support for CTL DONE irq
|
||||||
@@ -813,6 +814,7 @@ enum sde_mdss_features {
|
|||||||
SDE_FEATURE_SUI_BLENDSTAGE,
|
SDE_FEATURE_SUI_BLENDSTAGE,
|
||||||
SDE_FEATURE_SUI_NS_ALLOWED,
|
SDE_FEATURE_SUI_NS_ALLOWED,
|
||||||
SDE_FEATURE_TRUSTED_VM,
|
SDE_FEATURE_TRUSTED_VM,
|
||||||
|
SDE_FEATURE_EPT,
|
||||||
SDE_FEATURE_UBWC_STATS,
|
SDE_FEATURE_UBWC_STATS,
|
||||||
SDE_FEATURE_VBIF_CLK_SPLIT,
|
SDE_FEATURE_VBIF_CLK_SPLIT,
|
||||||
SDE_FEATURE_CTL_DONE,
|
SDE_FEATURE_CTL_DONE,
|
||||||
|
Reference in New Issue
Block a user