diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 107 |
4 files changed, 75 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 02fce7f..0de75a2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -355,10 +355,10 @@ static int i915_drm_thaw(struct drm_device *dev) /* Resume the modeset for every activated CRTC */ drm_helper_resume_force_mode(dev); - } - /* Clock gating state */ - intel_enable_clock_gating(dev); + if (dev_priv->renderctx && dev_priv->pwrctx) + ironlake_enable_rc6(dev); + } intel_opregion_init(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1f77d8c..4552600 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1260,6 +1260,7 @@ extern void intel_disable_fbc(struct drm_device *dev); extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval); extern bool intel_fbc_enabled(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); +extern void ironlake_enable_rc6(struct drm_device *dev); extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void intel_detect_pch (struct drm_device *dev); extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 147cd96..0521ecf2 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -822,10 +822,6 @@ int i915_save_state(struct drm_device *dev) if (IS_GEN6(dev)) gen6_disable_rps(dev); - /* XXX disabling the clock gating breaks suspend on gm45 - intel_disable_clock_gating(dev); - */ - /* Cache mode state */ dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); @@ -868,6 +864,9 @@ int i915_restore_state(struct drm_device *dev) I915_WRITE (IMR, dev_priv->saveIMR); } + /* Clock gating state */ + intel_enable_clock_gating(dev); + if (IS_IRONLAKE_M(dev)) { ironlake_enable_drps(dev); intel_init_emon(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f3c0525..1190efa 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); |