From 8a16de7174620b1d17ab016ee4d3d269e236cdcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 22 Feb 2019 16:31:12 +0200 Subject: [PATCH] drm/i915: Disable LP1+ watermarks on Lenovo Thinkpad T431s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lenovo Thinkpad T431s (ivb) apparently can't handle LP1+ watermarks being enabled. It underruns severly enough that the screen is unusable. The latency values and watemarks look as expected. And sadly updating the BIOS to the latest version (BIOS GHET41WW (1.26 ) 11/21/2018) did not help. One glimmer of hope I had was the VBT. It seems to have some sort of flag for "self refresh = yes/no", but when I looked at a bunch of VBTs I had lying around most of them had that field set to "no". So if we used that we'd end up disabling LP1+ on most machines. That seems a bit harsh since we know LP1+ works just fine on most machines. Since I have no better ideas let's just disable LP1+ watermarks on this particular machine via a quirk. Cc: stable@vger.kernel.org Cc: Andrea Reported-by: Andrea Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109477 Fixes: a46a7350b1e8 ("drm/i915: Fix ilk+ watermarks when disabling pipes") Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 51 ++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 81ec73e4a083..3c2af41a928d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -2190,6 +2190,7 @@ bool intel_psr_enabled(struct intel_dp *intel_dp); void intel_init_quirks(struct drm_i915_private *dev_priv); /* intel_runtime_pm.c */ +void ilk_disable_lp1(struct drm_i915_private *dev_priv); void intel_runtime_pm_init_early(struct drm_i915_private *dev_priv); int intel_power_domains_init(struct drm_i915_private *); void intel_power_domains_cleanup(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4c0e43caa5cd..75dceac19950 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3015,6 +3015,29 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv) intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); } +static void ilk_wm_disable_quirk(struct drm_i915_private *dev_priv, + int level) +{ + int max_level = ilk_wm_max_level(dev_priv); + + if (dev_priv->wm.pri_latency[level] == 0 && + dev_priv->wm.spr_latency[level] == 0 && + dev_priv->wm.cur_latency[level] == 0) + return; + + DRM_DEBUG_KMS("LP%d+ watermarks disabled by quirk\n", level); + + for (; level <= max_level; level++) { + dev_priv->wm.pri_latency[level] = 0; + dev_priv->wm.spr_latency[level] = 0; + dev_priv->wm.cur_latency[level] = 0; + } + + intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); + intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); + intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); +} + static void snb_wm_lp3_irq_quirk(struct drm_i915_private *dev_priv) { /* @@ -3028,23 +3051,18 @@ static void snb_wm_lp3_irq_quirk(struct drm_i915_private *dev_priv) * interrupts only. To play it safe we disable LP3 * watermarks entirely. */ - if (dev_priv->wm.pri_latency[3] == 0 && - dev_priv->wm.spr_latency[3] == 0 && - dev_priv->wm.cur_latency[3] == 0) - return; - - dev_priv->wm.pri_latency[3] = 0; - dev_priv->wm.spr_latency[3] = 0; - dev_priv->wm.cur_latency[3] = 0; + ilk_wm_disable_quirk(dev_priv, 3); +} - DRM_DEBUG_KMS("LP3 watermarks disabled due to potential for lost interrupts\n"); - intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); - intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); - intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); +static void ilk_wm_disable_lp1_quirk(struct drm_i915_private *dev_priv) +{ + ilk_wm_disable_quirk(dev_priv, 1); } static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) { + struct pci_dev *pdev = dev_priv->drm.pdev; + intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency); memcpy(dev_priv->wm.spr_latency, dev_priv->wm.pri_latency, @@ -3063,6 +3081,15 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) snb_wm_latency_quirk(dev_priv); snb_wm_lp3_irq_quirk(dev_priv); } + + /* + * Lenovo Thinkpad T431s (ivb) + * Massive underruns. + */ + if (pdev->device == 0x0166 && + pdev->subsystem_vendor == 0x17aa && + pdev->subsystem_device == 0x2208) + ilk_wm_disable_lp1_quirk(dev_priv); } static void skl_setup_wm_latency(struct drm_i915_private *dev_priv) -- 2.19.2