aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorAlexander Lam <lambchop468@gmail.com>2011-01-03 13:28:56 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-01-19 07:38:48 -0500
commit18b2190ca5bd3f19717421b1591c79c9b0372428 (patch)
treec55fc64a0ff773a98bbbfc366b8b9600064bd5b8 /drivers/gpu/drm/i915/intel_display.c
parentb0b544cd37c060e261afb2cf486296983fcb56da (diff)
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 944001201: drm/i915: enable low power render writes on GEN3 hardware, automatic CxSR seems stable. Signed-off-by: Alexander 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: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c62
1 files changed, 24 insertions, 38 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 36f9e97f05c4..fe8454a48eab 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3761,7 +3761,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
3761 int planea_wm, planeb_wm; 3761 int planea_wm, planeb_wm;
3762 struct intel_watermark_params planea_params, planeb_params; 3762 struct intel_watermark_params planea_params, planeb_params;
3763 unsigned long line_time_us; 3763 unsigned long line_time_us;
3764 int sr_clock, sr_entries = 0; 3764 int sr_clock, sr_entries = 0, sr_enabled = 0;
3765 3765
3766 /* Create copies of the base settings for each pipe */ 3766 /* Create copies of the base settings for each pipe */
3767 if (IS_CRESTLINE(dev) || IS_I945GM(dev)) 3767 if (IS_CRESTLINE(dev) || IS_I945GM(dev))
@@ -3790,6 +3790,12 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
3790 */ 3790 */
3791 cwm = 2; 3791 cwm = 2;
3792 3792
3793 /* Play safe and disable self-refresh before adjusting watermarks. */
3794 if (IS_I945G(dev) || IS_I945GM(dev))
3795 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0);
3796 else if (IS_I915GM(dev))
3797 I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
3798
3793 /* Calc sr entries for one plane configs */ 3799 /* Calc sr entries for one plane configs */
3794 if (HAS_FW_BLC(dev) && sr_hdisplay && 3800 if (HAS_FW_BLC(dev) && sr_hdisplay &&
3795 (!planea_clock || !planeb_clock)) { 3801 (!planea_clock || !planeb_clock)) {
@@ -3809,20 +3815,12 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
3809 srwm = 1; 3815 srwm = 1;
3810 3816
3811 if (IS_I945G(dev) || IS_I945GM(dev)) 3817 if (IS_I945G(dev) || IS_I945GM(dev))
3812 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff)); 3818 I915_WRITE(FW_BLC_SELF,
3813 else if (IS_I915GM(dev)) { 3819 FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
3814 /* 915M has a smaller SRWM field */ 3820 else if (IS_I915GM(dev))
3815 I915_WRITE(FW_BLC_SELF, srwm & 0x3f); 3821 I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
3816 I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN); 3822
3817 } 3823 sr_enabled = 1;
3818 } else {
3819 /* Turn off self refresh if both pipes are enabled */
3820 if (IS_I945G(dev) || IS_I945GM(dev)) {
3821 I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
3822 & ~FW_BLC_SELF_EN);
3823 } else if (IS_I915GM(dev)) {
3824 I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
3825 }
3826 } 3824 }
3827 3825
3828 DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", 3826 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 3835
3838 I915_WRITE(FW_BLC, fwater_lo); 3836 I915_WRITE(FW_BLC, fwater_lo);
3839 I915_WRITE(FW_BLC2, fwater_hi); 3837 I915_WRITE(FW_BLC2, fwater_hi);
3838
3839 if (sr_enabled) {
3840 if (IS_I945G(dev) || IS_I945GM(dev))
3841 I915_WRITE(FW_BLC_SELF,
3842 FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
3843 else if (IS_I915GM(dev))
3844 I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
3845 DRM_DEBUG_KMS("memory self refresh enabled\n");
3846 } else
3847 DRM_DEBUG_KMS("memory self refresh disabled\n");
3840} 3848}
3841 3849
3842static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, 3850static 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 struct drm_device *dev = dev_priv->dev; 5594 struct drm_device *dev = dev_priv->dev;
5587 struct drm_crtc *crtc; 5595 struct drm_crtc *crtc;
5588 struct intel_crtc *intel_crtc; 5596 struct intel_crtc *intel_crtc;
5589 int enabled = 0;
5590 5597
5591 if (!i915_powersave) 5598 if (!i915_powersave)
5592 return; 5599 return;
@@ -5600,16 +5607,11 @@ static void intel_idle_update(struct work_struct *work)
5600 if (!crtc->fb) 5607 if (!crtc->fb)
5601 continue; 5608 continue;
5602 5609
5603 enabled++;
5604 intel_crtc = to_intel_crtc(crtc); 5610 intel_crtc = to_intel_crtc(crtc);
5605 if (!intel_crtc->busy) 5611 if (!intel_crtc->busy)
5606 intel_decrease_pllclock(crtc); 5612 intel_decrease_pllclock(crtc);
5607 } 5613 }
5608 5614
5609 if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) {
5610 DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
5611 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
5612 }
5613 5615
5614 mutex_unlock(&dev->struct_mutex); 5616 mutex_unlock(&dev->struct_mutex);
5615} 5617}
@@ -5634,17 +5636,9 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
5634 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 5636 if (!drm_core_check_feature(dev, DRIVER_MODESET))
5635 return; 5637 return;
5636 5638
5637 if (!dev_priv->busy) { 5639 if (!dev_priv->busy)
5638 if (IS_I945G(dev) || IS_I945GM(dev)) {
5639 u32 fw_blc_self;
5640
5641 DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
5642 fw_blc_self = I915_READ(FW_BLC_SELF);
5643 fw_blc_self &= ~FW_BLC_SELF_EN;
5644 I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
5645 }
5646 dev_priv->busy = true; 5640 dev_priv->busy = true;
5647 } else 5641 else
5648 mod_timer(&dev_priv->idle_timer, jiffies + 5642 mod_timer(&dev_priv->idle_timer, jiffies +
5649 msecs_to_jiffies(GPU_IDLE_TIMEOUT)); 5643 msecs_to_jiffies(GPU_IDLE_TIMEOUT));
5650 5644
@@ -5656,14 +5650,6 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
5656 intel_fb = to_intel_framebuffer(crtc->fb); 5650 intel_fb = to_intel_framebuffer(crtc->fb);
5657 if (intel_fb->obj == obj) { 5651 if (intel_fb->obj == obj) {
5658 if (!intel_crtc->busy) { 5652 if (!intel_crtc->busy) {
5659 if (IS_I945G(dev) || IS_I945GM(dev)) {
5660 u32 fw_blc_self;
5661
5662 DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
5663 fw_blc_self = I915_READ(FW_BLC_SELF);
5664 fw_blc_self &= ~FW_BLC_SELF_EN;
5665 I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
5666 }
5667 /* Non-busy -> busy, upclock */ 5653 /* Non-busy -> busy, upclock */
5668 intel_increase_pllclock(crtc); 5654 intel_increase_pllclock(crtc);
5669 intel_crtc->busy = true; 5655 intel_crtc->busy = true;