summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c199
1 files changed, 191 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 273ffce9807a..3505fafcfb7b 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2988,6 +2988,15 @@ static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
}
+static void ibx_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
+ ibx_hotplug_mask(encoder->hpd_pin),
+ ibx_hotplug_enables(encoder));
+}
+
static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug_irqs, enabled_irqs;
@@ -3048,6 +3057,15 @@ static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
}
+static void icp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_DDI,
+ icp_ddi_hotplug_mask(encoder->hpd_pin),
+ icp_ddi_hotplug_enables(encoder));
+}
+
static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
@@ -3060,6 +3078,21 @@ static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
}
+static void icp_tc_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_TC,
+ icp_tc_hotplug_mask(encoder->hpd_pin),
+ icp_tc_hotplug_enables(encoder));
+}
+
+static void icp_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ icp_ddi_hpd_enable_detection(encoder);
+ icp_tc_hpd_enable_detection(encoder);
+}
+
static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug_irqs, enabled_irqs;
@@ -3105,6 +3138,14 @@ static void dg1_hpd_invert(struct drm_i915_private *i915)
intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
}
+static void dg1_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ dg1_hpd_invert(i915);
+ icp_hpd_enable_detection(encoder);
+}
+
static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
dg1_hpd_invert(dev_priv);
@@ -3123,6 +3164,15 @@ static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
}
+static void gen11_tc_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, GEN11_TC_HOTPLUG_CTL,
+ gen11_hotplug_mask(encoder->hpd_pin),
+ gen11_hotplug_enables(encoder));
+}
+
static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
@@ -3135,6 +3185,26 @@ static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
}
+static void gen11_tbt_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, GEN11_TBT_HOTPLUG_CTL,
+ gen11_hotplug_mask(encoder->hpd_pin),
+ gen11_hotplug_enables(encoder));
+}
+
+static void gen11_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ gen11_tc_hpd_enable_detection(encoder);
+ gen11_tbt_hpd_enable_detection(encoder);
+
+ if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
+ icp_hpd_enable_detection(encoder);
+}
+
static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug_irqs, enabled_irqs;
@@ -3195,6 +3265,15 @@ static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915)
intel_hpd_hotplug_enables(i915, mtp_ddi_hotplug_enables));
}
+static void mtp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
+ mtp_ddi_hotplug_mask(encoder->hpd_pin),
+ mtp_ddi_hotplug_enables(encoder));
+}
+
static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
{
intel_de_rmw(i915, SHOTPLUG_CTL_TC,
@@ -3205,6 +3284,15 @@ static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
intel_hpd_hotplug_enables(i915, mtp_tc_hotplug_enables));
}
+static void mtp_tc_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
+ mtp_tc_hotplug_mask(encoder->hpd_pin),
+ mtp_tc_hotplug_enables(encoder));
+}
+
static void mtp_hpd_invert(struct drm_i915_private *i915)
{
u32 val = (INVERT_DDIA_HPD |
@@ -3219,6 +3307,15 @@ static void mtp_hpd_invert(struct drm_i915_private *i915)
intel_de_rmw(i915, SOUTH_CHICKEN1, 0, val);
}
+static void mtp_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ mtp_hpd_invert(i915);
+ mtp_ddi_hpd_enable_detection(encoder);
+ mtp_tc_hpd_enable_detection(encoder);
+}
+
static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
{
u32 hotplug_irqs, enabled_irqs;
@@ -3235,25 +3332,50 @@ static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
mtp_tc_hpd_detection_setup(i915);
}
+static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin)
+{
+ return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4;
+}
+
+static void _xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915,
+ enum hpd_pin hpd_pin, bool enable)
+{
+ u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
+ XELPDP_DP_ALT_HOTPLUG_ENABLE;
+
+ if (!is_xelpdp_pica_hpd_pin(hpd_pin))
+ return;
+
+ intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(hpd_pin),
+ mask, enable ? mask : 0);
+}
+
+static void xelpdp_pica_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ _xelpdp_pica_hpd_detection_setup(i915, encoder->hpd_pin, true);
+}
+
static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915)
{
struct intel_encoder *encoder;
- enum hpd_pin pin;
u32 available_pins = 0;
+ enum hpd_pin pin;
BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS);
for_each_intel_encoder(&i915->drm, encoder)
available_pins |= BIT(encoder->hpd_pin);
- for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
- u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
- XELPDP_DP_ALT_HOTPLUG_ENABLE;
+ for_each_hpd_pin(pin)
+ _xelpdp_pica_hpd_detection_setup(i915, pin, available_pins & BIT(pin));
+}
- intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(pin),
- mask,
- available_pins & BIT(pin) ? mask : 0);
- }
+static void xelpdp_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ xelpdp_pica_hpd_enable_detection(encoder);
+ mtp_hpd_enable_detection(encoder);
}
static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
@@ -3330,6 +3452,26 @@ static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
}
+static void spt_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ /* Display WA #1179 WaHardHangonHotPlug: cnp */
+ if (HAS_PCH_CNP(i915)) {
+ intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1,
+ CHASSIS_CLK_REQ_DURATION_MASK,
+ CHASSIS_CLK_REQ_DURATION(0xf));
+ }
+
+ intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
+ spt_hotplug_mask(encoder->hpd_pin),
+ spt_hotplug_enables(encoder));
+
+ intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG2,
+ spt_hotplug2_mask(encoder->hpd_pin),
+ spt_hotplug2_enables(encoder));
+}
+
static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug_irqs, enabled_irqs;
@@ -3379,6 +3521,17 @@ static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
}
+static void ilk_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
+ ilk_hotplug_mask(encoder->hpd_pin),
+ ilk_hotplug_enables(encoder));
+
+ ibx_hpd_enable_detection(encoder);
+}
+
static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug_irqs, enabled_irqs;
@@ -3444,6 +3597,15 @@ static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
}
+static void bxt_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
+ bxt_hotplug_mask(encoder->hpd_pin),
+ bxt_hotplug_enables(encoder));
+}
+
static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug_irqs, enabled_irqs;
@@ -4121,6 +4283,15 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
i915_enable_asle_pipestat(dev_priv);
}
+static void i915_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ u32 hotplug_en = hpd_mask_i915[encoder->hpd_pin];
+
+ /* HPD sense and interrupt enable are one and the same */
+ i915_hotplug_interrupt_update(i915, hotplug_en, hotplug_en);
+}
+
static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug_en;
@@ -4206,12 +4377,16 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
}
struct intel_hotplug_funcs {
+ /* Enable HPD sense and interrupts for all present encoders */
void (*hpd_irq_setup)(struct drm_i915_private *i915);
+ /* Enable HPD sense for a single encoder */
+ void (*hpd_enable_detection)(struct intel_encoder *encoder);
};
#define HPD_FUNCS(platform) \
static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
.hpd_irq_setup = platform##_hpd_irq_setup, \
+ .hpd_enable_detection = platform##_hpd_enable_detection, \
}
HPD_FUNCS(i915);
@@ -4224,6 +4399,14 @@ HPD_FUNCS(spt);
HPD_FUNCS(ilk);
#undef HPD_FUNCS
+void intel_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ if (i915->display.funcs.hotplug)
+ i915->display.funcs.hotplug->hpd_enable_detection(encoder);
+}
+
void intel_hpd_irq_setup(struct drm_i915_private *i915)
{
if (i915->display_irqs_enabled && i915->display.funcs.hotplug)