[Intel-gfx] [PATCH 1/2] drm/i915: report Gen5+ CPU and PCH FIFO underruns
Imre Deak
imre.deak at intel.com
Thu Apr 18 22:29:17 CEST 2013
Hi,
one comment below:
On Fri, 2013-04-12 at 17:57 -0300, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni at intel.com>
>
> In this commit we enable both CPU and PCH FIFO underrun reporting and
> start reporting them. We follow a few rules:
> - after we receive one of these errors, we mask the interrupt, so
> we won't get an "interrupt storm" and we also won't flood dmesg;
> - at each mode set we enable the interrupts again, so we'll see each
> message at most once per mode set;
> - in the specific places where we need to ignore the errors, we
> completely mask the interrupts.
>
> The downside of this patch is that since we're completely disabling
> (masking) the interrupts instead of just not printing error messages,
> we will mask more than just what we want on IVB/HSW CPU interrupts
> (due to GEN7_ERR_INT) and on CPT/PPT/LPT PCHs (due to SERR_INT). So
> when we decide to mask PCH FIFO underruns for pipe A on CPT, we'll
> also be masking PCH FIFO underruns for pipe B, because both are
> reported by SERR_INT, which has to be either completely enabled or
> completely disabled (in othe words, there's no way to disable/enable
> specific bits of GEN7_ERR_INT and SERR_INT).
>
> V2: Rename some functions and variables, downgrade messages to
> DRM_DEBUG_DRIVER and rebase.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
> ---
> drivers/gpu/drm/i915/i915_irq.c | 315 +++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/i915/i915_reg.h | 13 +-
> drivers/gpu/drm/i915/intel_display.c | 14 ++
> drivers/gpu/drm/i915/intel_drv.h | 11 ++
> 4 files changed, 342 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index e97bbb2..9aff6ed 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -111,6 +111,213 @@ ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
> }
> }
>
> +static bool ivb_can_enable_err_int(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_crtc *crtc;
> + enum pipe pipe;
> +
> + for_each_pipe(pipe) {
> + crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
> +
> + if (crtc->cpu_fifo_underrun_disabled)
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static bool cpt_can_enable_serr_int(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + enum pipe pipe;
> + struct intel_crtc *crtc;
> +
> + for_each_pipe(pipe) {
> + crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
> +
> + if (crtc->pch_fifo_underrun_disabled)
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
> + enum pipe pipe, bool enable)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + uint32_t bit = (pipe == PIPE_A) ? DE_PIPEA_FIFO_UNDERRUN :
> + DE_PIPEB_FIFO_UNDERRUN;
> +
> + if (enable)
> + ironlake_enable_display_irq(dev_priv, bit);
> + else
> + ironlake_disable_display_irq(dev_priv, bit);
> +}
> +
> +static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
> + bool enable)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + if (enable) {
> + if (!ivb_can_enable_err_int(dev))
> + return;
> +
> + I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN_A |
> + ERR_INT_FIFO_UNDERRUN_B |
> + ERR_INT_FIFO_UNDERRUN_C);
> +
> + ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
> + } else {
> + ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
> + }
> +}
> +
> +static void ibx_set_fifo_underrun_reporting(struct intel_crtc *crtc,
> + bool enable)
> +{
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + uint32_t bit = (crtc->pipe == PIPE_A) ? SDE_TRANSA_FIFO_UNDER :
> + SDE_TRANSB_FIFO_UNDER;
> +
> + if (enable)
> + I915_WRITE(SDEIMR, I915_READ(SDEIMR) & ~bit);
> + else
> + I915_WRITE(SDEIMR, I915_READ(SDEIMR) | bit);
> +
> + POSTING_READ(SDEIMR);
> +}
> +
> +static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
> + enum transcoder pch_transcoder,
> + bool enable)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + if (enable) {
> + if (!cpt_can_enable_serr_int(dev))
> + return;
> +
> + I915_WRITE(SERR_INT, SERR_INT_TRANS_A_FIFO_UNDERRUN |
> + SERR_INT_TRANS_B_FIFO_UNDERRUN |
> + SERR_INT_TRANS_C_FIFO_UNDERRUN);
We end up here for LPT too, but there only the TRANS_A bit is defined.
Otherwise looks good:
Reviewed-by: Imre Deak <imre.deak at intel.com>
> +
> + I915_WRITE(SDEIMR, I915_READ(SDEIMR) & ~SDE_ERROR_CPT);
> + } else {
> + I915_WRITE(SDEIMR, I915_READ(SDEIMR) | SDE_ERROR_CPT);
> + }
> +
> + POSTING_READ(SDEIMR);
> +}
> +
> +/**
> + * intel_set_cpu_fifo_underrun_reporting - enable/disable FIFO underrun messages
> + * @dev: drm device
> + * @pipe: pipe
> + * @enable: true if we want to report FIFO underrun errors, false otherwise
> + *
> + * This function makes us disable or enable CPU fifo underruns for a specific
> + * pipe. Notice that on some Gens (e.g. IVB, HSW), disabling FIFO underrun
> + * reporting for one pipe may also disable all the other CPU error interruts for
> + * the other pipes, due to the fact that there's just one interrupt mask/enable
> + * bit for all the pipes.
> + *
> + * Returns the previous state of underrun reporting.
> + */
> +bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
> + enum pipe pipe, bool enable)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + unsigned long flags;
> + bool ret;
> +
> + spin_lock_irqsave(&dev_priv->irq_lock, flags);
> +
> + ret = !intel_crtc->cpu_fifo_underrun_disabled;
> +
> + if (enable == ret)
> + goto done;
> +
> + intel_crtc->cpu_fifo_underrun_disabled = !enable;
> +
> + 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, enable);
> +
> +done:
> + spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
> + return ret;
> +}
> +
> +/**
> + * intel_set_pch_fifo_underrun_reporting - enable/disable FIFO underrun messages
> + * @dev: drm device
> + * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
> + * @enable: true if we want to report FIFO underrun errors, false otherwise
> + *
> + * This function makes us disable or enable PCH fifo underruns for a specific
> + * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
> + * underrun reporting for one transcoder may also disable all the other PCH
> + * error interruts for the other transcoders, due to the fact that there's just
> + * one interrupt mask/enable bit for all the transcoders.
> + *
> + * Returns the previous state of underrun reporting.
> + */
> +bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
> + enum transcoder pch_transcoder,
> + bool enable)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + enum pipe p;
> + struct drm_crtc *crtc;
> + struct intel_crtc *intel_crtc;
> + unsigned long flags;
> + bool ret;
> +
> + if (HAS_PCH_LPT(dev)) {
> + crtc = NULL;
> + for_each_pipe(p) {
> + struct drm_crtc *c = dev_priv->pipe_to_crtc_mapping[p];
> + if (intel_pipe_has_type(c, INTEL_OUTPUT_ANALOG)) {
> + crtc = c;
> + break;
> + }
> + }
> + if (!crtc) {
> + DRM_ERROR("PCH FIFO underrun, but no CRTC using the PCH found\n");
> + return false;
> + }
> + } else {
> + crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
> + }
> + intel_crtc = to_intel_crtc(crtc);
> +
> + spin_lock_irqsave(&dev_priv->irq_lock, flags);
> +
> + ret = !intel_crtc->pch_fifo_underrun_disabled;
> +
> + if (enable == ret)
> + goto done;
> +
> + intel_crtc->pch_fifo_underrun_disabled = !enable;
> +
> + if (HAS_PCH_IBX(dev))
> + ibx_set_fifo_underrun_reporting(intel_crtc, enable);
> + else
> + cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
> +
> +done:
> + spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
> + return ret;
> +}
> +
> +
> void
> i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
> {
> @@ -716,10 +923,58 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
> if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
> DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n");
>
> - if (pch_iir & SDE_TRANSB_FIFO_UNDER)
> - DRM_DEBUG_DRIVER("PCH transcoder B underrun interrupt\n");
> if (pch_iir & SDE_TRANSA_FIFO_UNDER)
> - DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n");
> + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A,
> + false))
> + DRM_DEBUG_DRIVER("PCH transcoder A FIFO underrun\n");
> +
> + if (pch_iir & SDE_TRANSB_FIFO_UNDER)
> + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B,
> + false))
> + DRM_DEBUG_DRIVER("PCH transcoder B FIFO underrun\n");
> +}
> +
> +static void ivb_err_int_handler(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + u32 err_int = I915_READ(GEN7_ERR_INT);
> +
> + if (err_int & ERR_INT_FIFO_UNDERRUN_A)
> + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false))
> + DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
> +
> + if (err_int & ERR_INT_FIFO_UNDERRUN_B)
> + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false))
> + DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
> +
> + if (err_int & ERR_INT_FIFO_UNDERRUN_C)
> + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, false))
> + DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n");
> +
> + I915_WRITE(GEN7_ERR_INT, err_int);
> +}
> +
> +static void cpt_serr_int_handler(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + u32 serr_int = I915_READ(SERR_INT);
> +
> + if (serr_int & SERR_INT_TRANS_A_FIFO_UNDERRUN)
> + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A,
> + false))
> + DRM_DEBUG_DRIVER("PCH transcoder A FIFO underrun\n");
> +
> + if (serr_int & SERR_INT_TRANS_B_FIFO_UNDERRUN)
> + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B,
> + false))
> + DRM_DEBUG_DRIVER("PCH transcoder B FIFO underrun\n");
> +
> + if (serr_int & SERR_INT_TRANS_C_FIFO_UNDERRUN)
> + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_C,
> + false))
> + DRM_DEBUG_DRIVER("PCH transcoder C FIFO underrun\n");
> +
> + I915_WRITE(SERR_INT, serr_int);
> }
>
> static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
> @@ -752,6 +1007,9 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
> DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n",
> pipe_name(pipe),
> I915_READ(FDI_RX_IIR(pipe)));
> +
> + if (pch_iir & SDE_ERROR_CPT)
> + cpt_serr_int_handler(dev);
> }
>
> static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
> @@ -764,6 +1022,14 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
>
> atomic_inc(&dev_priv->irq_received);
>
> + /* We get interrupts on unclaimed registers, so check for this before we
> + * do any I915_{READ,WRITE}. */
> + if (IS_HASWELL(dev) &&
> + (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
> + DRM_ERROR("Unclaimed register before interrupt\n");
> + I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
> + }
> +
> /* disable master interrupt before clearing iir */
> de_ier = I915_READ(DEIER);
> I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
> @@ -779,6 +1045,12 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
> POSTING_READ(SDEIER);
> }
>
> + /* On Haswell, also mask ERR_INT because we don't want to risk
> + * generating "unclaimed register" interrupts from inside the interrupt
> + * handler. */
> + if (IS_HASWELL(dev))
> + ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
> +
> gt_iir = I915_READ(GTIIR);
> if (gt_iir) {
> snb_gt_irq_handler(dev, dev_priv, gt_iir);
> @@ -788,6 +1060,9 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
>
> de_iir = I915_READ(DEIIR);
> if (de_iir) {
> + if (de_iir & DE_ERR_INT_IVB)
> + ivb_err_int_handler(dev);
> +
> if (de_iir & DE_AUX_CHANNEL_A_IVB)
> dp_aux_irq_handler(dev);
>
> @@ -825,6 +1100,9 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
> ret = IRQ_HANDLED;
> }
>
> + if (IS_HASWELL(dev) && ivb_can_enable_err_int(dev))
> + ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
> +
> I915_WRITE(DEIER, de_ier);
> POSTING_READ(DEIER);
> if (!HAS_PCH_NOP(dev)) {
> @@ -894,6 +1172,14 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
> if (de_iir & DE_PIPEB_VBLANK)
> drm_handle_vblank(dev, 1);
>
> + if (de_iir & DE_PIPEA_FIFO_UNDERRUN)
> + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false))
> + DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
> +
> + if (de_iir & DE_PIPEB_FIFO_UNDERRUN)
> + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false))
> + DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
> +
> if (de_iir & DE_PLANEA_FLIP_DONE) {
> intel_prepare_page_flip(dev, 0);
> intel_finish_page_flip_plane(dev, 0);
> @@ -2115,10 +2401,14 @@ static void ibx_irq_postinstall(struct drm_device *dev)
> drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
> u32 mask;
>
> - if (HAS_PCH_IBX(dev))
> - mask = SDE_GMBUS | SDE_AUX_MASK;
> - else
> - mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
> + if (HAS_PCH_IBX(dev)) {
> + mask = SDE_GMBUS | SDE_AUX_MASK | SDE_TRANSB_FIFO_UNDER |
> + SDE_TRANSA_FIFO_UNDER;
> + } else {
> + mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT | SDE_ERROR_CPT;
> +
> + I915_WRITE(SERR_INT, I915_READ(SERR_INT));
> + }
>
> if (HAS_PCH_NOP(dev))
> return;
> @@ -2133,7 +2423,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
> /* enable kind of interrupts always enabled */
> u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
> DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
> - DE_AUX_CHANNEL_A;
> + DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN |
> + DE_PIPEA_FIFO_UNDERRUN;
> u32 render_irqs;
>
> dev_priv->irq_mask = ~display_mask;
> @@ -2183,12 +2474,14 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
> DE_PLANEC_FLIP_DONE_IVB |
> DE_PLANEB_FLIP_DONE_IVB |
> DE_PLANEA_FLIP_DONE_IVB |
> - DE_AUX_CHANNEL_A_IVB;
> + DE_AUX_CHANNEL_A_IVB |
> + DE_ERR_INT_IVB;
> u32 render_irqs;
>
> dev_priv->irq_mask = ~display_mask;
>
> /* should always can generate irq */
> + I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
> I915_WRITE(DEIIR, I915_READ(DEIIR));
> I915_WRITE(DEIMR, dev_priv->irq_mask);
> I915_WRITE(DEIER,
> @@ -2312,6 +2605,8 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
> I915_WRITE(DEIMR, 0xffffffff);
> I915_WRITE(DEIER, 0x0);
> I915_WRITE(DEIIR, I915_READ(DEIIR));
> + if (IS_GEN7(dev))
> + I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
>
> I915_WRITE(GTIMR, 0xffffffff);
> I915_WRITE(GTIER, 0x0);
> @@ -2323,6 +2618,8 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
> I915_WRITE(SDEIMR, 0xffffffff);
> I915_WRITE(SDEIER, 0x0);
> I915_WRITE(SDEIIR, I915_READ(SDEIIR));
> + if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev))
> + I915_WRITE(SERR_INT, I915_READ(SERR_INT));
> }
>
> static void i8xx_irq_preinstall(struct drm_device * dev)
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 76d9df1..932b4a0 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -529,7 +529,10 @@
>
> #define ERROR_GEN6 0x040a0
> #define GEN7_ERR_INT 0x44040
> -#define ERR_INT_MMIO_UNCLAIMED (1<<13)
> +#define ERR_INT_MMIO_UNCLAIMED (1<<13)
> +#define ERR_INT_FIFO_UNDERRUN_C (1<<6)
> +#define ERR_INT_FIFO_UNDERRUN_B (1<<3)
> +#define ERR_INT_FIFO_UNDERRUN_A (1<<0)
>
> #define FPGA_DBG 0x42300
> #define FPGA_DBG_RM_NOCLAIM (1<<31)
> @@ -3505,7 +3508,7 @@
> #define DE_PIPEA_FIFO_UNDERRUN (1 << 0)
>
> /* More Ivybridge lolz */
> -#define DE_ERR_DEBUG_IVB (1<<30)
> +#define DE_ERR_INT_IVB (1<<30)
> #define DE_GSE_IVB (1<<29)
> #define DE_PCH_EVENT_IVB (1<<28)
> #define DE_DP_A_HOTPLUG_IVB (1<<27)
> @@ -3664,6 +3667,7 @@
> SDE_PORTC_HOTPLUG_CPT | \
> SDE_PORTB_HOTPLUG_CPT)
> #define SDE_GMBUS_CPT (1 << 17)
> +#define SDE_ERROR_CPT (1 << 16)
> #define SDE_AUDIO_CP_REQ_C_CPT (1 << 10)
> #define SDE_AUDIO_CP_CHG_C_CPT (1 << 9)
> #define SDE_FDI_RXC_CPT (1 << 8)
> @@ -3688,6 +3692,11 @@
> #define SDEIIR 0xc4008
> #define SDEIER 0xc400c
>
> +#define SERR_INT 0xc4040
> +#define SERR_INT_TRANS_C_FIFO_UNDERRUN (1<<6)
> +#define SERR_INT_TRANS_B_FIFO_UNDERRUN (1<<3)
> +#define SERR_INT_TRANS_A_FIFO_UNDERRUN (1<<0)
> +
> /* digital port hotplug */
> #define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */
> #define PORTD_HOTPLUG_ENABLE (1 << 20)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 457a0a0..574d68d 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3339,6 +3339,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
> return;
>
> intel_crtc->active = true;
> +
> + intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
> + intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
> +
> intel_update_watermarks(dev);
>
> if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
> @@ -3430,6 +3434,11 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
> return;
>
> intel_crtc->active = true;
> +
> + intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
> + if (intel_crtc->config.has_pch_encoder)
> + intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
> +
> intel_update_watermarks(dev);
>
> if (intel_crtc->config.has_pch_encoder)
> @@ -3516,6 +3525,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
> if (dev_priv->cfb_plane == plane)
> intel_disable_fbc(dev);
>
> + intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
> intel_disable_pipe(dev_priv, pipe);
>
> /* Disable PF */
> @@ -3529,6 +3539,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
> ironlake_fdi_disable(crtc);
>
> ironlake_disable_pch_transcoder(dev_priv, pipe);
> + intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
>
> if (HAS_PCH_CPT(dev)) {
> /* disable TRANS_DP_CTL */
> @@ -3595,6 +3606,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
> if (dev_priv->cfb_plane == plane)
> intel_disable_fbc(dev);
>
> + if (intel_crtc->config.has_pch_encoder)
> + intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false);
> intel_disable_pipe(dev_priv, pipe);
>
> intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
> @@ -3611,6 +3624,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>
> if (intel_crtc->config.has_pch_encoder) {
> lpt_disable_pch_transcoder(dev_priv);
> + intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
> intel_ddi_fdi_disable(crtc);
> }
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d7bd031..fe3566c 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -258,6 +258,10 @@ struct intel_crtc {
>
> /* reset counter value when the last flip was submitted */
> unsigned int reset_counter;
> +
> + /* Access to these should be protected by dev_priv->irq_lock. */
> + bool cpu_fifo_underrun_disabled;
> + bool pch_fifo_underrun_disabled;
> };
>
> struct intel_plane {
> @@ -467,6 +471,7 @@ int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
> extern void intel_attach_force_audio_property(struct drm_connector *connector);
> extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
>
> +extern bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
> extern void intel_crt_init(struct drm_device *dev);
> extern void intel_hdmi_init(struct drm_device *dev,
> int hdmi_reg, enum port port);
> @@ -719,5 +724,11 @@ intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
> extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
>
> extern void intel_display_handle_reset(struct drm_device *dev);
> +extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
> + enum pipe pipe,
> + bool enable);
> +extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
> + enum transcoder pch_transcoder,
> + bool enable);
>
> #endif /* __INTEL_DRV_H__ */
More information about the Intel-gfx
mailing list