Commit 1d411c8f authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Kamal Mostafa

drm/i915: Increase WM memory latency values on SNB

commit e95a2f75 upstream.

On SNB the BIOS provided WM memory latency values seem insufficient to
handle high resolution displays.

In this particular case the display mode was a 2560x1440@60Hz, which
makes the pixel clock 241.5 MHz. It was empirically found that a memory
latency value if 1.2 usec is enough to avoid underruns, whereas the BIOS
provided value of 0.7 usec was clearly too low. Incidentally 1.2 usec
is what the typical BIOS provided values are on IVB systems.

Increase the WM memory latency values to at least 1.2 usec on SNB.
Hopefully this won't have a significant effect on power consumption.

v2: Increase the latency values regardless of the pixel clock

Cc: Robert N <crshman@gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70254Tested-by: default avatarRobert Navarro <crshman@gmail.com>
Tested-by: default avatarVitaly Minko <vitaly.minko@gmail.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
parent f36efe47
...@@ -2563,6 +2563,43 @@ static void intel_print_wm_latency(struct drm_device *dev, ...@@ -2563,6 +2563,43 @@ static void intel_print_wm_latency(struct drm_device *dev,
} }
} }
static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
uint16_t wm[5], uint16_t min)
{
int level, max_level = ilk_wm_max_level(dev_priv->dev);
if (wm[0] >= min)
return false;
wm[0] = max(wm[0], min);
for (level = 1; level <= max_level; level++)
wm[level] = max_t(uint16_t, wm[level], DIV_ROUND_UP(min, 5));
return true;
}
static void snb_wm_latency_quirk(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
bool changed;
/*
* The BIOS provided WM memory latency values are often
* inadequate for high resolution displays. Adjust them.
*/
changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12) |
ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12) |
ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12);
if (!changed)
return;
DRM_DEBUG_KMS("WM latency values increased to avoid potential underruns\n");
intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
}
static void intel_setup_wm_latency(struct drm_device *dev) static void intel_setup_wm_latency(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -2580,6 +2617,9 @@ static void intel_setup_wm_latency(struct drm_device *dev) ...@@ -2580,6 +2617,9 @@ static void intel_setup_wm_latency(struct drm_device *dev)
intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency); intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency); intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
if (IS_GEN6(dev))
snb_wm_latency_quirk(dev);
} }
static void hsw_compute_wm_parameters(struct drm_crtc *crtc, static void hsw_compute_wm_parameters(struct drm_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