aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c105
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
6261static struct drm_crtc_helper_funcs intel_helper_funcs = { 6259static 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
7146void intel_disable_clock_gating(struct drm_device *dev) 7145static 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
7162static 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
7173static void ironlake_disable_rc6(struct drm_device *dev) 7182static 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
7194void ironlake_enable_rc6(struct drm_device *dev) 7201void 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 */
7225static void intel_init_display(struct drm_device *dev) 7244static 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
7476skip_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);