Commit 2ac5438c authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915/vrr: Be more careful with the bits in TRANS_VRR_CTL

On mtl (at least) clearing the guardband bits in the same write
as the enable bit gets cleared seems to cause an immediate FIFO
underrun. Thus is seems that we need to first clear just the
enable bit, then wait for the VRR live status to indicate the
transcoder has exited VRR mode (this step is documented in Bspec
as well), and finally we can clear out the rest of the TRANS_VRR_CTL
for good measure.

I did this without any RMWs in case we want to toggle VRR on/off
via DSB in the future, and as we know DSB can't read registers.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221202134412.21943-5-ville.syrjala@linux.intel.comReviewed-by: default avatarManasi Navare <manasi.d.navare@intel.com>
parent 0504d0ac
......@@ -161,31 +161,36 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
}
static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
if (DISPLAY_VER(i915) >= 13)
return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband);
else
return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) |
VRR_CTL_PIPELINE_FULL_OVERRIDE;
}
void intel_vrr_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 trans_vrr_ctl;
if (!crtc_state->vrr.enable)
return;
if (DISPLAY_VER(dev_priv) >= 13)
trans_vrr_ctl = VRR_CTL_VRR_ENABLE |
VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband);
else
trans_vrr_ctl = VRR_CTL_VRR_ENABLE |
VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) |
VRR_CTL_PIPELINE_FULL_OVERRIDE;
intel_de_write(dev_priv, TRANS_VRR_VMIN(cpu_transcoder), crtc_state->vrr.vmin - 1);
intel_de_write(dev_priv, TRANS_VRR_VMAX(cpu_transcoder), crtc_state->vrr.vmax - 1);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl(crtc_state));
intel_de_write(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder), crtc_state->vrr.flipline - 1);
intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder),
VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state));
}
void intel_vrr_send_push(const struct intel_crtc_state *crtc_state)
......@@ -222,8 +227,13 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state)
if (!old_crtc_state->vrr.enable)
return;
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder),
trans_vrr_ctl(old_crtc_state));
intel_de_wait_for_clear(dev_priv, TRANS_VRR_STATUS(cpu_transcoder),
VRR_STATUS_VRR_EN_LIVE, 1000);
intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), 0);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0);
}
void intel_vrr_get_config(struct intel_crtc *crtc,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment