diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 83 |
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 | ||
| 337 | static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, | 337 | static 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 | ||
| 368 | static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, | 369 | static 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 | ||
| 445 | static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, | 448 | static 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 | ||
| 509 | done: | 509 | return old; |
| 510 | return ret; | ||
| 511 | } | 510 | } |
| 512 | 511 | ||
| 513 | bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, | 512 | bool 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 | ||
| 584 | done: | ||
| 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 | ||
| 3120 | static void ironlake_irq_preinstall(struct drm_device *dev) | ||
| 3121 | { | ||
| 3122 | ironlake_irq_reset(dev); | ||
| 3123 | } | ||
| 3124 | |||
| 3125 | static void valleyview_irq_preinstall(struct drm_device *dev) | 3107 | static 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 | ||
| 3136 | static 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 | |||
| 3154 | static void gen8_irq_reset(struct drm_device *dev) | 3144 | static 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 | ||
| 3177 | static void gen8_irq_preinstall(struct drm_device *dev) | ||
| 3178 | { | ||
| 3179 | gen8_irq_reset(dev); | ||
| 3180 | } | ||
| 3181 | |||
| 3182 | static void cherryview_irq_preinstall(struct drm_device *dev) | 3164 | static 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; |
