diff options
author | Alexander Lam <lambchop468@gmail.com> | 2011-01-03 13:28:56 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-01-19 07:38:48 -0500 |
commit | 18b2190ca5bd3f19717421b1591c79c9b0372428 (patch) | |
tree | c55fc64a0ff773a98bbbfc366b8b9600064bd5b8 /drivers/gpu/drm/i915/intel_display.c | |
parent | b0b544cd37c060e261afb2cf486296983fcb56da (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.c | 62 |
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 | ||
3842 | static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, | 3850 | 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 | 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; |