Commit 18b2190c authored by Alexander Lam's avatar Alexander Lam Committed by Chris Wilson

drm/i915: allow 945 to control self refresh (CxSR) automatically

I changed 945's self refresh to work without the need for the driver to
enable/disable self refresh manually based on the idle state of the gpu.
This is much better than enabling/disabling self refresh for various
reasons, including staying in a lower power state for more time and
avoiding the need for cpu cycles.

This was originally done manually to workaround issues with the hardware
hanging. However, since 94400120: drm/i915: enable low power render
writes on GEN3 hardware, automatic CxSR seems stable.
Signed-off-by: default avatarAlexander Lam <lambchop468@gmail.com>
Acked-by : Li Peng <peng.li@linux.intel.com>
[ickle: play safe with the ordering and disable CxSR before tweaking any
watermark and enable afterwards.]
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent b0b544cd
...@@ -3761,7 +3761,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3761,7 +3761,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
int planea_wm, planeb_wm; int planea_wm, planeb_wm;
struct intel_watermark_params planea_params, planeb_params; struct intel_watermark_params planea_params, planeb_params;
unsigned long line_time_us; unsigned long line_time_us;
int sr_clock, sr_entries = 0; int sr_clock, sr_entries = 0, sr_enabled = 0;
/* Create copies of the base settings for each pipe */ /* Create copies of the base settings for each pipe */
if (IS_CRESTLINE(dev) || IS_I945GM(dev)) if (IS_CRESTLINE(dev) || IS_I945GM(dev))
...@@ -3790,6 +3790,12 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3790,6 +3790,12 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
*/ */
cwm = 2; cwm = 2;
/* Play safe and disable self-refresh before adjusting watermarks. */
if (IS_I945G(dev) || IS_I945GM(dev))
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0);
else if (IS_I915GM(dev))
I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
/* Calc sr entries for one plane configs */ /* Calc sr entries for one plane configs */
if (HAS_FW_BLC(dev) && sr_hdisplay && if (HAS_FW_BLC(dev) && sr_hdisplay &&
(!planea_clock || !planeb_clock)) { (!planea_clock || !planeb_clock)) {
...@@ -3809,20 +3815,12 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3809,20 +3815,12 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
srwm = 1; srwm = 1;
if (IS_I945G(dev) || IS_I945GM(dev)) if (IS_I945G(dev) || IS_I945GM(dev))
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff)); I915_WRITE(FW_BLC_SELF,
else if (IS_I915GM(dev)) { FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
/* 915M has a smaller SRWM field */ else if (IS_I915GM(dev))
I915_WRITE(FW_BLC_SELF, srwm & 0x3f); I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
} sr_enabled = 1;
} else {
/* Turn off self refresh if both pipes are enabled */
if (IS_I945G(dev) || IS_I945GM(dev)) {
I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
& ~FW_BLC_SELF_EN);
} else if (IS_I915GM(dev)) {
I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
}
} }
DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
...@@ -3837,6 +3835,16 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, ...@@ -3837,6 +3835,16 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
I915_WRITE(FW_BLC, fwater_lo); I915_WRITE(FW_BLC, fwater_lo);
I915_WRITE(FW_BLC2, fwater_hi); I915_WRITE(FW_BLC2, fwater_hi);
if (sr_enabled) {
if (IS_I945G(dev) || IS_I945GM(dev))
I915_WRITE(FW_BLC_SELF,
FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
else if (IS_I915GM(dev))
I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
DRM_DEBUG_KMS("memory self refresh enabled\n");
} else
DRM_DEBUG_KMS("memory self refresh disabled\n");
} }
static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
...@@ -5586,7 +5594,6 @@ static void intel_idle_update(struct work_struct *work) ...@@ -5586,7 +5594,6 @@ static void intel_idle_update(struct work_struct *work)
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct intel_crtc *intel_crtc; struct intel_crtc *intel_crtc;
int enabled = 0;
if (!i915_powersave) if (!i915_powersave)
return; return;
...@@ -5600,16 +5607,11 @@ static void intel_idle_update(struct work_struct *work) ...@@ -5600,16 +5607,11 @@ static void intel_idle_update(struct work_struct *work)
if (!crtc->fb) if (!crtc->fb)
continue; continue;
enabled++;
intel_crtc = to_intel_crtc(crtc); intel_crtc = to_intel_crtc(crtc);
if (!intel_crtc->busy) if (!intel_crtc->busy)
intel_decrease_pllclock(crtc); intel_decrease_pllclock(crtc);
} }
if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) {
DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
}
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
...@@ -5634,17 +5636,9 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj) ...@@ -5634,17 +5636,9 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
if (!drm_core_check_feature(dev, DRIVER_MODESET)) if (!drm_core_check_feature(dev, DRIVER_MODESET))
return; return;
if (!dev_priv->busy) { if (!dev_priv->busy)
if (IS_I945G(dev) || IS_I945GM(dev)) {
u32 fw_blc_self;
DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
fw_blc_self = I915_READ(FW_BLC_SELF);
fw_blc_self &= ~FW_BLC_SELF_EN;
I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
}
dev_priv->busy = true; dev_priv->busy = true;
} else else
mod_timer(&dev_priv->idle_timer, jiffies + mod_timer(&dev_priv->idle_timer, jiffies +
msecs_to_jiffies(GPU_IDLE_TIMEOUT)); msecs_to_jiffies(GPU_IDLE_TIMEOUT));
...@@ -5656,14 +5650,6 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj) ...@@ -5656,14 +5650,6 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
intel_fb = to_intel_framebuffer(crtc->fb); intel_fb = to_intel_framebuffer(crtc->fb);
if (intel_fb->obj == obj) { if (intel_fb->obj == obj) {
if (!intel_crtc->busy) { if (!intel_crtc->busy) {
if (IS_I945G(dev) || IS_I945GM(dev)) {
u32 fw_blc_self;
DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
fw_blc_self = I915_READ(FW_BLC_SELF);
fw_blc_self &= ~FW_BLC_SELF_EN;
I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
}
/* Non-busy -> busy, upclock */ /* Non-busy -> busy, upclock */
intel_increase_pllclock(crtc); intel_increase_pllclock(crtc);
intel_crtc->busy = true; intel_crtc->busy = true;
......
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