aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c83
1 files changed, 31 insertions, 52 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index cbf31cbfa084..cf288a95347c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -335,7 +335,8 @@ void i9xx_check_fifo_underruns(struct drm_device *dev)
335} 335}
336 336
337static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, 337static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
338 enum pipe pipe, bool enable) 338 enum pipe pipe,
339 bool enable, bool old)
339{ 340{
340 struct drm_i915_private *dev_priv = dev->dev_private; 341 struct drm_i915_private *dev_priv = dev->dev_private;
341 u32 reg = PIPESTAT(pipe); 342 u32 reg = PIPESTAT(pipe);
@@ -347,7 +348,7 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
347 I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); 348 I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
348 POSTING_READ(reg); 349 POSTING_READ(reg);
349 } else { 350 } else {
350 if (pipestat & PIPE_FIFO_UNDERRUN_STATUS) 351 if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS)
351 DRM_ERROR("pipe %c underrun\n", pipe_name(pipe)); 352 DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
352 } 353 }
353} 354}
@@ -366,7 +367,8 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
366} 367}
367 368
368static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, 369static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
369 enum pipe pipe, bool enable) 370 enum pipe pipe,
371 bool enable, bool old)
370{ 372{
371 struct drm_i915_private *dev_priv = dev->dev_private; 373 struct drm_i915_private *dev_priv = dev->dev_private;
372 if (enable) { 374 if (enable) {
@@ -379,7 +381,8 @@ static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
379 } else { 381 } else {
380 ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB); 382 ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
381 383
382 if (I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) { 384 if (old &&
385 I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
383 DRM_ERROR("uncleared fifo underrun on pipe %c\n", 386 DRM_ERROR("uncleared fifo underrun on pipe %c\n",
384 pipe_name(pipe)); 387 pipe_name(pipe));
385 } 388 }
@@ -444,7 +447,7 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
444 447
445static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, 448static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
446 enum transcoder pch_transcoder, 449 enum transcoder pch_transcoder,
447 bool enable) 450 bool enable, bool old)
448{ 451{
449 struct drm_i915_private *dev_priv = dev->dev_private; 452 struct drm_i915_private *dev_priv = dev->dev_private;
450 453
@@ -459,7 +462,8 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
459 } else { 462 } else {
460 ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT); 463 ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
461 464
462 if (I915_READ(SERR_INT) & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) { 465 if (old && I915_READ(SERR_INT) &
466 SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
463 DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n", 467 DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
464 transcoder_name(pch_transcoder)); 468 transcoder_name(pch_transcoder));
465 } 469 }
@@ -486,28 +490,23 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
486 struct drm_i915_private *dev_priv = dev->dev_private; 490 struct drm_i915_private *dev_priv = dev->dev_private;
487 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; 491 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
488 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 492 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
489 bool ret; 493 bool old;
490 494
491 assert_spin_locked(&dev_priv->irq_lock); 495 assert_spin_locked(&dev_priv->irq_lock);
492 496
493 ret = !intel_crtc->cpu_fifo_underrun_disabled; 497 old = !intel_crtc->cpu_fifo_underrun_disabled;
494
495 if (enable == ret)
496 goto done;
497
498 intel_crtc->cpu_fifo_underrun_disabled = !enable; 498 intel_crtc->cpu_fifo_underrun_disabled = !enable;
499 499
500 if (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev)) 500 if (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev))
501 i9xx_set_fifo_underrun_reporting(dev, pipe, enable); 501 i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
502 else if (IS_GEN5(dev) || IS_GEN6(dev)) 502 else if (IS_GEN5(dev) || IS_GEN6(dev))
503 ironlake_set_fifo_underrun_reporting(dev, pipe, enable); 503 ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
504 else if (IS_GEN7(dev)) 504 else if (IS_GEN7(dev))
505 ivybridge_set_fifo_underrun_reporting(dev, pipe, enable); 505 ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
506 else if (IS_GEN8(dev)) 506 else if (IS_GEN8(dev))
507 broadwell_set_fifo_underrun_reporting(dev, pipe, enable); 507 broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
508 508
509done: 509 return old;
510 return ret;
511} 510}
512 511
513bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, 512bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
@@ -556,7 +555,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
556 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder]; 555 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
557 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 556 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
558 unsigned long flags; 557 unsigned long flags;
559 bool ret; 558 bool old;
560 559
561 /* 560 /*
562 * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT 561 * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
@@ -569,21 +568,16 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
569 568
570 spin_lock_irqsave(&dev_priv->irq_lock, flags); 569 spin_lock_irqsave(&dev_priv->irq_lock, flags);
571 570
572 ret = !intel_crtc->pch_fifo_underrun_disabled; 571 old = !intel_crtc->pch_fifo_underrun_disabled;
573
574 if (enable == ret)
575 goto done;
576
577 intel_crtc->pch_fifo_underrun_disabled = !enable; 572 intel_crtc->pch_fifo_underrun_disabled = !enable;
578 573
579 if (HAS_PCH_IBX(dev)) 574 if (HAS_PCH_IBX(dev))
580 ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable); 575 ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
581 else 576 else
582 cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable); 577 cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable, old);
583 578
584done:
585 spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 579 spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
586 return ret; 580 return old;
587} 581}
588 582
589 583
@@ -2634,10 +2628,6 @@ static int i915_enable_vblank(struct drm_device *dev, int pipe)
2634 else 2628 else
2635 i915_enable_pipestat(dev_priv, pipe, 2629 i915_enable_pipestat(dev_priv, pipe,
2636 PIPE_VBLANK_INTERRUPT_STATUS); 2630 PIPE_VBLANK_INTERRUPT_STATUS);
2637
2638 /* maintain vblank delivery even in deep C-states */
2639 if (INTEL_INFO(dev)->gen == 3)
2640 I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_AGPBUSY_DIS));
2641 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2631 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2642 2632
2643 return 0; 2633 return 0;
@@ -2701,9 +2691,6 @@ static void i915_disable_vblank(struct drm_device *dev, int pipe)
2701 unsigned long irqflags; 2691 unsigned long irqflags;
2702 2692
2703 spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2693 spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2704 if (INTEL_INFO(dev)->gen == 3)
2705 I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS));
2706
2707 i915_disable_pipestat(dev_priv, pipe, 2694 i915_disable_pipestat(dev_priv, pipe,
2708 PIPE_VBLANK_INTERRUPT_STATUS | 2695 PIPE_VBLANK_INTERRUPT_STATUS |
2709 PIPE_START_VBLANK_INTERRUPT_STATUS); 2696 PIPE_START_VBLANK_INTERRUPT_STATUS);
@@ -3117,11 +3104,6 @@ static void ironlake_irq_reset(struct drm_device *dev)
3117 ibx_irq_reset(dev); 3104 ibx_irq_reset(dev);
3118} 3105}
3119 3106
3120static void ironlake_irq_preinstall(struct drm_device *dev)
3121{
3122 ironlake_irq_reset(dev);
3123}
3124
3125static void valleyview_irq_preinstall(struct drm_device *dev) 3107static void valleyview_irq_preinstall(struct drm_device *dev)
3126{ 3108{
3127 struct drm_i915_private *dev_priv = dev->dev_private; 3109 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3151,6 +3133,14 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
3151 POSTING_READ(VLV_IER); 3133 POSTING_READ(VLV_IER);
3152} 3134}
3153 3135
3136static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv)
3137{
3138 GEN8_IRQ_RESET_NDX(GT, 0);
3139 GEN8_IRQ_RESET_NDX(GT, 1);
3140 GEN8_IRQ_RESET_NDX(GT, 2);
3141 GEN8_IRQ_RESET_NDX(GT, 3);
3142}
3143
3154static void gen8_irq_reset(struct drm_device *dev) 3144static void gen8_irq_reset(struct drm_device *dev)
3155{ 3145{
3156 struct drm_i915_private *dev_priv = dev->dev_private; 3146 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3159,10 +3149,7 @@ static void gen8_irq_reset(struct drm_device *dev)
3159 I915_WRITE(GEN8_MASTER_IRQ, 0); 3149 I915_WRITE(GEN8_MASTER_IRQ, 0);
3160 POSTING_READ(GEN8_MASTER_IRQ); 3150 POSTING_READ(GEN8_MASTER_IRQ);
3161 3151
3162 GEN8_IRQ_RESET_NDX(GT, 0); 3152 gen8_gt_irq_reset(dev_priv);
3163 GEN8_IRQ_RESET_NDX(GT, 1);
3164 GEN8_IRQ_RESET_NDX(GT, 2);
3165 GEN8_IRQ_RESET_NDX(GT, 3);
3166 3153
3167 for_each_pipe(pipe) 3154 for_each_pipe(pipe)
3168 GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); 3155 GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
@@ -3174,11 +3161,6 @@ static void gen8_irq_reset(struct drm_device *dev)
3174 ibx_irq_reset(dev); 3161 ibx_irq_reset(dev);
3175} 3162}
3176 3163
3177static void gen8_irq_preinstall(struct drm_device *dev)
3178{
3179 gen8_irq_reset(dev);
3180}
3181
3182static void cherryview_irq_preinstall(struct drm_device *dev) 3164static void cherryview_irq_preinstall(struct drm_device *dev)
3183{ 3165{
3184 struct drm_i915_private *dev_priv = dev->dev_private; 3166 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3187,10 +3169,7 @@ static void cherryview_irq_preinstall(struct drm_device *dev)
3187 I915_WRITE(GEN8_MASTER_IRQ, 0); 3169 I915_WRITE(GEN8_MASTER_IRQ, 0);
3188 POSTING_READ(GEN8_MASTER_IRQ); 3170 POSTING_READ(GEN8_MASTER_IRQ);
3189 3171
3190 GEN8_IRQ_RESET_NDX(GT, 0); 3172 gen8_gt_irq_reset(dev_priv);
3191 GEN8_IRQ_RESET_NDX(GT, 1);
3192 GEN8_IRQ_RESET_NDX(GT, 2);
3193 GEN8_IRQ_RESET_NDX(GT, 3);
3194 3173
3195 GEN5_IRQ_RESET(GEN8_PCU_); 3174 GEN5_IRQ_RESET(GEN8_PCU_);
3196 3175
@@ -4387,7 +4366,7 @@ void intel_irq_init(struct drm_device *dev)
4387 dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 4366 dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
4388 } else if (IS_GEN8(dev)) { 4367 } else if (IS_GEN8(dev)) {
4389 dev->driver->irq_handler = gen8_irq_handler; 4368 dev->driver->irq_handler = gen8_irq_handler;
4390 dev->driver->irq_preinstall = gen8_irq_preinstall; 4369 dev->driver->irq_preinstall = gen8_irq_reset;
4391 dev->driver->irq_postinstall = gen8_irq_postinstall; 4370 dev->driver->irq_postinstall = gen8_irq_postinstall;
4392 dev->driver->irq_uninstall = gen8_irq_uninstall; 4371 dev->driver->irq_uninstall = gen8_irq_uninstall;
4393 dev->driver->enable_vblank = gen8_enable_vblank; 4372 dev->driver->enable_vblank = gen8_enable_vblank;
@@ -4395,7 +4374,7 @@ void intel_irq_init(struct drm_device *dev)
4395 dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; 4374 dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
4396 } else if (HAS_PCH_SPLIT(dev)) { 4375 } else if (HAS_PCH_SPLIT(dev)) {
4397 dev->driver->irq_handler = ironlake_irq_handler; 4376 dev->driver->irq_handler = ironlake_irq_handler;
4398 dev->driver->irq_preinstall = ironlake_irq_preinstall; 4377 dev->driver->irq_preinstall = ironlake_irq_reset;
4399 dev->driver->irq_postinstall = ironlake_irq_postinstall; 4378 dev->driver->irq_postinstall = ironlake_irq_postinstall;
4400 dev->driver->irq_uninstall = ironlake_irq_uninstall; 4379 dev->driver->irq_uninstall = ironlake_irq_uninstall;
4401 dev->driver->enable_vblank = ironlake_enable_vblank; 4380 dev->driver->enable_vblank = ironlake_enable_vblank;