mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-16 09:57:40 +07:00
drm/i915: Check for FIFO underruns after modeset on IVB/HSW and CPT/PPT
Due to the shared error interrupt on IVB/HSW and CPT/PPT we may not always get an interrupt on a FIFO underrun. But we can always do an explicit check (like we do on GMCH platforms that have no underrun interrupt). v2: Drop stale kerneldoc for i9xx_check_fifo_underruns() (Daniel) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/1446225741-11070-1-git-send-email-ville.syrjala@linux.intel.com
This commit is contained in:
parent
81b088ca87
commit
aca7b684ba
@ -4688,9 +4688,9 @@ intel_post_enable_primary(struct drm_crtc *crtc)
|
||||
if (IS_GEN2(dev))
|
||||
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
||||
|
||||
/* Underruns don't raise interrupts, so check manually. */
|
||||
if (HAS_GMCH_DISPLAY(dev))
|
||||
i9xx_check_fifo_underruns(dev_priv);
|
||||
/* Underruns don't always raise interrupts, so check manually. */
|
||||
intel_check_cpu_fifo_underruns(dev_priv);
|
||||
intel_check_pch_fifo_underruns(dev_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -965,7 +965,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe);
|
||||
void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
|
||||
enum transcoder pch_transcoder);
|
||||
void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv);
|
||||
void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv);
|
||||
void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv);
|
||||
|
||||
/* i915_irq.c */
|
||||
void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
|
||||
|
@ -84,38 +84,21 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* i9xx_check_fifo_underruns - check for fifo underruns
|
||||
* @dev_priv: i915 device instance
|
||||
*
|
||||
* This function checks for fifo underruns on GMCH platforms. This needs to be
|
||||
* done manually on modeset to make sure that we catch all underruns since they
|
||||
* do not generate an interrupt by themselves on these platforms.
|
||||
*/
|
||||
void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv)
|
||||
static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *crtc;
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 reg = PIPESTAT(crtc->pipe);
|
||||
u32 pipestat = I915_READ(reg) & 0xffff0000;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
assert_spin_locked(&dev_priv->irq_lock);
|
||||
|
||||
for_each_intel_crtc(dev_priv->dev, crtc) {
|
||||
u32 reg = PIPESTAT(crtc->pipe);
|
||||
u32 pipestat;
|
||||
if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
|
||||
return;
|
||||
|
||||
if (crtc->cpu_fifo_underrun_disabled)
|
||||
continue;
|
||||
I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
|
||||
POSTING_READ(reg);
|
||||
|
||||
pipestat = I915_READ(reg) & 0xffff0000;
|
||||
if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
|
||||
continue;
|
||||
|
||||
I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
|
||||
POSTING_READ(reg);
|
||||
|
||||
DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
|
||||
}
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
|
||||
}
|
||||
|
||||
static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
@ -150,6 +133,23 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
ironlake_disable_display_irq(dev_priv, bit);
|
||||
}
|
||||
|
||||
static void ivybridge_check_fifo_underruns(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
uint32_t err_int = I915_READ(GEN7_ERR_INT);
|
||||
|
||||
assert_spin_locked(&dev_priv->irq_lock);
|
||||
|
||||
if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0)
|
||||
return;
|
||||
|
||||
I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
|
||||
POSTING_READ(GEN7_ERR_INT);
|
||||
|
||||
DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe));
|
||||
}
|
||||
|
||||
static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
enum pipe pipe,
|
||||
bool enable, bool old)
|
||||
@ -202,6 +202,24 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
ibx_disable_display_interrupt(dev_priv, bit);
|
||||
}
|
||||
|
||||
static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum transcoder pch_transcoder = (enum transcoder) crtc->pipe;
|
||||
uint32_t serr_int = I915_READ(SERR_INT);
|
||||
|
||||
assert_spin_locked(&dev_priv->irq_lock);
|
||||
|
||||
if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0)
|
||||
return;
|
||||
|
||||
I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
|
||||
POSTING_READ(SERR_INT);
|
||||
|
||||
DRM_ERROR("pch fifo underrun on pch transcoder %c\n",
|
||||
transcoder_name(pch_transcoder));
|
||||
}
|
||||
|
||||
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
enum transcoder pch_transcoder,
|
||||
bool enable, bool old)
|
||||
@ -375,3 +393,56 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
|
||||
DRM_ERROR("PCH transcoder %c FIFO underrun\n",
|
||||
transcoder_name(pch_transcoder));
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately
|
||||
* @dev_priv: i915 device instance
|
||||
*
|
||||
* Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared
|
||||
* error interrupt may have been disabled, and so CPU fifo underruns won't
|
||||
* necessarily raise an interrupt, and on GMCH platforms where underruns never
|
||||
* raise an interrupt.
|
||||
*/
|
||||
void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
|
||||
for_each_intel_crtc(dev_priv->dev, crtc) {
|
||||
if (crtc->cpu_fifo_underrun_disabled)
|
||||
continue;
|
||||
|
||||
if (HAS_GMCH_DISPLAY(dev_priv))
|
||||
i9xx_check_fifo_underruns(crtc);
|
||||
else if (IS_GEN7(dev_priv))
|
||||
ivybridge_check_fifo_underruns(crtc);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately
|
||||
* @dev_priv: i915 device instance
|
||||
*
|
||||
* Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared
|
||||
* error interrupt may have been disabled, and so PCH fifo underruns won't
|
||||
* necessarily raise an interrupt.
|
||||
*/
|
||||
void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
|
||||
for_each_intel_crtc(dev_priv->dev, crtc) {
|
||||
if (crtc->pch_fifo_underrun_disabled)
|
||||
continue;
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
cpt_check_pch_fifo_underruns(crtc);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user