@@ -232,6 +232,18 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
return true;
}
+static void i9xx_clear_fifo_underrun(struct drm_device *dev, enum pipe pipe)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 reg = PIPESTAT(pipe);
+ u32 pipestat = I915_READ(reg) & 0x7fff0000;
+
+ assert_spin_locked(&dev_priv->irq_lock);
+
+ I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
+ POSTING_READ(reg);
+}
+
static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
@@ -393,7 +405,9 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
intel_crtc->cpu_fifo_underrun_disabled = !enable;
- if (IS_GEN5(dev) || IS_GEN6(dev))
+ if (enable && (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev)))
+ i9xx_clear_fifo_underrun(dev, pipe);
+ else if (IS_GEN5(dev) || IS_GEN6(dev))
ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
else if (IS_GEN7(dev))
ivybridge_set_fifo_underrun_reporting(dev, pipe, enable);
@@ -1466,12 +1480,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
/*
* Clear the PIPE*STAT regs before the IIR
*/
- if (pipe_stats[pipe] & 0x8000ffff) {
- if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
- DRM_DEBUG_DRIVER("pipe %c underrun\n",
- pipe_name(pipe));
+ if (pipe_stats[pipe] & 0x8000ffff)
I915_WRITE(reg, pipe_stats[pipe]);
- }
}
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -1486,6 +1496,10 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe);
+
+ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
+ intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
+ DRM_DEBUG_DRIVER("pipe %c underrun\n", pipe_name(pipe));
}
/* Consume port. Then clear IIR or we'll miss events */
@@ -3208,12 +3222,8 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
/*
* Clear the PIPE*STAT regs before the IIR
*/
- if (pipe_stats[pipe] & 0x8000ffff) {
- if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
- DRM_DEBUG_DRIVER("pipe %c underrun\n",
- pipe_name(pipe));
+ if (pipe_stats[pipe] & 0x8000ffff)
I915_WRITE(reg, pipe_stats[pipe]);
- }
}
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -3236,6 +3246,10 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe);
+
+ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
+ intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
+ DRM_DEBUG_DRIVER("pipe %c underrun\n", pipe_name(pipe));
}
iir = new_iir;
@@ -3389,9 +3403,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
/* Clear the PIPE*STAT regs before the IIR */
if (pipe_stats[pipe] & 0x8000ffff) {
- if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
- DRM_DEBUG_DRIVER("pipe %c underrun\n",
- pipe_name(pipe));
I915_WRITE(reg, pipe_stats[pipe]);
irq_received = true;
}
@@ -3433,6 +3444,10 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe);
+
+ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
+ intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
+ DRM_DEBUG_DRIVER("pipe %c underrun\n", pipe_name(pipe));
}
if (blc_event || (iir & I915_ASLE_INTERRUPT))
@@ -3627,9 +3642,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
* Clear the PIPE*STAT regs before the IIR
*/
if (pipe_stats[pipe] & 0x8000ffff) {
- if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
- DRM_DEBUG_DRIVER("pipe %c underrun\n",
- pipe_name(pipe));
I915_WRITE(reg, pipe_stats[pipe]);
irq_received = true;
}
@@ -3677,8 +3689,11 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe);
- }
+ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
+ intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
+ DRM_DEBUG_DRIVER("pipe %c underrun\n", pipe_name(pipe));
+ }
if (blc_event || (iir & I915_ASLE_INTERRUPT))
intel_opregion_asle_intr(dev);
@@ -4170,6 +4170,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_update_watermarks(crtc);
intel_enable_pipe(dev_priv, pipe, false, is_dsi);
+ intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
intel_enable_primary_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc);
intel_crtc_update_cursor(crtc, true);
@@ -4208,6 +4209,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_update_watermarks(crtc);
intel_enable_pipe(dev_priv, pipe, false, false);
+ intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
intel_enable_primary_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc);
/* The fixup needs to happen before cursor is enabled */
@@ -4266,6 +4268,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_disable_planes(crtc);
intel_disable_primary_plane(dev_priv, plane, pipe);
+ intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
intel_disable_pipe(dev_priv, pipe);
i9xx_pfit_disable(intel_crtc);