[PATCH] [VPG HSW-A] drm/i915: BUN vol4g[DevHSW] Vblank interrupt on disabled pipe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This change is to comply with the BUN - Vblank interrupt on disabled pipe.
BUN states - Do not unmask and enable a vertical blank interrupt on a pipe
that is not enabled. Do not leave this interrupt enabled and unmasked after
the associated pipe is disabled. If the vblank interrupt is unmasked and
enabled on a disabled pipe it will block package C3, wasting power.

Issue: HSD link - https://hsdhsw.intel.com/hsd/haswell_platform/default.aspx#sighting/default.aspx?sighting_id=4391617
Change Details:
drmP.h
Add two new functions to enable and disable the IER bit for Vblank interrupt.
i915_irq.c
Set these functions to interrupt_enable and interrupt_disable.
intel_display.c
Call interrupt_enable(), from intel_enable_pipe(), after pipe is enabled.
Call interrupt_disable(), from intel_disable_pipe(), after pipe is disabled.

Change-Id: I982654f6ca9a5d48b3d7bc569069a1b0b38f4280
Signed-off-by: Sandeep Ramankutty <sandeepx.ramakutty@xxxxxxxxx>
---
 drivers/gpu/drm/i915/i915_irq.c      |   51 ++++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_display.c |    6 +++-
 include/drm/drmP.h                   |   20 +++++++++++++
 3 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index bc14d30..89a5793 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -27,7 +27,6 @@
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/sysrq.h>
 #include <linux/slab.h>
 #include <drm/drmP.h>
@@ -2216,6 +2215,35 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
 	return 0;
 }
 
+/* Enable Vblank interrupt for the pipe. set IER bit. Bit - 0(A),5(B),10(c) */
+static void hsw_enable_interrupt(struct drm_device *dev, int pipe)
+{
+	u32 de_ier;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	/* Enable Vblank interrupt only if pipe is enabled */
+	if (IS_HASWELL(dev) && i915_pipe_enabled(dev, pipe)) {
+		de_ier = I915_READ(DEIER);
+		de_ier |= (DE_PIPEA_VBLANK_IVB << (5 * pipe));
+		I915_WRITE(DEIER, de_ier);
+		POSTING_READ(DEIMR);
+	} else
+		DRM_ERROR("Vblank Interrupt enable not allowed\n");
+}
+
+/* Disable Vblank interrupt for the pipe. set IER bit to 0. */
+static void hsw_disable_interrupt(struct drm_device *dev, int pipe)
+{
+	u32 de_ier;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	if (IS_HASWELL(dev)) {
+		de_ier = I915_READ(DEIER);
+		de_ier &= (~(DE_PIPEA_VBLANK_IVB << (5 * pipe)));
+		I915_WRITE(DEIER, de_ier);
+		POSTING_READ(DEIMR);
+	} else
+		DRM_ERROR("Vblank Interrupt disable failed\n");
+}
+
 static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -2768,11 +2796,17 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
 	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,
-		   display_mask |
-		   DE_PIPEC_VBLANK_IVB |
-		   DE_PIPEB_VBLANK_IVB |
-		   DE_PIPEA_VBLANK_IVB);
+
+	/* For Haswell, do not enable the Vblank interrupt by default.
+		Enable the interrupt when pipe is enabled */
+	if (IS_HASWELL(dev)) {
+		I915_WRITE(DEIER, display_mask);
+	} else
+		I915_WRITE(DEIER,
+			display_mask |
+			DE_PIPEC_VBLANK_IVB |
+			DE_PIPEB_VBLANK_IVB |
+			DE_PIPEA_VBLANK_IVB);
 	POSTING_READ(DEIER);
 
 	dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
@@ -3623,6 +3657,11 @@ void intel_irq_init(struct drm_device *dev)
 		dev->driver->irq_uninstall = ironlake_irq_uninstall;
 		dev->driver->enable_vblank = ivybridge_enable_vblank;
 		dev->driver->disable_vblank = ivybridge_disable_vblank;
+		/* handlers to enable and disable vblank interrupt */
+		if (IS_HASWELL(dev)) {
+			dev->driver->enable_interrupt = hsw_enable_interrupt;
+			dev->driver->disable_interrupt = hsw_disable_interrupt;
+		}
 		dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		dev->driver->irq_handler = ironlake_irq_handler;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 24fa298..3efc25a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1646,6 +1646,9 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 		return;
 
 	I915_WRITE(reg, val | PIPECONF_ENABLE);
+	/* Enable Vblank interrupt for the pipe */
+	dev_priv->dev->driver->enable_interrupt(dev_priv->dev, pipe);
+
 	intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
@@ -1684,7 +1687,8 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 	val = I915_READ(reg);
 	if ((val & PIPECONF_ENABLE) == 0)
 		return;
-
+	/* Disable Vblank interrupt for the pipe */
+	dev_priv->dev->driver->disable_interrupt(dev_priv->dev, pipe);
 	I915_WRITE(reg, val & ~PIPECONF_ENABLE);
 	intel_wait_for_pipe_off(dev_priv->dev, pipe);
 }
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 4ccc955..78ad5dc 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -805,6 +805,26 @@ struct drm_driver {
 	void (*disable_vblank) (struct drm_device *dev, int crtc);
 
 	/**
+	* enable_interrupt - enable Vblank interrupt
+	* @dev: DRM device
+	* @crtc: which pipe to enable
+	*
+	* Enable Vblank interrupt for @crtc.  If the device is connected
+	* i.e. the pipe is enabled, the Vblank interrupt is enabled.
+	*/
+	void (*enable_interrupt) (struct drm_device *dev, int crtc);
+
+	/**
+	* disable_interrupt - disable interrupt
+	* @dev: DRM device
+	* @crtc: which pipe to enable
+	*
+	* Disable vblank interrupts for @crtc.  If the device is disconnected
+	* or pipe is disabled the interrupt is disabled.
+	*/
+	void (*disable_interrupt) (struct drm_device *dev, int crtc);
+
+	/**
 	 * Called by \c drm_device_is_agp.  Typically used to determine if a
 	 * card is really attached to AGP or not.
 	 *
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux