diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 107 |
1 files changed, 68 insertions, 39 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f3c0525d5328..1190efa390bd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6415,44 +6415,6 @@ void intel_enable_clock_gating(struct drm_device *dev) } else if (IS_I830(dev)) { I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); } - - /* - * GPU can automatically power down the render unit if given a page - * to save state. - */ - if (IS_IRONLAKE_M(dev)) { - if (dev_priv->renderctx == NULL) - dev_priv->renderctx = intel_alloc_context_page(dev); - if (dev_priv->renderctx) { - struct drm_i915_gem_object *obj = dev_priv->renderctx; - if (BEGIN_LP_RING(6) != 0) { - i915_gem_object_unpin(obj); - drm_gem_object_unreference(&obj->base); - dev_priv->renderctx = NULL; - return; - } - OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); - OUT_RING(MI_SET_CONTEXT); - OUT_RING(obj->gtt_offset | - MI_MM_SPACE_GTT | - MI_SAVE_EXT_STATE_EN | - MI_RESTORE_EXT_STATE_EN | - MI_RESTORE_INHIBIT); - OUT_RING(MI_SUSPEND_FLUSH); - OUT_RING(MI_NOOP); - OUT_RING(MI_FLUSH); - ADVANCE_LP_RING(); - } else - DRM_DEBUG_KMS("Failed to allocate render context." - "Disable RC6\n"); - - if (dev_priv->pwrctx == NULL) - dev_priv->pwrctx = intel_alloc_context_page(dev); - if (dev_priv->pwrctx) { - struct drm_i915_gem_object *obj = dev_priv->pwrctx; - I915_WRITE(PWRCTXA, obj->gtt_offset | PWRCTX_EN); - } - } } void intel_disable_clock_gating(struct drm_device *dev) @@ -6482,6 +6444,57 @@ void intel_disable_clock_gating(struct drm_device *dev) } } +static void ironlake_disable_rc6(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ + I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); + wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), + 10); + POSTING_READ(CCID); + I915_WRITE(PWRCTXA, 0); + POSTING_READ(PWRCTXA); + I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); + POSTING_READ(RSTDBYCTL); + i915_gem_object_unpin(dev_priv->renderctx); + drm_gem_object_unreference(&dev_priv->renderctx->base); + dev_priv->renderctx = NULL; + i915_gem_object_unpin(dev_priv->pwrctx); + drm_gem_object_unreference(&dev_priv->pwrctx->base); + dev_priv->pwrctx = NULL; +} + +void ironlake_enable_rc6(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + + /* + * GPU can automatically power down the render unit if given a page + * to save state. + */ + ret = BEGIN_LP_RING(6); + if (ret) { + ironlake_disable_rc6(dev); + return; + } + OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); + OUT_RING(MI_SET_CONTEXT); + OUT_RING(dev_priv->renderctx->gtt_offset | + MI_MM_SPACE_GTT | + MI_SAVE_EXT_STATE_EN | + MI_RESTORE_EXT_STATE_EN | + MI_RESTORE_INHIBIT); + OUT_RING(MI_SUSPEND_FLUSH); + OUT_RING(MI_NOOP); + OUT_RING(MI_FLUSH); + ADVANCE_LP_RING(); + + I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN); + I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); +} + /* Set up chip specific display functions */ static void intel_init_display(struct drm_device *dev) { @@ -6724,6 +6737,21 @@ void intel_modeset_init(struct drm_device *dev) if (IS_GEN6(dev)) gen6_enable_rps(dev_priv); + if (IS_IRONLAKE_M(dev)) { + dev_priv->renderctx = intel_alloc_context_page(dev); + if (!dev_priv->renderctx) + goto skip_rc6; + dev_priv->pwrctx = intel_alloc_context_page(dev); + if (!dev_priv->pwrctx) { + i915_gem_object_unpin(dev_priv->renderctx); + drm_gem_object_unreference(&dev_priv->renderctx->base); + dev_priv->renderctx = NULL; + goto skip_rc6; + } + ironlake_enable_rc6(dev); + } + +skip_rc6: INIT_WORK(&dev_priv->idle_work, intel_idle_update); setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, (unsigned long)dev); @@ -6760,7 +6788,8 @@ void intel_modeset_cleanup(struct drm_device *dev) if (IS_GEN6(dev)) gen6_disable_rps(dev); - intel_disable_clock_gating(dev); + if (IS_IRONLAKE_M(dev)) + ironlake_disable_rc6(dev); mutex_unlock(&dev->struct_mutex); |