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.c131
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
1216static 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
1216static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 1236static 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
5554static 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
5533static struct drm_crtc_helper_funcs intel_helper_funcs = { 5564static 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
5543static const struct drm_crtc_funcs intel_crtc_funcs = { 5574static 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
6432void intel_disable_clock_gating(struct drm_device *dev) 6465static 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
6482static 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
6459static void ironlake_disable_rc6(struct drm_device *dev) 6502static 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
6480void ironlake_enable_rc6(struct drm_device *dev) 6521void 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 */
6511static void intel_init_display(struct drm_device *dev) 6564static 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
6766skip_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);