diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 199 |
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) |