Commit 11a85d6a authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Skip vblank wait if cxsr was already off

Before we attempt to turn any planes on or off we must first exit
csxr. That's due to cxsr effectively making the plane enable bits
read-only. Currently we achieve that with a vblank wait right after
toggling the cxsr enable bit. We do the vblank wait even if cxsr was
already off, which seems wasteful, so let's try to only do it when
absolutely necessary.

We could start tracking the cxsr state fully somewhere, but for now
it seems easiest to just have intel_set_memory_cxsr() return the
previous cxsr state.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1480354637-14209-11-git-send-email-ville.syrjala@linux.intel.comReviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
parent 3d90e649
...@@ -3575,7 +3575,7 @@ extern void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv); ...@@ -3575,7 +3575,7 @@ extern void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv);
extern bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val); extern bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val);
extern void intel_init_pch_refclk(struct drm_i915_private *dev_priv); extern void intel_init_pch_refclk(struct drm_i915_private *dev_priv);
extern void intel_set_rps(struct drm_i915_private *dev_priv, u8 val); extern void intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, extern bool intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
bool enable); bool enable);
int i915_reg_read_ioctl(struct drm_device *dev, void *data, int i915_reg_read_ioctl(struct drm_device *dev, void *data,
......
...@@ -5021,10 +5021,9 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) ...@@ -5021,10 +5021,9 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc)
* event which is after the vblank start event, so we need to have a * event which is after the vblank start event, so we need to have a
* wait-for-vblank between disabling the plane and the pipe. * wait-for-vblank between disabling the plane and the pipe.
*/ */
if (HAS_GMCH_DISPLAY(dev_priv)) { if (HAS_GMCH_DISPLAY(dev_priv) &&
intel_set_memory_cxsr(dev_priv, false); intel_set_memory_cxsr(dev_priv, false))
intel_wait_for_vblank(dev_priv, pipe); intel_wait_for_vblank(dev_priv, pipe);
}
} }
static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
...@@ -5099,11 +5098,10 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) ...@@ -5099,11 +5098,10 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
* event which is after the vblank start event, so we need to have a * event which is after the vblank start event, so we need to have a
* wait-for-vblank between disabling the plane and the pipe. * wait-for-vblank between disabling the plane and the pipe.
*/ */
if (old_crtc_state->base.active) { if (old_crtc_state->base.active &&
intel_set_memory_cxsr(dev_priv, false); intel_set_memory_cxsr(dev_priv, false))
intel_wait_for_vblank(dev_priv, crtc->pipe); intel_wait_for_vblank(dev_priv, crtc->pipe);
} }
}
/* /*
* IVB workaround: must disable low power watermarks for at least * IVB workaround: must disable low power watermarks for at least
......
...@@ -312,22 +312,30 @@ static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable) ...@@ -312,22 +312,30 @@ static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable)
#define FW_WM(value, plane) \ #define FW_WM(value, plane) \
(((value) << DSPFW_ ## plane ## _SHIFT) & DSPFW_ ## plane ## _MASK) (((value) << DSPFW_ ## plane ## _SHIFT) & DSPFW_ ## plane ## _MASK)
static void _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) static bool _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
{ {
bool was_enabled;
u32 val; u32 val;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
was_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0); I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0);
POSTING_READ(FW_BLC_SELF_VLV); POSTING_READ(FW_BLC_SELF_VLV);
} else if (IS_G4X(dev_priv) || IS_CRESTLINE(dev_priv)) { } else if (IS_G4X(dev_priv) || IS_CRESTLINE(dev_priv)) {
was_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0); I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0);
POSTING_READ(FW_BLC_SELF); POSTING_READ(FW_BLC_SELF);
} else if (IS_PINEVIEW(dev_priv)) { } else if (IS_PINEVIEW(dev_priv)) {
val = I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN; val = I915_READ(DSPFW3);
val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0; was_enabled = val & PINEVIEW_SELF_REFRESH_EN;
if (enable)
val |= PINEVIEW_SELF_REFRESH_EN;
else
val &= ~PINEVIEW_SELF_REFRESH_EN;
I915_WRITE(DSPFW3, val); I915_WRITE(DSPFW3, val);
POSTING_READ(DSPFW3); POSTING_READ(DSPFW3);
} else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) { } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) {
was_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) : val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) :
_MASKED_BIT_DISABLE(FW_BLC_SELF_EN); _MASKED_BIT_DISABLE(FW_BLC_SELF_EN);
I915_WRITE(FW_BLC_SELF, val); I915_WRITE(FW_BLC_SELF, val);
...@@ -338,23 +346,32 @@ static void _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enabl ...@@ -338,23 +346,32 @@ static void _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enabl
* and yet it does have the related watermark in * and yet it does have the related watermark in
* FW_BLC_SELF. What's going on? * FW_BLC_SELF. What's going on?
*/ */
was_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
val = enable ? _MASKED_BIT_ENABLE(INSTPM_SELF_EN) : val = enable ? _MASKED_BIT_ENABLE(INSTPM_SELF_EN) :
_MASKED_BIT_DISABLE(INSTPM_SELF_EN); _MASKED_BIT_DISABLE(INSTPM_SELF_EN);
I915_WRITE(INSTPM, val); I915_WRITE(INSTPM, val);
POSTING_READ(INSTPM); POSTING_READ(INSTPM);
} else { } else {
return; return false;
} }
DRM_DEBUG_KMS("memory self-refresh is %s\n", enableddisabled(enable)); DRM_DEBUG_KMS("memory self-refresh is %s (was %s)\n",
enableddisabled(enable),
enableddisabled(was_enabled));
return was_enabled;
} }
void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) bool intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
{ {
bool ret;
mutex_lock(&dev_priv->wm.wm_mutex); mutex_lock(&dev_priv->wm.wm_mutex);
_intel_set_memory_cxsr(dev_priv, enable); ret = _intel_set_memory_cxsr(dev_priv, enable);
dev_priv->wm.vlv.cxsr = enable; dev_priv->wm.vlv.cxsr = enable;
mutex_unlock(&dev_priv->wm.wm_mutex); mutex_unlock(&dev_priv->wm.wm_mutex);
return ret;
} }
/* /*
......
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