diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 106 |
1 files changed, 62 insertions, 44 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d7f237deaaf0..3b006536b3d2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -5551,6 +5551,16 @@ cleanup_work: | |||
5551 | return ret; | 5551 | return ret; |
5552 | } | 5552 | } |
5553 | 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 | |||
5554 | static struct drm_crtc_helper_funcs intel_helper_funcs = { | 5564 | static struct drm_crtc_helper_funcs intel_helper_funcs = { |
5555 | .dpms = intel_crtc_dpms, | 5565 | .dpms = intel_crtc_dpms, |
5556 | .mode_fixup = intel_crtc_mode_fixup, | 5566 | .mode_fixup = intel_crtc_mode_fixup, |
@@ -5562,6 +5572,7 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = { | |||
5562 | }; | 5572 | }; |
5563 | 5573 | ||
5564 | static const struct drm_crtc_funcs intel_crtc_funcs = { | 5574 | static const struct drm_crtc_funcs intel_crtc_funcs = { |
5575 | .reset = intel_crtc_reset, | ||
5565 | .cursor_set = intel_crtc_cursor_set, | 5576 | .cursor_set = intel_crtc_cursor_set, |
5566 | .cursor_move = intel_crtc_cursor_move, | 5577 | .cursor_move = intel_crtc_cursor_move, |
5567 | .gamma_set = intel_crtc_gamma_set, | 5578 | .gamma_set = intel_crtc_gamma_set, |
@@ -5652,8 +5663,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
5652 | 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; |
5653 | 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; |
5654 | 5665 | ||
5655 | intel_crtc->cursor_addr = 0; | 5666 | intel_crtc_reset(&intel_crtc->base); |
5656 | intel_crtc->dpms_mode = -1; | ||
5657 | 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 */ |
5658 | 5668 | ||
5659 | if (HAS_PCH_SPLIT(dev)) { | 5669 | if (HAS_PCH_SPLIT(dev)) { |
@@ -6452,52 +6462,60 @@ void intel_enable_clock_gating(struct drm_device *dev) | |||
6452 | } | 6462 | } |
6453 | } | 6463 | } |
6454 | 6464 | ||
6455 | void intel_disable_clock_gating(struct drm_device *dev) | 6465 | static void ironlake_teardown_rc6(struct drm_device *dev) |
6456 | { | 6466 | { |
6457 | struct drm_i915_private *dev_priv = dev->dev_private; | 6467 | struct drm_i915_private *dev_priv = dev->dev_private; |
6458 | 6468 | ||
6459 | if (dev_priv->renderctx) { | 6469 | if (dev_priv->renderctx) { |
6460 | struct drm_i915_gem_object *obj = dev_priv->renderctx; | 6470 | i915_gem_object_unpin(dev_priv->renderctx); |
6461 | 6471 | drm_gem_object_unreference(&dev_priv->renderctx->base); | |
6462 | I915_WRITE(CCID, 0); | ||
6463 | POSTING_READ(CCID); | ||
6464 | |||
6465 | i915_gem_object_unpin(obj); | ||
6466 | drm_gem_object_unreference(&obj->base); | ||
6467 | dev_priv->renderctx = NULL; | 6472 | dev_priv->renderctx = NULL; |
6468 | } | 6473 | } |
6469 | 6474 | ||
6470 | if (dev_priv->pwrctx) { | 6475 | if (dev_priv->pwrctx) { |
6471 | 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); | ||
6472 | 6491 | ||
6473 | I915_WRITE(PWRCTXA, 0); | 6492 | I915_WRITE(PWRCTXA, 0); |
6474 | POSTING_READ(PWRCTXA); | 6493 | POSTING_READ(PWRCTXA); |
6475 | 6494 | ||
6476 | i915_gem_object_unpin(obj); | 6495 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
6477 | drm_gem_object_unreference(&obj->base); | 6496 | POSTING_READ(RSTDBYCTL); |
6478 | dev_priv->pwrctx = NULL; | ||
6479 | } | 6497 | } |
6498 | |||
6499 | ironlake_disable_rc6(dev); | ||
6480 | } | 6500 | } |
6481 | 6501 | ||
6482 | static void ironlake_disable_rc6(struct drm_device *dev) | 6502 | static int ironlake_setup_rc6(struct drm_device *dev) |
6483 | { | 6503 | { |
6484 | struct drm_i915_private *dev_priv = dev->dev_private; | 6504 | struct drm_i915_private *dev_priv = dev->dev_private; |
6485 | 6505 | ||
6486 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ | 6506 | if (dev_priv->renderctx == NULL) |
6487 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); | 6507 | dev_priv->renderctx = intel_alloc_context_page(dev); |
6488 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), | 6508 | if (!dev_priv->renderctx) |
6489 | 10); | 6509 | return -ENOMEM; |
6490 | POSTING_READ(CCID); | 6510 | |
6491 | I915_WRITE(PWRCTXA, 0); | 6511 | if (dev_priv->pwrctx == NULL) |
6492 | POSTING_READ(PWRCTXA); | 6512 | dev_priv->pwrctx = intel_alloc_context_page(dev); |
6493 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 6513 | if (!dev_priv->pwrctx) { |
6494 | POSTING_READ(RSTDBYCTL); | 6514 | ironlake_teardown_rc6(dev); |
6495 | i915_gem_object_unpin(dev_priv->renderctx); | 6515 | return -ENOMEM; |
6496 | drm_gem_object_unreference(&dev_priv->renderctx->base); | 6516 | } |
6497 | dev_priv->renderctx = NULL; | 6517 | |
6498 | i915_gem_object_unpin(dev_priv->pwrctx); | 6518 | return 0; |
6499 | drm_gem_object_unreference(&dev_priv->pwrctx->base); | ||
6500 | dev_priv->pwrctx = NULL; | ||
6501 | } | 6519 | } |
6502 | 6520 | ||
6503 | void ironlake_enable_rc6(struct drm_device *dev) | 6521 | void ironlake_enable_rc6(struct drm_device *dev) |
@@ -6505,15 +6523,26 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
6505 | struct drm_i915_private *dev_priv = dev->dev_private; | 6523 | struct drm_i915_private *dev_priv = dev->dev_private; |
6506 | int ret; | 6524 | int ret; |
6507 | 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 | |||
6508 | /* | 6536 | /* |
6509 | * 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 |
6510 | * to save state. | 6538 | * to save state. |
6511 | */ | 6539 | */ |
6512 | ret = BEGIN_LP_RING(6); | 6540 | ret = BEGIN_LP_RING(6); |
6513 | if (ret) { | 6541 | if (ret) { |
6514 | ironlake_disable_rc6(dev); | 6542 | ironlake_teardown_rc6(dev); |
6515 | return; | 6543 | return; |
6516 | } | 6544 | } |
6545 | |||
6517 | OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); | 6546 | OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); |
6518 | OUT_RING(MI_SET_CONTEXT); | 6547 | OUT_RING(MI_SET_CONTEXT); |
6519 | OUT_RING(dev_priv->renderctx->gtt_offset | | 6548 | OUT_RING(dev_priv->renderctx->gtt_offset | |
@@ -6530,6 +6559,7 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
6530 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 6559 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
6531 | } | 6560 | } |
6532 | 6561 | ||
6562 | |||
6533 | /* Set up chip specific display functions */ | 6563 | /* Set up chip specific display functions */ |
6534 | static void intel_init_display(struct drm_device *dev) | 6564 | static void intel_init_display(struct drm_device *dev) |
6535 | { | 6565 | { |
@@ -6772,21 +6802,9 @@ void intel_modeset_init(struct drm_device *dev) | |||
6772 | if (IS_GEN6(dev)) | 6802 | if (IS_GEN6(dev)) |
6773 | gen6_enable_rps(dev_priv); | 6803 | gen6_enable_rps(dev_priv); |
6774 | 6804 | ||
6775 | if (IS_IRONLAKE_M(dev)) { | 6805 | if (IS_IRONLAKE_M(dev)) |
6776 | dev_priv->renderctx = intel_alloc_context_page(dev); | ||
6777 | if (!dev_priv->renderctx) | ||
6778 | goto skip_rc6; | ||
6779 | dev_priv->pwrctx = intel_alloc_context_page(dev); | ||
6780 | if (!dev_priv->pwrctx) { | ||
6781 | i915_gem_object_unpin(dev_priv->renderctx); | ||
6782 | drm_gem_object_unreference(&dev_priv->renderctx->base); | ||
6783 | dev_priv->renderctx = NULL; | ||
6784 | goto skip_rc6; | ||
6785 | } | ||
6786 | ironlake_enable_rc6(dev); | 6806 | ironlake_enable_rc6(dev); |
6787 | } | ||
6788 | 6807 | ||
6789 | skip_rc6: | ||
6790 | INIT_WORK(&dev_priv->idle_work, intel_idle_update); | 6808 | INIT_WORK(&dev_priv->idle_work, intel_idle_update); |
6791 | setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, | 6809 | setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, |
6792 | (unsigned long)dev); | 6810 | (unsigned long)dev); |