[PATCH 26/71] drm/i915: Enable PM Interrupts for CHV/BDW Platform.

ville.syrjala
2014-04-09T10:30:39Z

From: Deepak S <deepak.s@intel.com>

v2: Remove vfuncs and add if else block to differentiate platform
(Daniel)

Signed-off-by: Deepak S <deepak.s@intel.com>
---
drivers/gpu/drm/i915/i915_irq.c | 49 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 1581b3d..6cf97c4 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -37,6 +37,9 @@
#include "i915_trace.h"
#include "intel_drv.h"

+
+static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
+
static const u32 hpd_ibx[] = {
[HPD_CRT] = SDE_CRT_HOTPLUG,
[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
@@ -154,6 +157,32 @@ void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
}

/**
+ * gen8_update_pm_irq - update GEN8_GT_IMR
+ * @dev_priv: driver private
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ * */
+
+static void gen8_update_pm_irq(struct drm_i915_private *dev_priv,
+ uint32_t interrupt_mask,
+ uint32_t enabled_irq_mask)
+{
+ uint32_t new_val;
+
+ assert_spin_locked(&dev_priv->irq_lock);
+
+ new_val = dev_priv->pm_irq_mask;
+ new_val &= ~interrupt_mask;
+ new_val |= (~enabled_irq_mask & interrupt_mask);
+
+ if (new_val != dev_priv->pm_irq_mask) {
+ dev_priv->pm_irq_mask = new_val;
+ I915_WRITE(GEN8_GT_IMR(2), dev_priv->pm_irq_mask);
+ POSTING_READ(GEN8_GT_IMR(2));
+ }
+}
+
+/**
* snb_update_pm_irq - update GEN6_PMIMR
* @dev_priv: driver private
* @interrupt_mask: mask of interrupt bits to update
@@ -188,12 +217,18 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,

void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
- snb_update_pm_irq(dev_priv, mask, mask);
+ if (IS_GEN8(dev_priv->dev))
+ gen8_update_pm_irq(dev_priv, mask, mask);
+ else
+ snb_update_pm_irq(dev_priv, mask, mask);
}

void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
- snb_update_pm_irq(dev_priv, mask, 0);
+ if (IS_GEN8(dev_priv->dev))
+ gen8_update_pm_irq(dev_priv, mask, 0);
+ else
+ snb_update_pm_irq(dev_priv, mask, 0);
}

static bool ivb_can_enable_err_int(struct drm_device *dev)
@@ -1341,6 +1376,9 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
u32 rcs, bcs, vcs;
uint32_t tmp = 0;
irqreturn_t ret = IRQ_NONE;
+ u32 pm_iir;
+
+ pm_iir = I915_READ(GEN8_GT_IIR(2));

if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
tmp = I915_READ(GEN8_GT_IIR(0));
@@ -1381,6 +1419,12 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
DRM_ERROR("The master control interrupt lied (GT3)!\n");
}

+
+ if (pm_iir)
+ gen6_rps_irq_handler(dev_priv, pm_iir);
+
+ I915_WRITE(GEN8_GT_IIR(2), pm_iir);
+
return ret;
}

@@ -1796,6 +1840,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
ret = IRQ_HANDLED;
}

+
I915_WRITE(VLV_IIR, iir);

I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
--
1.8.3.2