summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorDhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>2018-06-16 03:05:29 +0300
committerPaulo Zanoni <paulo.r.zanoni@intel.com>2018-06-19 02:04:45 +0300
commit121e758ee5782b31fa5ecf23a3828f86167d36cc (patch)
tree02c4e162b9e09a4e91db93c1ec78cd2a174564ea /drivers/gpu/drm/i915/i915_irq.c
parentdf0d28c185ad29d539826a8eb8b651ea9c46051d (diff)
downloadlinux-121e758ee5782b31fa5ecf23a3828f86167d36cc.tar.xz
drm/i915/icl: Support for TC North Display interrupts
The hotplug interrupts for the ports can be routed to either North Display or South Display depending on the output mode. DP Alternate or DP over TBT outputs will have hotplug interrupts routed to the North Display while interrupts for legacy modes will be routed to the South Display in PCH. This patch adds hotplug interrupt handling support for DP Alternate mode. Cc: Jani Nikula <jani.nikula@intel.com> Cc: Anusha Srivatsa <anusha.srivatsa@intel.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com> [Paulo: coding style changes] Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180616000530.5357-2-paulo.r.zanoni@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c95
1 files changed, 92 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 64d5e10a4de8..40e563eb3a1f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -115,6 +115,13 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = {
[HPD_PORT_C] = BXT_DE_PORT_HP_DDIC
};
+static const u32 hpd_tc_gen11[HPD_NUM_PINS] = {
+ [HPD_PORT_C] = GEN11_TC1_HOTPLUG,
+ [HPD_PORT_D] = GEN11_TC2_HOTPLUG,
+ [HPD_PORT_E] = GEN11_TC3_HOTPLUG,
+ [HPD_PORT_F] = GEN11_TC4_HOTPLUG
+};
+
/* IIR can theoretically queue up two events. Be paranoid. */
#define GEN8_IRQ_RESET_NDX(type, which) do { \
I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
@@ -1549,6 +1556,22 @@ static void gen8_gt_irq_handler(struct drm_i915_private *i915,
}
}
+static bool gen11_port_hotplug_long_detect(enum port port, u32 val)
+{
+ switch (port) {
+ case PORT_C:
+ return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC1);
+ case PORT_D:
+ return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC2);
+ case PORT_E:
+ return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC3);
+ case PORT_F:
+ return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC4);
+ default:
+ return false;
+ }
+}
+
static bool bxt_port_hotplug_long_detect(enum port port, u32 val)
{
switch (port) {
@@ -2598,6 +2621,25 @@ static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv,
intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
}
+static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
+{
+ u32 pin_mask = 0, long_mask = 0;
+ u32 trigger_tc, dig_hotplug_reg;
+
+ trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK;
+ if (trigger_tc) {
+ dig_hotplug_reg = I915_READ(GEN11_TC_HOTPLUG_CTL);
+ I915_WRITE(GEN11_TC_HOTPLUG_CTL, dig_hotplug_reg);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tc,
+ dig_hotplug_reg, hpd_tc_gen11,
+ gen11_port_hotplug_long_detect);
+ intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+ } else {
+ DRM_ERROR("Unexpected DE HPD interrupt 0x%08x\n", iir);
+ }
+}
+
static irqreturn_t
gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
{
@@ -2633,6 +2675,17 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
DRM_ERROR("The master control interrupt lied (DE MISC)!\n");
}
+ if (INTEL_GEN(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) {
+ iir = I915_READ(GEN11_DE_HPD_IIR);
+ if (iir) {
+ I915_WRITE(GEN11_DE_HPD_IIR, iir);
+ ret = IRQ_HANDLED;
+ gen11_hpd_irq_handler(dev_priv, iir);
+ } else {
+ DRM_ERROR("The master control interrupt lied, (DE HPD)!\n");
+ }
+ }
+
if (master_ctl & GEN8_DE_PORT_IRQ) {
iir = I915_READ(GEN8_DE_PORT_IIR);
if (iir) {
@@ -3513,6 +3566,7 @@ static void gen11_irq_reset(struct drm_device *dev)
GEN3_IRQ_RESET(GEN8_DE_PORT_);
GEN3_IRQ_RESET(GEN8_DE_MISC_);
+ GEN3_IRQ_RESET(GEN11_DE_HPD_);
GEN3_IRQ_RESET(GEN11_GU_MISC_);
GEN3_IRQ_RESET(GEN8_PCU_);
}
@@ -3631,6 +3685,34 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
ibx_hpd_detection_setup(dev_priv);
}
+static void gen11_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug;
+
+ hotplug = I915_READ(GEN11_TC_HOTPLUG_CTL);
+ hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) |
+ GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) |
+ GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) |
+ GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4);
+ I915_WRITE(GEN11_TC_HOTPLUG_CTL, hotplug);
+}
+
+static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_irqs, enabled_irqs;
+ u32 val;
+
+ enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_tc_gen11);
+ hotplug_irqs = GEN11_DE_TC_HOTPLUG_MASK;
+
+ val = I915_READ(GEN11_DE_HPD_IMR);
+ val &= ~hotplug_irqs;
+ I915_WRITE(GEN11_DE_HPD_IMR, val);
+ POSTING_READ(GEN11_DE_HPD_IMR);
+
+ gen11_hpd_detection_setup(dev_priv);
+}
+
static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
u32 val, hotplug;
@@ -4004,10 +4086,17 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
GEN3_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
GEN3_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
- if (IS_GEN9_LP(dev_priv))
+ if (INTEL_GEN(dev_priv) >= 11) {
+ u32 de_hpd_masked = 0;
+ u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK;
+
+ GEN3_IRQ_INIT(GEN11_DE_HPD_, ~de_hpd_masked, de_hpd_enables);
+ gen11_hpd_detection_setup(dev_priv);
+ } else if (IS_GEN9_LP(dev_priv)) {
bxt_hpd_detection_setup(dev_priv);
- else if (IS_BROADWELL(dev_priv))
+ } else if (IS_BROADWELL(dev_priv)) {
ilk_hpd_detection_setup(dev_priv);
+ }
}
static int gen8_irq_postinstall(struct drm_device *dev)
@@ -4529,7 +4618,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
dev->driver->irq_uninstall = gen11_irq_reset;
dev->driver->enable_vblank = gen8_enable_vblank;
dev->driver->disable_vblank = gen8_disable_vblank;
- dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup;
+ dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup;
} else if (INTEL_GEN(dev_priv) >= 8) {
dev->driver->irq_handler = gen8_irq_handler;
dev->driver->irq_preinstall = gen8_irq_reset;