diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 105 |
1 files changed, 56 insertions, 49 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 42c64cb35738..5e478338dc0a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -2236,19 +2236,19 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
2236 | struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; | 2236 | struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; |
2237 | 2237 | ||
2238 | wait_event(dev_priv->pending_flip_queue, | 2238 | wait_event(dev_priv->pending_flip_queue, |
2239 | atomic_read(&dev_priv->mm.wedged) || | ||
2239 | atomic_read(&obj->pending_flip) == 0); | 2240 | atomic_read(&obj->pending_flip) == 0); |
2240 | 2241 | ||
2241 | /* Big Hammer, we also need to ensure that any pending | 2242 | /* Big Hammer, we also need to ensure that any pending |
2242 | * MI_WAIT_FOR_EVENT inside a user batch buffer on the | 2243 | * MI_WAIT_FOR_EVENT inside a user batch buffer on the |
2243 | * current scanout is retired before unpinning the old | 2244 | * current scanout is retired before unpinning the old |
2244 | * framebuffer. | 2245 | * framebuffer. |
2246 | * | ||
2247 | * This should only fail upon a hung GPU, in which case we | ||
2248 | * can safely continue. | ||
2245 | */ | 2249 | */ |
2246 | ret = i915_gem_object_flush_gpu(obj, false); | 2250 | ret = i915_gem_object_flush_gpu(obj, false); |
2247 | if (ret) { | 2251 | (void) ret; |
2248 | i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); | ||
2249 | mutex_unlock(&dev->struct_mutex); | ||
2250 | return ret; | ||
2251 | } | ||
2252 | } | 2252 | } |
2253 | 2253 | ||
2254 | ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y, | 2254 | ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y, |
@@ -6253,9 +6253,7 @@ static void intel_crtc_reset(struct drm_crtc *crtc) | |||
6253 | /* Reset flags back to the 'unknown' status so that they | 6253 | /* Reset flags back to the 'unknown' status so that they |
6254 | * will be correctly set on the initial modeset. | 6254 | * will be correctly set on the initial modeset. |
6255 | */ | 6255 | */ |
6256 | intel_crtc->cursor_addr = 0; | ||
6257 | intel_crtc->dpms_mode = -1; | 6256 | intel_crtc->dpms_mode = -1; |
6258 | intel_crtc->active = true; /* force the pipe off on setup_init_config */ | ||
6259 | } | 6257 | } |
6260 | 6258 | ||
6261 | static struct drm_crtc_helper_funcs intel_helper_funcs = { | 6259 | static struct drm_crtc_helper_funcs intel_helper_funcs = { |
@@ -6347,6 +6345,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
6347 | dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; | 6345 | dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; |
6348 | 6346 | ||
6349 | intel_crtc_reset(&intel_crtc->base); | 6347 | intel_crtc_reset(&intel_crtc->base); |
6348 | intel_crtc->active = true; /* force the pipe off on setup_init_config */ | ||
6350 | 6349 | ||
6351 | if (HAS_PCH_SPLIT(dev)) { | 6350 | if (HAS_PCH_SPLIT(dev)) { |
6352 | intel_helper_funcs.prepare = ironlake_crtc_prepare; | 6351 | intel_helper_funcs.prepare = ironlake_crtc_prepare; |
@@ -7143,52 +7142,60 @@ void intel_enable_clock_gating(struct drm_device *dev) | |||
7143 | } | 7142 | } |
7144 | } | 7143 | } |
7145 | 7144 | ||
7146 | void intel_disable_clock_gating(struct drm_device *dev) | 7145 | static void ironlake_teardown_rc6(struct drm_device *dev) |
7147 | { | 7146 | { |
7148 | struct drm_i915_private *dev_priv = dev->dev_private; | 7147 | struct drm_i915_private *dev_priv = dev->dev_private; |
7149 | 7148 | ||
7150 | if (dev_priv->renderctx) { | 7149 | if (dev_priv->renderctx) { |
7151 | struct drm_i915_gem_object *obj = dev_priv->renderctx; | 7150 | i915_gem_object_unpin(dev_priv->renderctx); |
7152 | 7151 | drm_gem_object_unreference(&dev_priv->renderctx->base); | |
7153 | I915_WRITE(CCID, 0); | ||
7154 | POSTING_READ(CCID); | ||
7155 | |||
7156 | i915_gem_object_unpin(obj); | ||
7157 | drm_gem_object_unreference(&obj->base); | ||
7158 | dev_priv->renderctx = NULL; | 7152 | dev_priv->renderctx = NULL; |
7159 | } | 7153 | } |
7160 | 7154 | ||
7161 | if (dev_priv->pwrctx) { | 7155 | if (dev_priv->pwrctx) { |
7162 | struct drm_i915_gem_object *obj = dev_priv->pwrctx; | 7156 | i915_gem_object_unpin(dev_priv->pwrctx); |
7157 | drm_gem_object_unreference(&dev_priv->pwrctx->base); | ||
7158 | dev_priv->pwrctx = NULL; | ||
7159 | } | ||
7160 | } | ||
7161 | |||
7162 | static void ironlake_disable_rc6(struct drm_device *dev) | ||
7163 | { | ||
7164 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
7165 | |||
7166 | if (I915_READ(PWRCTXA)) { | ||
7167 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ | ||
7168 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); | ||
7169 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), | ||
7170 | 50); | ||
7163 | 7171 | ||
7164 | I915_WRITE(PWRCTXA, 0); | 7172 | I915_WRITE(PWRCTXA, 0); |
7165 | POSTING_READ(PWRCTXA); | 7173 | POSTING_READ(PWRCTXA); |
7166 | 7174 | ||
7167 | i915_gem_object_unpin(obj); | 7175 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
7168 | drm_gem_object_unreference(&obj->base); | 7176 | POSTING_READ(RSTDBYCTL); |
7169 | dev_priv->pwrctx = NULL; | ||
7170 | } | 7177 | } |
7178 | |||
7179 | ironlake_disable_rc6(dev); | ||
7171 | } | 7180 | } |
7172 | 7181 | ||
7173 | static void ironlake_disable_rc6(struct drm_device *dev) | 7182 | static int ironlake_setup_rc6(struct drm_device *dev) |
7174 | { | 7183 | { |
7175 | struct drm_i915_private *dev_priv = dev->dev_private; | 7184 | struct drm_i915_private *dev_priv = dev->dev_private; |
7176 | 7185 | ||
7177 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ | 7186 | if (dev_priv->renderctx == NULL) |
7178 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); | 7187 | dev_priv->renderctx = intel_alloc_context_page(dev); |
7179 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), | 7188 | if (!dev_priv->renderctx) |
7180 | 10); | 7189 | return -ENOMEM; |
7181 | POSTING_READ(CCID); | 7190 | |
7182 | I915_WRITE(PWRCTXA, 0); | 7191 | if (dev_priv->pwrctx == NULL) |
7183 | POSTING_READ(PWRCTXA); | 7192 | dev_priv->pwrctx = intel_alloc_context_page(dev); |
7184 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 7193 | if (!dev_priv->pwrctx) { |
7185 | POSTING_READ(RSTDBYCTL); | 7194 | ironlake_teardown_rc6(dev); |
7186 | i915_gem_object_unpin(dev_priv->renderctx); | 7195 | return -ENOMEM; |
7187 | drm_gem_object_unreference(&dev_priv->renderctx->base); | 7196 | } |
7188 | dev_priv->renderctx = NULL; | 7197 | |
7189 | i915_gem_object_unpin(dev_priv->pwrctx); | 7198 | return 0; |
7190 | drm_gem_object_unreference(&dev_priv->pwrctx->base); | ||
7191 | dev_priv->pwrctx = NULL; | ||
7192 | } | 7199 | } |
7193 | 7200 | ||
7194 | void ironlake_enable_rc6(struct drm_device *dev) | 7201 | void ironlake_enable_rc6(struct drm_device *dev) |
@@ -7196,15 +7203,26 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
7196 | struct drm_i915_private *dev_priv = dev->dev_private; | 7203 | struct drm_i915_private *dev_priv = dev->dev_private; |
7197 | int ret; | 7204 | int ret; |
7198 | 7205 | ||
7206 | /* rc6 disabled by default due to repeated reports of hanging during | ||
7207 | * boot and resume. | ||
7208 | */ | ||
7209 | if (!i915_enable_rc6) | ||
7210 | return; | ||
7211 | |||
7212 | ret = ironlake_setup_rc6(dev); | ||
7213 | if (ret) | ||
7214 | return; | ||
7215 | |||
7199 | /* | 7216 | /* |
7200 | * GPU can automatically power down the render unit if given a page | 7217 | * GPU can automatically power down the render unit if given a page |
7201 | * to save state. | 7218 | * to save state. |
7202 | */ | 7219 | */ |
7203 | ret = BEGIN_LP_RING(6); | 7220 | ret = BEGIN_LP_RING(6); |
7204 | if (ret) { | 7221 | if (ret) { |
7205 | ironlake_disable_rc6(dev); | 7222 | ironlake_teardown_rc6(dev); |
7206 | return; | 7223 | return; |
7207 | } | 7224 | } |
7225 | |||
7208 | OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); | 7226 | OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); |
7209 | OUT_RING(MI_SET_CONTEXT); | 7227 | OUT_RING(MI_SET_CONTEXT); |
7210 | OUT_RING(dev_priv->renderctx->gtt_offset | | 7228 | OUT_RING(dev_priv->renderctx->gtt_offset | |
@@ -7221,6 +7239,7 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
7221 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 7239 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
7222 | } | 7240 | } |
7223 | 7241 | ||
7242 | |||
7224 | /* Set up chip specific display functions */ | 7243 | /* Set up chip specific display functions */ |
7225 | static void intel_init_display(struct drm_device *dev) | 7244 | static void intel_init_display(struct drm_device *dev) |
7226 | { | 7245 | { |
@@ -7459,21 +7478,9 @@ void intel_modeset_init(struct drm_device *dev) | |||
7459 | if (IS_GEN6(dev)) | 7478 | if (IS_GEN6(dev)) |
7460 | gen6_enable_rps(dev_priv); | 7479 | gen6_enable_rps(dev_priv); |
7461 | 7480 | ||
7462 | if (IS_IRONLAKE_M(dev)) { | 7481 | if (IS_IRONLAKE_M(dev)) |
7463 | dev_priv->renderctx = intel_alloc_context_page(dev); | ||
7464 | if (!dev_priv->renderctx) | ||
7465 | goto skip_rc6; | ||
7466 | dev_priv->pwrctx = intel_alloc_context_page(dev); | ||
7467 | if (!dev_priv->pwrctx) { | ||
7468 | i915_gem_object_unpin(dev_priv->renderctx); | ||
7469 | drm_gem_object_unreference(&dev_priv->renderctx->base); | ||
7470 | dev_priv->renderctx = NULL; | ||
7471 | goto skip_rc6; | ||
7472 | } | ||
7473 | ironlake_enable_rc6(dev); | 7482 | ironlake_enable_rc6(dev); |
7474 | } | ||
7475 | 7483 | ||
7476 | skip_rc6: | ||
7477 | INIT_WORK(&dev_priv->idle_work, intel_idle_update); | 7484 | INIT_WORK(&dev_priv->idle_work, intel_idle_update); |
7478 | setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, | 7485 | setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, |
7479 | (unsigned long)dev); | 7486 | (unsigned long)dev); |