[Intel-gfx] [PATCH 18/20] drm/i915: Enable hpd logic only for ports that are present
Ville Syrjala
ville.syrjala at linux.intel.com
Tue Oct 6 14:33:47 UTC 2020
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
Let's enable the hardware hpd logic only for the ports we
can actually use.
In theory this may save some miniscule amounts of power,
and more importantly it eliminates a lot if platform specific
codepaths since the generic thing can now deal with any
combination of ports being present on each SKU.
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
drivers/gpu/drm/i915/i915_irq.c | 301 ++++++++++++++++++++++----------
drivers/gpu/drm/i915/i915_reg.h | 13 --
2 files changed, 205 insertions(+), 109 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index dd6a8d2690f6..222d2e6d7ee4 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -61,6 +61,8 @@
*/
typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val);
+typedef u32 (*hotplug_enables_func)(struct drm_i915_private *i915,
+ enum hpd_pin pin);
static const u32 hpd_ilk[HPD_NUM_PINS] = {
[HPD_PORT_A] = DE_DP_A_HOTPLUG,
@@ -1221,6 +1223,18 @@ static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv,
return hotplug_irqs;
}
+static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915,
+ hotplug_enables_func hotplug_enables)
+{
+ struct intel_encoder *encoder;
+ u32 hotplug = 0;
+
+ for_each_intel_encoder(&i915->drm, encoder)
+ hotplug |= hotplug_enables(i915, encoder->hpd_pin);
+
+ return hotplug;
+}
+
static void gmbus_irq_handler(struct drm_i915_private *dev_priv)
{
wake_up_all(&dev_priv->gmbus_wait_queue);
@@ -3141,6 +3155,31 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
spin_unlock_irq(&dev_priv->irq_lock);
}
+static u32 ibx_hotplug_enables(struct drm_i915_private *i915,
+ enum hpd_pin pin)
+{
+ switch (pin) {
+ case HPD_PORT_A:
+ /*
+ * When CPU and PCH are on the same package, port A
+ * HPD must be enabled in both north and south.
+ */
+ return HAS_PCH_LPT_LP(i915) ?
+ PORTA_HOTPLUG_ENABLE : 0;
+ case HPD_PORT_B:
+ return PORTB_HOTPLUG_ENABLE |
+ PORTB_PULSE_DURATION_2ms;
+ case HPD_PORT_C:
+ return PORTC_HOTPLUG_ENABLE |
+ PORTC_PULSE_DURATION_2ms;
+ case HPD_PORT_D:
+ return PORTD_HOTPLUG_ENABLE |
+ PORTD_PULSE_DURATION_2ms;
+ default:
+ return 0;
+ }
+}
+
static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug;
@@ -3151,18 +3190,14 @@ static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
* The pulse duration bits are reserved on LPT+.
*/
hotplug = I915_READ(PCH_PORT_HOTPLUG);
- hotplug &= ~(PORTB_PULSE_DURATION_MASK |
+ hotplug &= ~(PORTA_HOTPLUG_ENABLE |
+ PORTB_HOTPLUG_ENABLE |
+ PORTC_HOTPLUG_ENABLE |
+ PORTD_HOTPLUG_ENABLE |
+ PORTB_PULSE_DURATION_MASK |
PORTC_PULSE_DURATION_MASK |
PORTD_PULSE_DURATION_MASK);
- hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
- hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
- hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
- /*
- * When CPU and PCH are on the same package, port A
- * HPD must be enabled in both north and south.
- */
- if (HAS_PCH_LPT_LP(dev_priv))
- hotplug |= PORTA_HOTPLUG_ENABLE;
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables);
I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
}
@@ -3178,28 +3213,63 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
ibx_hpd_detection_setup(dev_priv);
}
-static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv,
- u32 enable_mask)
+static u32 icp_ddi_hotplug_enables(struct drm_i915_private *i915,
+ enum hpd_pin pin)
+{
+ switch (pin) {
+ case HPD_PORT_A:
+ case HPD_PORT_B:
+ case HPD_PORT_C:
+ return SHOTPLUG_CTL_DDI_HPD_ENABLE(pin);
+ default:
+ return 0;
+ }
+}
+
+static u32 icp_tc_hotplug_enables(struct drm_i915_private *i915,
+ enum hpd_pin pin)
+{
+ switch (pin) {
+ case HPD_PORT_TC1:
+ case HPD_PORT_TC2:
+ case HPD_PORT_TC3:
+ case HPD_PORT_TC4:
+ case HPD_PORT_TC5:
+ case HPD_PORT_TC6:
+ return ICP_TC_HPD_ENABLE(pin);
+ default:
+ return 0;
+ }
+}
+
+static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug;
hotplug = I915_READ(SHOTPLUG_CTL_DDI);
- hotplug |= enable_mask;
+ hotplug &= ~(SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) |
+ SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) |
+ SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C));
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables);
I915_WRITE(SHOTPLUG_CTL_DDI, hotplug);
}
-static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv,
- u32 enable_mask)
+static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug;
hotplug = I915_READ(SHOTPLUG_CTL_TC);
- hotplug |= enable_mask;
+ hotplug &= ~(ICP_TC_HPD_ENABLE(HPD_PORT_TC1) |
+ ICP_TC_HPD_ENABLE(HPD_PORT_TC2) |
+ ICP_TC_HPD_ENABLE(HPD_PORT_TC3) |
+ ICP_TC_HPD_ENABLE(HPD_PORT_TC4) |
+ ICP_TC_HPD_ENABLE(HPD_PORT_TC5) |
+ ICP_TC_HPD_ENABLE(HPD_PORT_TC6));
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables);
I915_WRITE(SHOTPLUG_CTL_TC, hotplug);
}
-static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv,
- u32 ddi_enable_mask, u32 tc_enable_mask)
+static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug_irqs, enabled_irqs;
@@ -3211,30 +3281,24 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv,
ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
- icp_ddi_hpd_detection_setup(dev_priv, ddi_enable_mask);
- if (tc_enable_mask)
- icp_tc_hpd_detection_setup(dev_priv, tc_enable_mask);
+ icp_ddi_hpd_detection_setup(dev_priv);
+ icp_tc_hpd_detection_setup(dev_priv);
}
-/*
- * EHL doesn't need most of gen11_hpd_irq_setup, it's handling only the
- * equivalent of SDE.
- */
-static void mcc_hpd_irq_setup(struct drm_i915_private *dev_priv)
+static u32 gen11_hotplug_enables(struct drm_i915_private *i915,
+ enum hpd_pin pin)
{
- icp_hpd_irq_setup(dev_priv,
- ICP_DDI_HPD_ENABLE_MASK, ICP_TC_HPD_ENABLE(HPD_PORT_TC1));
-}
-
-/*
- * JSP behaves exactly the same as MCC above except that port C is mapped to
- * the DDI-C pins instead of the TC1 pins. This means we should follow TGP's
- * masks & tables rather than ICP's masks & tables.
- */
-static void jsp_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- icp_hpd_irq_setup(dev_priv,
- TGP_DDI_HPD_ENABLE_MASK, 0);
+ switch (pin) {
+ case HPD_PORT_TC1:
+ case HPD_PORT_TC2:
+ case HPD_PORT_TC3:
+ case HPD_PORT_TC4:
+ case HPD_PORT_TC5:
+ case HPD_PORT_TC6:
+ return GEN11_HOTPLUG_CTL_ENABLE(pin);
+ default:
+ return 0;
+ }
}
static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
@@ -3242,12 +3306,13 @@ static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
u32 hotplug;
hotplug = I915_READ(GEN11_TC_HOTPLUG_CTL);
- hotplug |= GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6);
+ hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6));
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables);
I915_WRITE(GEN11_TC_HOTPLUG_CTL, hotplug);
}
@@ -3256,12 +3321,13 @@ static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
u32 hotplug;
hotplug = I915_READ(GEN11_TBT_HOTPLUG_CTL);
- hotplug |= GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6);
+ hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) |
+ GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6));
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables);
I915_WRITE(GEN11_TBT_HOTPLUG_CTL, hotplug);
}
@@ -3282,12 +3348,36 @@ static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
gen11_tc_hpd_detection_setup(dev_priv);
gen11_tbt_hpd_detection_setup(dev_priv);
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP)
- icp_hpd_irq_setup(dev_priv,
- TGP_DDI_HPD_ENABLE_MASK, TGP_TC_HPD_ENABLE_MASK);
- else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
- icp_hpd_irq_setup(dev_priv,
- ICP_DDI_HPD_ENABLE_MASK, ICP_TC_HPD_ENABLE_MASK);
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
+ icp_hpd_irq_setup(dev_priv);
+}
+
+static u32 spt_hotplug_enables(struct drm_i915_private *i915,
+ enum hpd_pin pin)
+{
+ switch (pin) {
+ case HPD_PORT_A:
+ return PORTA_HOTPLUG_ENABLE;
+ case HPD_PORT_B:
+ return PORTB_HOTPLUG_ENABLE;
+ case HPD_PORT_C:
+ return PORTC_HOTPLUG_ENABLE;
+ case HPD_PORT_D:
+ return PORTD_HOTPLUG_ENABLE;
+ default:
+ return 0;
+ }
+}
+
+static u32 spt_hotplug2_enables(struct drm_i915_private *i915,
+ enum hpd_pin pin)
+{
+ switch (pin) {
+ case HPD_PORT_E:
+ return PORTE_HOTPLUG_ENABLE;
+ default:
+ return 0;
+ }
}
static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
@@ -3304,14 +3394,16 @@ static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
/* Enable digital hotplug on the PCH */
hotplug = I915_READ(PCH_PORT_HOTPLUG);
- hotplug |= PORTA_HOTPLUG_ENABLE |
- PORTB_HOTPLUG_ENABLE |
- PORTC_HOTPLUG_ENABLE |
- PORTD_HOTPLUG_ENABLE;
+ hotplug &= ~(PORTA_HOTPLUG_ENABLE |
+ PORTB_HOTPLUG_ENABLE |
+ PORTC_HOTPLUG_ENABLE |
+ PORTD_HOTPLUG_ENABLE);
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables);
I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
hotplug = I915_READ(PCH_PORT_HOTPLUG2);
- hotplug |= PORTE_HOTPLUG_ENABLE;
+ hotplug &= ~PORTE_HOTPLUG_ENABLE;
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables);
I915_WRITE(PCH_PORT_HOTPLUG2, hotplug);
}
@@ -3330,6 +3422,18 @@ static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
spt_hpd_detection_setup(dev_priv);
}
+static u32 ilk_hotplug_enables(struct drm_i915_private *i915,
+ enum hpd_pin pin)
+{
+ switch (pin) {
+ case HPD_PORT_A:
+ return DIGITAL_PORTA_HOTPLUG_ENABLE |
+ DIGITAL_PORTA_PULSE_DURATION_2ms;
+ default:
+ return 0;
+ }
+}
+
static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug;
@@ -3340,9 +3444,9 @@ static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
* The pulse duration bits are reserved on HSW+.
*/
hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL);
- hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK;
- hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE |
- DIGITAL_PORTA_PULSE_DURATION_2ms;
+ hotplug &= ~(DIGITAL_PORTA_HOTPLUG_ENABLE |
+ DIGITAL_PORTA_PULSE_DURATION_MASK);
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables);
I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug);
}
@@ -3363,35 +3467,44 @@ static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
ibx_hpd_irq_setup(dev_priv);
}
-static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv,
- u32 enabled_irqs)
+static u32 bxt_hotplug_enables(struct drm_i915_private *i915,
+ enum hpd_pin pin)
+{
+ u32 hotplug;
+
+ switch (pin) {
+ case HPD_PORT_A:
+ hotplug = PORTA_HOTPLUG_ENABLE;
+ if (intel_bios_is_port_hpd_inverted(i915, PORT_A))
+ hotplug |= BXT_DDIA_HPD_INVERT;
+ return hotplug;
+ case HPD_PORT_B:
+ hotplug = PORTB_HOTPLUG_ENABLE;
+ if (intel_bios_is_port_hpd_inverted(i915, PORT_B))
+ hotplug |= BXT_DDIB_HPD_INVERT;
+ return hotplug;
+ case HPD_PORT_C:
+ hotplug = PORTC_HOTPLUG_ENABLE;
+ if (intel_bios_is_port_hpd_inverted(i915, PORT_C))
+ hotplug |= BXT_DDIC_HPD_INVERT;
+ return hotplug;
+ default:
+ return 0;
+ }
+}
+
+static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
u32 hotplug;
hotplug = I915_READ(PCH_PORT_HOTPLUG);
- hotplug |= PORTA_HOTPLUG_ENABLE |
- PORTB_HOTPLUG_ENABLE |
- PORTC_HOTPLUG_ENABLE;
-
- drm_dbg_kms(&dev_priv->drm,
- "Invert bit setting: hp_ctl:%x hp_port:%x\n",
- hotplug, enabled_irqs);
- hotplug &= ~BXT_DDI_HPD_INVERT_MASK;
-
- /*
- * For BXT invert bit has to be set based on AOB design
- * for HPD detection logic, update it based on VBT fields.
- */
- if ((enabled_irqs & GEN8_DE_PORT_HOTPLUG(HPD_PORT_A)) &&
- intel_bios_is_port_hpd_inverted(dev_priv, PORT_A))
- hotplug |= BXT_DDIA_HPD_INVERT;
- if ((enabled_irqs & GEN8_DE_PORT_HOTPLUG(HPD_PORT_B)) &&
- intel_bios_is_port_hpd_inverted(dev_priv, PORT_B))
- hotplug |= BXT_DDIB_HPD_INVERT;
- if ((enabled_irqs & GEN8_DE_PORT_HOTPLUG(HPD_PORT_C)) &&
- intel_bios_is_port_hpd_inverted(dev_priv, PORT_C))
- hotplug |= BXT_DDIC_HPD_INVERT;
-
+ hotplug &= ~(PORTA_HOTPLUG_ENABLE |
+ PORTB_HOTPLUG_ENABLE |
+ PORTC_HOTPLUG_ENABLE |
+ BXT_DDIA_HPD_INVERT |
+ BXT_DDIB_HPD_INVERT |
+ BXT_DDIC_HPD_INVERT);
+ hotplug |= intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables);
I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
}
@@ -3404,7 +3517,7 @@ static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
- bxt_hpd_detection_setup(dev_priv, enabled_irqs);
+ bxt_hpd_detection_setup(dev_priv);
}
static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
@@ -4122,11 +4235,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
if (I915_HAS_HOTPLUG(dev_priv))
dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
} else {
- if (HAS_PCH_JSP(dev_priv))
- dev_priv->display.hpd_irq_setup = jsp_hpd_irq_setup;
- else if (HAS_PCH_MCC(dev_priv))
- dev_priv->display.hpd_irq_setup = mcc_hpd_irq_setup;
- else if (INTEL_GEN(dev_priv) >= 11)
+ if (INTEL_GEN(dev_priv) >= 11)
dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup;
else if (IS_GEN9_LP(dev_priv))
dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index d2175faf7d34..75c45fda0f85 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8410,19 +8410,6 @@ enum {
#define SHPD_FILTER_CNT _MMIO(0xc4038)
#define SHPD_FILTER_CNT_500_ADJ 0x001D9
-#define ICP_DDI_HPD_ENABLE_MASK (SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | \
- SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A))
-#define ICP_TC_HPD_ENABLE_MASK (ICP_TC_HPD_ENABLE(HPD_PORT_TC4) | \
- ICP_TC_HPD_ENABLE(HPD_PORT_TC3) | \
- ICP_TC_HPD_ENABLE(HPD_PORT_TC2) | \
- ICP_TC_HPD_ENABLE(HPD_PORT_TC1))
-#define TGP_DDI_HPD_ENABLE_MASK (SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) | \
- SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | \
- SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A))
-#define TGP_TC_HPD_ENABLE_MASK (ICP_TC_HPD_ENABLE(HPD_PORT_TC6) | \
- ICP_TC_HPD_ENABLE(HPD_PORT_TC5) | \
- ICP_TC_HPD_ENABLE_MASK)
-
#define _PCH_DPLL_A 0xc6014
#define _PCH_DPLL_B 0xc6018
#define PCH_DPLL(pll) _MMIO((pll) == 0 ? _PCH_DPLL_A : _PCH_DPLL_B)
--
2.26.2
More information about the Intel-gfx
mailing list