diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 131 |
1 files changed, 86 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 98967f3b772..3b006536b3d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1213,6 +1213,26 @@ static bool g4x_fbc_enabled(struct drm_device *dev) | |||
1213 | return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; | 1213 | return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | static void sandybridge_blit_fbc_update(struct drm_device *dev) | ||
1217 | { | ||
1218 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1219 | u32 blt_ecoskpd; | ||
1220 | |||
1221 | /* Make sure blitter notifies FBC of writes */ | ||
1222 | __gen6_force_wake_get(dev_priv); | ||
1223 | blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); | ||
1224 | blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << | ||
1225 | GEN6_BLITTER_LOCK_SHIFT; | ||
1226 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); | ||
1227 | blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY; | ||
1228 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); | ||
1229 | blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY << | ||
1230 | GEN6_BLITTER_LOCK_SHIFT); | ||
1231 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); | ||
1232 | POSTING_READ(GEN6_BLITTER_ECOSKPD); | ||
1233 | __gen6_force_wake_put(dev_priv); | ||
1234 | } | ||
1235 | |||
1216 | static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 1236 | static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
1217 | { | 1237 | { |
1218 | struct drm_device *dev = crtc->dev; | 1238 | struct drm_device *dev = crtc->dev; |
@@ -1266,6 +1286,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | |||
1266 | I915_WRITE(SNB_DPFC_CTL_SA, | 1286 | I915_WRITE(SNB_DPFC_CTL_SA, |
1267 | SNB_CPU_FENCE_ENABLE | dev_priv->cfb_fence); | 1287 | SNB_CPU_FENCE_ENABLE | dev_priv->cfb_fence); |
1268 | I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); | 1288 | I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); |
1289 | sandybridge_blit_fbc_update(dev); | ||
1269 | } | 1290 | } |
1270 | 1291 | ||
1271 | DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); | 1292 | DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); |
@@ -5530,6 +5551,16 @@ cleanup_work: | |||
5530 | return ret; | 5551 | return ret; |
5531 | } | 5552 | } |
5532 | 5553 | ||
5554 | static void intel_crtc_reset(struct drm_crtc *crtc) | ||
5555 | { | ||
5556 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
5557 | |||
5558 | /* Reset flags back to the 'unknown' status so that they | ||
5559 | * will be correctly set on the initial modeset. | ||
5560 | */ | ||
5561 | intel_crtc->dpms_mode = -1; | ||
5562 | } | ||
5563 | |||
5533 | static struct drm_crtc_helper_funcs intel_helper_funcs = { | 5564 | static struct drm_crtc_helper_funcs intel_helper_funcs = { |
5534 | .dpms = intel_crtc_dpms, | 5565 | .dpms = intel_crtc_dpms, |
5535 | .mode_fixup = intel_crtc_mode_fixup, | 5566 | .mode_fixup = intel_crtc_mode_fixup, |
@@ -5541,6 +5572,7 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = { | |||
5541 | }; | 5572 | }; |
5542 | 5573 | ||
5543 | static const struct drm_crtc_funcs intel_crtc_funcs = { | 5574 | static const struct drm_crtc_funcs intel_crtc_funcs = { |
5575 | .reset = intel_crtc_reset, | ||
5544 | .cursor_set = intel_crtc_cursor_set, | 5576 | .cursor_set = intel_crtc_cursor_set, |
5545 | .cursor_move = intel_crtc_cursor_move, | 5577 | .cursor_move = intel_crtc_cursor_move, |
5546 | .gamma_set = intel_crtc_gamma_set, | 5578 | .gamma_set = intel_crtc_gamma_set, |
@@ -5631,8 +5663,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
5631 | dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base; | 5663 | dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base; |
5632 | dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; | 5664 | dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; |
5633 | 5665 | ||
5634 | intel_crtc->cursor_addr = 0; | 5666 | intel_crtc_reset(&intel_crtc->base); |
5635 | intel_crtc->dpms_mode = -1; | ||
5636 | intel_crtc->active = true; /* force the pipe off on setup_init_config */ | 5667 | intel_crtc->active = true; /* force the pipe off on setup_init_config */ |
5637 | 5668 | ||
5638 | if (HAS_PCH_SPLIT(dev)) { | 5669 | if (HAS_PCH_SPLIT(dev)) { |
@@ -6286,7 +6317,9 @@ void intel_enable_clock_gating(struct drm_device *dev) | |||
6286 | 6317 | ||
6287 | if (IS_GEN5(dev)) { | 6318 | if (IS_GEN5(dev)) { |
6288 | /* Required for FBC */ | 6319 | /* Required for FBC */ |
6289 | dspclk_gate |= DPFDUNIT_CLOCK_GATE_DISABLE; | 6320 | dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE | |
6321 | DPFCRUNIT_CLOCK_GATE_DISABLE | | ||
6322 | DPFDUNIT_CLOCK_GATE_DISABLE; | ||
6290 | /* Required for CxSR */ | 6323 | /* Required for CxSR */ |
6291 | dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE; | 6324 | dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE; |
6292 | 6325 | ||
@@ -6429,52 +6462,60 @@ void intel_enable_clock_gating(struct drm_device *dev) | |||
6429 | } | 6462 | } |
6430 | } | 6463 | } |
6431 | 6464 | ||
6432 | void intel_disable_clock_gating(struct drm_device *dev) | 6465 | static void ironlake_teardown_rc6(struct drm_device *dev) |
6433 | { | 6466 | { |
6434 | struct drm_i915_private *dev_priv = dev->dev_private; | 6467 | struct drm_i915_private *dev_priv = dev->dev_private; |
6435 | 6468 | ||
6436 | if (dev_priv->renderctx) { | 6469 | if (dev_priv->renderctx) { |
6437 | struct drm_i915_gem_object *obj = dev_priv->renderctx; | 6470 | i915_gem_object_unpin(dev_priv->renderctx); |
6438 | 6471 | drm_gem_object_unreference(&dev_priv->renderctx->base); | |
6439 | I915_WRITE(CCID, 0); | ||
6440 | POSTING_READ(CCID); | ||
6441 | |||
6442 | i915_gem_object_unpin(obj); | ||
6443 | drm_gem_object_unreference(&obj->base); | ||
6444 | dev_priv->renderctx = NULL; | 6472 | dev_priv->renderctx = NULL; |
6445 | } | 6473 | } |
6446 | 6474 | ||
6447 | if (dev_priv->pwrctx) { | 6475 | if (dev_priv->pwrctx) { |
6448 | struct drm_i915_gem_object *obj = dev_priv->pwrctx; | 6476 | i915_gem_object_unpin(dev_priv->pwrctx); |
6477 | drm_gem_object_unreference(&dev_priv->pwrctx->base); | ||
6478 | dev_priv->pwrctx = NULL; | ||
6479 | } | ||
6480 | } | ||
6481 | |||
6482 | static void ironlake_disable_rc6(struct drm_device *dev) | ||
6483 | { | ||
6484 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
6485 | |||
6486 | if (I915_READ(PWRCTXA)) { | ||
6487 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ | ||
6488 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); | ||
6489 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), | ||
6490 | 50); | ||
6449 | 6491 | ||
6450 | I915_WRITE(PWRCTXA, 0); | 6492 | I915_WRITE(PWRCTXA, 0); |
6451 | POSTING_READ(PWRCTXA); | 6493 | POSTING_READ(PWRCTXA); |
6452 | 6494 | ||
6453 | i915_gem_object_unpin(obj); | 6495 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
6454 | drm_gem_object_unreference(&obj->base); | 6496 | POSTING_READ(RSTDBYCTL); |
6455 | dev_priv->pwrctx = NULL; | ||
6456 | } | 6497 | } |
6498 | |||
6499 | ironlake_disable_rc6(dev); | ||
6457 | } | 6500 | } |
6458 | 6501 | ||
6459 | static void ironlake_disable_rc6(struct drm_device *dev) | 6502 | static int ironlake_setup_rc6(struct drm_device *dev) |
6460 | { | 6503 | { |
6461 | struct drm_i915_private *dev_priv = dev->dev_private; | 6504 | struct drm_i915_private *dev_priv = dev->dev_private; |
6462 | 6505 | ||
6463 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ | 6506 | if (dev_priv->renderctx == NULL) |
6464 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); | 6507 | dev_priv->renderctx = intel_alloc_context_page(dev); |
6465 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), | 6508 | if (!dev_priv->renderctx) |
6466 | 10); | 6509 | return -ENOMEM; |
6467 | POSTING_READ(CCID); | 6510 | |
6468 | I915_WRITE(PWRCTXA, 0); | 6511 | if (dev_priv->pwrctx == NULL) |
6469 | POSTING_READ(PWRCTXA); | 6512 | dev_priv->pwrctx = intel_alloc_context_page(dev); |
6470 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 6513 | if (!dev_priv->pwrctx) { |
6471 | POSTING_READ(RSTDBYCTL); | 6514 | ironlake_teardown_rc6(dev); |
6472 | i915_gem_object_unpin(dev_priv->renderctx); | 6515 | return -ENOMEM; |
6473 | drm_gem_object_unreference(&dev_priv->renderctx->base); | 6516 | } |
6474 | dev_priv->renderctx = NULL; | 6517 | |
6475 | i915_gem_object_unpin(dev_priv->pwrctx); | 6518 | return 0; |
6476 | drm_gem_object_unreference(&dev_priv->pwrctx->base); | ||
6477 | dev_priv->pwrctx = NULL; | ||
6478 | } | 6519 | } |
6479 | 6520 | ||
6480 | void ironlake_enable_rc6(struct drm_device *dev) | 6521 | void ironlake_enable_rc6(struct drm_device *dev) |
@@ -6482,15 +6523,26 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
6482 | struct drm_i915_private *dev_priv = dev->dev_private; | 6523 | struct drm_i915_private *dev_priv = dev->dev_private; |
6483 | int ret; | 6524 | int ret; |
6484 | 6525 | ||
6526 | /* rc6 disabled by default due to repeated reports of hanging during | ||
6527 | * boot and resume. | ||
6528 | */ | ||
6529 | if (!i915_enable_rc6) | ||
6530 | return; | ||
6531 | |||
6532 | ret = ironlake_setup_rc6(dev); | ||
6533 | if (ret) | ||
6534 | return; | ||
6535 | |||
6485 | /* | 6536 | /* |
6486 | * GPU can automatically power down the render unit if given a page | 6537 | * GPU can automatically power down the render unit if given a page |
6487 | * to save state. | 6538 | * to save state. |
6488 | */ | 6539 | */ |
6489 | ret = BEGIN_LP_RING(6); | 6540 | ret = BEGIN_LP_RING(6); |
6490 | if (ret) { | 6541 | if (ret) { |
6491 | ironlake_disable_rc6(dev); | 6542 | ironlake_teardown_rc6(dev); |
6492 | return; | 6543 | return; |
6493 | } | 6544 | } |
6545 | |||
6494 | OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); | 6546 | OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); |
6495 | OUT_RING(MI_SET_CONTEXT); | 6547 | OUT_RING(MI_SET_CONTEXT); |
6496 | OUT_RING(dev_priv->renderctx->gtt_offset | | 6548 | OUT_RING(dev_priv->renderctx->gtt_offset | |
@@ -6507,6 +6559,7 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
6507 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 6559 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
6508 | } | 6560 | } |
6509 | 6561 | ||
6562 | |||
6510 | /* Set up chip specific display functions */ | 6563 | /* Set up chip specific display functions */ |
6511 | static void intel_init_display(struct drm_device *dev) | 6564 | static void intel_init_display(struct drm_device *dev) |
6512 | { | 6565 | { |
@@ -6749,21 +6802,9 @@ void intel_modeset_init(struct drm_device *dev) | |||
6749 | if (IS_GEN6(dev)) | 6802 | if (IS_GEN6(dev)) |
6750 | gen6_enable_rps(dev_priv); | 6803 | gen6_enable_rps(dev_priv); |
6751 | 6804 | ||
6752 | if (IS_IRONLAKE_M(dev)) { | 6805 | if (IS_IRONLAKE_M(dev)) |
6753 | dev_priv->renderctx = intel_alloc_context_page(dev); | ||
6754 | if (!dev_priv->renderctx) | ||
6755 | goto skip_rc6; | ||
6756 | dev_priv->pwrctx = intel_alloc_context_page(dev); | ||
6757 | if (!dev_priv->pwrctx) { | ||
6758 | i915_gem_object_unpin(dev_priv->renderctx); | ||
6759 | drm_gem_object_unreference(&dev_priv->renderctx->base); | ||
6760 | dev_priv->renderctx = NULL; | ||
6761 | goto skip_rc6; | ||
6762 | } | ||
6763 | ironlake_enable_rc6(dev); | 6806 | ironlake_enable_rc6(dev); |
6764 | } | ||
6765 | 6807 | ||
6766 | skip_rc6: | ||
6767 | INIT_WORK(&dev_priv->idle_work, intel_idle_update); | 6808 | INIT_WORK(&dev_priv->idle_work, intel_idle_update); |
6768 | setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, | 6809 | setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, |
6769 | (unsigned long)dev); | 6810 | (unsigned long)dev); |