aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorLi Peng <peng.li@linux.intel.com>2010-01-27 06:01:11 -0500
committerEric Anholt <eric@anholt.net>2010-02-22 11:46:50 -0500
commitee980b8003a25fbfed50c3367f2b426c870eaf90 (patch)
tree1753500fd849e4dd68a4878f31baa95743699535 /drivers/gpu/drm/i915
parentb397c836eff58cd9a43f7bd8b853a51b3ecc3420 (diff)
drm/i915: enable memory self refresh on 9xx
Enabling memory self refresh (SR) on 9xx needs to set additional register bits. On 945, we need bit 31 of FW_BLC_SELF to enable the write to self refresh bit and bit 16 to enable the write of self refresh watermark. On 915, bit 12 of INSTPM is used to enable SR. SR will take effect when CPU enters C3+ state and its entry/exit should be automatically controlled by H/W, driver only needs to set SR enable bits in wm update. But this isn't safe in my test on 945 because GPU is hung. So this patch explicitly enables SR when GPU is idle, and disables SR when it is busy. In my test on a netbook of 945GSE chipset, it saves about 0.8W idle power. Signed-off-by: Li Peng <peng.li@intel.com> [anholt: rebased against 33c5fd121eabbccc9103daf6cda36941eb3c349f by adding disable of INSTPM SR bit on 915GM for two pipe setup] Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h5
-rw-r--r--drivers/gpu/drm/i915/intel_display.c31
2 files changed, 32 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ab1bd2d3d3b6..6defb7f47348 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -306,11 +306,14 @@
306#define I915_ERROR_MEMORY_REFRESH (1<<1) 306#define I915_ERROR_MEMORY_REFRESH (1<<1)
307#define I915_ERROR_INSTRUCTION (1<<0) 307#define I915_ERROR_INSTRUCTION (1<<0)
308#define INSTPM 0x020c0 308#define INSTPM 0x020c0
309#define INSTPM_SELF_EN (1<<12) /* 915GM only */
309#define ACTHD 0x020c8 310#define ACTHD 0x020c8
310#define FW_BLC 0x020d8 311#define FW_BLC 0x020d8
311#define FW_BLC2 0x020dc 312#define FW_BLC2 0x020dc
312#define FW_BLC_SELF 0x020e0 /* 915+ only */ 313#define FW_BLC_SELF 0x020e0 /* 915+ only */
313#define FW_BLC_SELF_EN (1<<15) 314#define FW_BLC_SELF_EN_MASK (1<<31)
315#define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */
316#define FW_BLC_SELF_EN (1<<15) /* 945 only */
314#define MM_BURST_LENGTH 0x00700000 317#define MM_BURST_LENGTH 0x00700000
315#define MM_FIFO_WATERMARK 0x0001F000 318#define MM_FIFO_WATERMARK 0x0001F000
316#define LM_BURST_LENGTH 0x00000700 319#define LM_BURST_LENGTH 0x00000700
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b27202d23ebc..af9ec217cd1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2757,11 +2757,22 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
2757 srwm = total_size - sr_entries; 2757 srwm = total_size - sr_entries;
2758 if (srwm < 0) 2758 if (srwm < 0)
2759 srwm = 1; 2759 srwm = 1;
2760 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); 2760
2761 if (IS_I945G(dev) || IS_I945GM(dev))
2762 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
2763 else if (IS_I915GM(dev)) {
2764 /* 915M has a smaller SRWM field */
2765 I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
2766 I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
2767 }
2761 } else { 2768 } else {
2762 /* Turn off self refresh if both pipes are enabled */ 2769 /* Turn off self refresh if both pipes are enabled */
2763 I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) 2770 if (IS_I945G(dev) || IS_I945GM(dev)) {
2764 & ~FW_BLC_SELF_EN); 2771 I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
2772 & ~FW_BLC_SELF_EN);
2773 } else if (IS_I915GM(dev)) {
2774 I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
2775 }
2765 } 2776 }
2766 2777
2767 DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", 2778 DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
@@ -4011,6 +4022,11 @@ static void intel_idle_update(struct work_struct *work)
4011 4022
4012 mutex_lock(&dev->struct_mutex); 4023 mutex_lock(&dev->struct_mutex);
4013 4024
4025 if (IS_I945G(dev) || IS_I945GM(dev)) {
4026 DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
4027 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
4028 }
4029
4014 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 4030 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
4015 /* Skip inactive CRTCs */ 4031 /* Skip inactive CRTCs */
4016 if (!crtc->fb) 4032 if (!crtc->fb)
@@ -4044,6 +4060,15 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
4044 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 4060 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4045 return; 4061 return;
4046 4062
4063 if (IS_I945G(dev) || IS_I945GM(dev)) {
4064 u32 fw_blc_self;
4065
4066 DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
4067 fw_blc_self = I915_READ(FW_BLC_SELF);
4068 fw_blc_self &= ~FW_BLC_SELF_EN;
4069 I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
4070 }
4071
4047 if (!dev_priv->busy) 4072 if (!dev_priv->busy)
4048 dev_priv->busy = true; 4073 dev_priv->busy = true;
4049 else 4074 else