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:
Shirisha Kollapuram
2022-08-01 12:35:19 +05:30
committed by Veera Sundaram Sankaran
부모 55e80bfcf7
커밋 0a0dbc1220
5개의 변경된 파일69개의 추가작업 그리고 5개의 파일을 삭제

파일 보기

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