drm/i915/icl: Add power well support
authorImre Deak <imre.deak@intel.com>
Tue, 26 Jun 2018 14:22:32 +0000 (17:22 +0300)
committerImre Deak <imre.deak@intel.com>
Wed, 27 Jun 2018 13:01:19 +0000 (16:01 +0300)
Add the definition for ICL power wells and their mapping to power
domains. On ICL there are 3 power well control registers, we'll select
the correct one based on higher bits of the power well ID. The offset
for the control and status flags within this register is based on the
lower bits of the ID as on older platforms.

As the DC state programming is also the same as on old platforms we can
reuse the corresponding helpers. For this we mark here the DC-off power
well as shared among multiple platforms.

Other than the above the delta between old platforms and ICL:
- Pipe C has its own power well, so we can save some additional power in the
  pipe A+B and (non-eDP) pipe A configurations.
- Power wells for port E/F DDI/AUX IO and Thunderbolt 1-4 AUX IO

v2:
- Rebase on drm-tip after prep patch for this was merged there as
  requested by Paulo.
- Actually add the new AUX and DDI power well control regs (Rakshmi)

v3:
- Fix power well register names in code comments
- Add TBT AUX->power well 3 dependency

v4:
- Rebase

v5:
- Detach AUX power wells from the INIT power domain. These power wells
  can only be enabled in a TC/TBT connected state and otherwise not
  needed during driver initialization.

v6:
- Use _MMIO_PORT(...) instead _MMIO(_PICK(...)) (Paulo)
  Fix checkpatch warnings.

Cc: Animesh Manna <animesh.manna@intel.com>
Cc: Rakshmi Bhatia <rakshmi.bhatia@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Animesh Manna <animesh.manna@intel.com> (v1)
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180626142232.22361-1-imre.deak@intel.com
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.h
drivers/gpu/drm/i915/intel_runtime_pm.c

index 43db91c19f52412e1b01dbaf1dbd72f33554450a..2c20dc0db6482175943ddeeb91794939f6fb177d 100644 (file)
@@ -1045,13 +1045,13 @@ enum i915_power_well_id {
 
        /*
         * HSW/BDW
-        *  - HSW_PWR_WELL_CTL_DRIVER(0) (status bit: id*2, req bit: id*2+1)
+        *  - _HSW_PWR_WELL_CTL1-4 (status bit: id*2, req bit: id*2+1)
         */
        HSW_DISP_PW_GLOBAL = 15,
 
        /*
         * GEN9+
-        *  - HSW_PWR_WELL_CTL_DRIVER(0) (status bit: id*2, req bit: id*2+1)
+        *  - _HSW_PWR_WELL_CTL1-4 (status bit: id*2, req bit: id*2+1)
         */
        SKL_DISP_PW_MISC_IO = 0,
        SKL_DISP_PW_DDI_A_E,
@@ -1075,17 +1075,54 @@ enum i915_power_well_id {
        SKL_DISP_PW_2,
 
        /* - custom power wells */
-       SKL_DISP_PW_DC_OFF,
        BXT_DPIO_CMN_A,
        BXT_DPIO_CMN_BC,
-       GLK_DPIO_CMN_C,                 /* 19 */
+       GLK_DPIO_CMN_C,                 /* 18 */
+
+       /*
+        * GEN11+
+        *  - _HSW_PWR_WELL_CTL1-4
+        *    (status bit: (id&15)*2, req bit:(id&15)*2+1)
+        */
+       ICL_DISP_PW_1 = 0,
+       ICL_DISP_PW_2,
+       ICL_DISP_PW_3,
+       ICL_DISP_PW_4,
+
+       /*
+        *  - _HSW_PWR_WELL_CTL_AUX1/2/4
+        *    (status bit: (id&15)*2, req bit:(id&15)*2+1)
+        */
+       ICL_DISP_PW_AUX_A = 16,
+       ICL_DISP_PW_AUX_B,
+       ICL_DISP_PW_AUX_C,
+       ICL_DISP_PW_AUX_D,
+       ICL_DISP_PW_AUX_E,
+       ICL_DISP_PW_AUX_F,
+
+       ICL_DISP_PW_AUX_TBT1 = 24,
+       ICL_DISP_PW_AUX_TBT2,
+       ICL_DISP_PW_AUX_TBT3,
+       ICL_DISP_PW_AUX_TBT4,
+
+       /*
+        *  - _HSW_PWR_WELL_CTL_DDI1/2/4
+        *    (status bit: (id&15)*2, req bit:(id&15)*2+1)
+        */
+       ICL_DISP_PW_DDI_A = 32,
+       ICL_DISP_PW_DDI_B,
+       ICL_DISP_PW_DDI_C,
+       ICL_DISP_PW_DDI_D,
+       ICL_DISP_PW_DDI_E,
+       ICL_DISP_PW_DDI_F,                      /* 37 */
 
        /*
         * Multiple platforms.
         * Must start following the highest ID of any platform.
         * - custom power wells
         */
-       I915_DISP_PW_ALWAYS_ON = 20,
+       SKL_DISP_PW_DC_OFF = 38,
+       I915_DISP_PW_ALWAYS_ON,
 };
 
 #define PUNIT_REG_PWRGT_CTRL                   0x60
@@ -1679,6 +1716,13 @@ enum i915_power_well_id {
 #define   IREF1RC_OFFSET_MASK          (0xFF << IREF1RC_OFFSET_SHIFT)
 #define BXT_PORT_CL1CM_DW10(phy)       _BXT_PHY((phy), _PORT_CL1CM_DW10_BC)
 
+#define _ICL_PORT_CL_DW12_A            0x162030
+#define _ICL_PORT_CL_DW12_B            0x6C030
+#define   ICL_LANE_ENABLE_AUX          (1 << 0)
+#define ICL_PORT_CL_DW12(port)         _MMIO_PORT((port),              \
+                                                  _ICL_PORT_CL_DW12_A, \
+                                                  _ICL_PORT_CL_DW12_B)
+
 #define _PORT_CL1CM_DW28_A             0x162070
 #define _PORT_CL1CM_DW28_BC            0x6C070
 #define   OCL1_POWER_DOWN_EN           (1 << 23)
@@ -8564,6 +8608,14 @@ enum {
 #define _HSW_PWR_WELL_CTL3                     0x45408
 #define _HSW_PWR_WELL_CTL4                     0x4540C
 
+#define _ICL_PWR_WELL_CTL_AUX1                 0x45440
+#define _ICL_PWR_WELL_CTL_AUX2                 0x45444
+#define _ICL_PWR_WELL_CTL_AUX4                 0x4544C
+
+#define _ICL_PWR_WELL_CTL_DDI1                 0x45450
+#define _ICL_PWR_WELL_CTL_DDI2                 0x45454
+#define _ICL_PWR_WELL_CTL_DDI4                 0x4545C
+
 /*
  * Each power well control register contains up to 16 (request, status) HW
  * flag tuples. The register index and HW flag shift is determined by the
@@ -8573,14 +8625,20 @@ enum {
  */
 #define _HSW_PW_REG_IDX(pw)                    ((pw) >> 4)
 #define _HSW_PW_SHIFT(pw)                      (((pw) & 0xf) * 2)
-/* TODO: Add all PWR_WELL_CTL registers below for new platforms */
 #define HSW_PWR_WELL_CTL_BIOS(pw)      _MMIO(_PICK(_HSW_PW_REG_IDX(pw),       \
-                                                   _HSW_PWR_WELL_CTL1))
+                                                   _HSW_PWR_WELL_CTL1,        \
+                                                   _ICL_PWR_WELL_CTL_AUX1,    \
+                                                   _ICL_PWR_WELL_CTL_DDI1))
 #define HSW_PWR_WELL_CTL_DRIVER(pw)    _MMIO(_PICK(_HSW_PW_REG_IDX(pw),       \
-                                                   _HSW_PWR_WELL_CTL2))
+                                                   _HSW_PWR_WELL_CTL2,        \
+                                                   _ICL_PWR_WELL_CTL_AUX2,    \
+                                                   _ICL_PWR_WELL_CTL_DDI2))
+/* KVMR doesn't have a reg for AUX or DDI power well control */
 #define HSW_PWR_WELL_CTL_KVMR          _MMIO(_HSW_PWR_WELL_CTL3)
 #define HSW_PWR_WELL_CTL_DEBUG(pw)     _MMIO(_PICK(_HSW_PW_REG_IDX(pw),       \
-                                                   _HSW_PWR_WELL_CTL4))
+                                                   _HSW_PWR_WELL_CTL4,        \
+                                                   _ICL_PWR_WELL_CTL_AUX4,    \
+                                                   _ICL_PWR_WELL_CTL_DDI4))
 
 #define   HSW_PWR_WELL_CTL_REQ(pw)             (1 << (_HSW_PW_SHIFT(pw) + 1))
 #define   HSW_PWR_WELL_CTL_STATE(pw)           (1 << _HSW_PW_SHIFT(pw))
@@ -8601,6 +8659,8 @@ enum skl_power_gate {
 #define  SKL_FUSE_DOWNLOAD_STATUS              (1 << 31)
 /* PG0 (HW control->no power well ID), PG1..PG2 (SKL_DISP_PW1..SKL_DISP_PW2) */
 #define  SKL_PW_TO_PG(pw)                      ((pw) - SKL_DISP_PW_1 + SKL_PG1)
+/* PG0 (HW control->no power well ID), PG1..PG4 (ICL_DISP_PW1..ICL_DISP_PW4) */
+#define  ICL_PW_TO_PG(pw)                      ((pw) - ICL_DISP_PW_1 + SKL_PG1)
 #define  SKL_FUSE_PG_DIST_STATUS(pg)           (1 << (27 - (pg)))
 
 #define _CNL_AUX_REG_IDX(pw)           ((pw) - 9)
index dfb02da73ac86199810ada1cc1f8e043a2ff2123..a77dd29db2ecbbf7c0fe68087a8f5c9ac41e081c 100644 (file)
@@ -199,6 +199,10 @@ enum intel_display_power_domain {
        POWER_DOMAIN_AUX_E,
        POWER_DOMAIN_AUX_F,
        POWER_DOMAIN_AUX_IO_A,
+       POWER_DOMAIN_AUX_TBT1,
+       POWER_DOMAIN_AUX_TBT2,
+       POWER_DOMAIN_AUX_TBT3,
+       POWER_DOMAIN_AUX_TBT4,
        POWER_DOMAIN_GMBUS,
        POWER_DOMAIN_MODESET,
        POWER_DOMAIN_GT_IRQ,
index 2969787201ef8f5fcb0dabf8935ef854bf43d911..d81b2cfe1c5ed5f2ef2805da71a98f1612c43c1f 100644 (file)
@@ -134,6 +134,14 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
                return "AUX_F";
        case POWER_DOMAIN_AUX_IO_A:
                return "AUX_IO_A";
+       case POWER_DOMAIN_AUX_TBT1:
+               return "AUX_TBT1";
+       case POWER_DOMAIN_AUX_TBT2:
+               return "AUX_TBT2";
+       case POWER_DOMAIN_AUX_TBT3:
+               return "AUX_TBT3";
+       case POWER_DOMAIN_AUX_TBT4:
+               return "AUX_TBT4";
        case POWER_DOMAIN_GMBUS:
                return "GMBUS";
        case POWER_DOMAIN_INIT:
@@ -384,7 +392,8 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
        u32 val;
 
        if (wait_fuses) {
-               pg = SKL_PW_TO_PG(id);
+               pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_TO_PG(id) :
+                                                SKL_PW_TO_PG(id);
                /*
                 * For PW1 we have to wait both for the PW0/PG0 fuse state
                 * before enabling the power well and PW1/PG1's own fuse
@@ -430,6 +439,43 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
        hsw_wait_for_power_well_disable(dev_priv, power_well);
 }
 
+#define ICL_AUX_PW_TO_PORT(pw) ((pw) - ICL_DISP_PW_AUX_A)
+
+static void
+icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
+                                   struct i915_power_well *power_well)
+{
+       enum i915_power_well_id id = power_well->id;
+       enum port port = ICL_AUX_PW_TO_PORT(id);
+       u32 val;
+
+       val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
+       I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), val | HSW_PWR_WELL_CTL_REQ(id));
+
+       val = I915_READ(ICL_PORT_CL_DW12(port));
+       I915_WRITE(ICL_PORT_CL_DW12(port), val | ICL_LANE_ENABLE_AUX);
+
+       hsw_wait_for_power_well_enable(dev_priv, power_well);
+}
+
+static void
+icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
+                                    struct i915_power_well *power_well)
+{
+       enum i915_power_well_id id = power_well->id;
+       enum port port = ICL_AUX_PW_TO_PORT(id);
+       u32 val;
+
+       val = I915_READ(ICL_PORT_CL_DW12(port));
+       I915_WRITE(ICL_PORT_CL_DW12(port), val & ~ICL_LANE_ENABLE_AUX);
+
+       val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
+       I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id),
+                  val & ~HSW_PWR_WELL_CTL_REQ(id));
+
+       hsw_wait_for_power_well_disable(dev_priv, power_well);
+}
+
 /*
  * We should only use the power well if we explicitly asked the hardware to
  * enable it, so check if it's enabled and also check if we've requested it to
@@ -1897,6 +1943,105 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
        BIT_ULL(POWER_DOMAIN_AUX_A) |                   \
        BIT_ULL(POWER_DOMAIN_INIT))
 
+/*
+ * ICL PW_0/PG_0 domains (HW/DMC control):
+ * - PCI
+ * - clocks except port PLL
+ * - central power except FBC
+ * - shared functions except pipe interrupts, pipe MBUS, DBUF registers
+ * ICL PW_1/PG_1 domains (HW/DMC control):
+ * - DBUF function
+ * - PIPE_A and its planes, except VGA
+ * - transcoder EDP + PSR
+ * - transcoder DSI
+ * - DDI_A
+ * - FBC
+ */
+#define ICL_PW_4_POWER_DOMAINS (                       \
+       BIT_ULL(POWER_DOMAIN_PIPE_C) |                  \
+       BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |     \
+       BIT_ULL(POWER_DOMAIN_INIT))
+       /* VDSC/joining */
+#define ICL_PW_3_POWER_DOMAINS (                       \
+       ICL_PW_4_POWER_DOMAINS |                        \
+       BIT_ULL(POWER_DOMAIN_PIPE_B) |                  \
+       BIT_ULL(POWER_DOMAIN_TRANSCODER_A) |            \
+       BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |            \
+       BIT_ULL(POWER_DOMAIN_TRANSCODER_C) |            \
+       BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |     \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) |        \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) |           \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) |        \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) |           \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |        \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) |           \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) |        \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO) |           \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_F_LANES) |        \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_F_IO) |           \
+       BIT_ULL(POWER_DOMAIN_AUX_B) |                   \
+       BIT_ULL(POWER_DOMAIN_AUX_C) |                   \
+       BIT_ULL(POWER_DOMAIN_AUX_D) |                   \
+       BIT_ULL(POWER_DOMAIN_AUX_E) |                   \
+       BIT_ULL(POWER_DOMAIN_AUX_F) |                   \
+       BIT_ULL(POWER_DOMAIN_AUX_TBT1) |                \
+       BIT_ULL(POWER_DOMAIN_AUX_TBT2) |                \
+       BIT_ULL(POWER_DOMAIN_AUX_TBT3) |                \
+       BIT_ULL(POWER_DOMAIN_AUX_TBT4) |                \
+       BIT_ULL(POWER_DOMAIN_VGA) |                     \
+       BIT_ULL(POWER_DOMAIN_AUDIO) |                   \
+       BIT_ULL(POWER_DOMAIN_INIT))
+       /*
+        * - transcoder WD
+        * - KVMR (HW control)
+        */
+#define ICL_PW_2_POWER_DOMAINS (                       \
+       ICL_PW_3_POWER_DOMAINS |                        \
+       BIT_ULL(POWER_DOMAIN_INIT))
+       /*
+        * - eDP/DSI VDSC
+        * - KVMR (HW control)
+        */
+#define ICL_DISPLAY_DC_OFF_POWER_DOMAINS (             \
+       ICL_PW_2_POWER_DOMAINS |                        \
+       BIT_ULL(POWER_DOMAIN_MODESET) |                 \
+       BIT_ULL(POWER_DOMAIN_AUX_A) |                   \
+       BIT_ULL(POWER_DOMAIN_INIT))
+
+#define ICL_DDI_IO_A_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO))
+#define ICL_DDI_IO_B_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO))
+#define ICL_DDI_IO_C_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO))
+#define ICL_DDI_IO_D_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO))
+#define ICL_DDI_IO_E_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO))
+#define ICL_DDI_IO_F_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_PORT_DDI_F_IO))
+
+#define ICL_AUX_A_IO_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_AUX_A))
+#define ICL_AUX_B_IO_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_AUX_B))
+#define ICL_AUX_C_IO_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_AUX_C))
+#define ICL_AUX_D_IO_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_AUX_D))
+#define ICL_AUX_E_IO_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_AUX_E))
+#define ICL_AUX_F_IO_POWER_DOMAINS (                   \
+       BIT_ULL(POWER_DOMAIN_AUX_F))
+#define ICL_AUX_TBT1_IO_POWER_DOMAINS (                        \
+       BIT_ULL(POWER_DOMAIN_AUX_TBT1))
+#define ICL_AUX_TBT2_IO_POWER_DOMAINS (                        \
+       BIT_ULL(POWER_DOMAIN_AUX_TBT2))
+#define ICL_AUX_TBT3_IO_POWER_DOMAINS (                        \
+       BIT_ULL(POWER_DOMAIN_AUX_TBT3))
+#define ICL_AUX_TBT4_IO_POWER_DOMAINS (                        \
+       BIT_ULL(POWER_DOMAIN_AUX_TBT4))
+
 static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
        .sync_hw = i9xx_power_well_sync_hw_noop,
        .enable = i9xx_always_on_power_well_noop,
@@ -2454,6 +2599,157 @@ static struct i915_power_well cnl_power_wells[] = {
        },
 };
 
+static const struct i915_power_well_ops icl_combo_phy_aux_power_well_ops = {
+       .sync_hw = hsw_power_well_sync_hw,
+       .enable = icl_combo_phy_aux_power_well_enable,
+       .disable = icl_combo_phy_aux_power_well_disable,
+       .is_enabled = hsw_power_well_enabled,
+};
+
+static struct i915_power_well icl_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = POWER_DOMAIN_MASK,
+               .ops = &i9xx_always_on_power_well_ops,
+               .id = I915_DISP_PW_ALWAYS_ON,
+       },
+       {
+               .name = "power well 1",
+               /* Handled by the DMC firmware */
+               .domains = 0,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_1,
+               .hsw.has_fuses = true,
+       },
+       {
+               .name = "power well 2",
+               .domains = ICL_PW_2_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_2,
+               .hsw.has_fuses = true,
+       },
+       {
+               .name = "DC off",
+               .domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS,
+               .ops = &gen9_dc_off_power_well_ops,
+               .id = SKL_DISP_PW_DC_OFF,
+       },
+       {
+               .name = "power well 3",
+               .domains = ICL_PW_3_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_3,
+               .hsw.irq_pipe_mask = BIT(PIPE_B),
+               .hsw.has_vga = true,
+               .hsw.has_fuses = true,
+       },
+       {
+               .name = "DDI A IO",
+               .domains = ICL_DDI_IO_A_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_DDI_A,
+       },
+       {
+               .name = "DDI B IO",
+               .domains = ICL_DDI_IO_B_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_DDI_B,
+       },
+       {
+               .name = "DDI C IO",
+               .domains = ICL_DDI_IO_C_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_DDI_C,
+       },
+       {
+               .name = "DDI D IO",
+               .domains = ICL_DDI_IO_D_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_DDI_D,
+       },
+       {
+               .name = "DDI E IO",
+               .domains = ICL_DDI_IO_E_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_DDI_E,
+       },
+       {
+               .name = "DDI F IO",
+               .domains = ICL_DDI_IO_F_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_DDI_F,
+       },
+       {
+               .name = "AUX A",
+               .domains = ICL_AUX_A_IO_POWER_DOMAINS,
+               .ops = &icl_combo_phy_aux_power_well_ops,
+               .id = ICL_DISP_PW_AUX_A,
+       },
+       {
+               .name = "AUX B",
+               .domains = ICL_AUX_B_IO_POWER_DOMAINS,
+               .ops = &icl_combo_phy_aux_power_well_ops,
+               .id = ICL_DISP_PW_AUX_B,
+       },
+       {
+               .name = "AUX C",
+               .domains = ICL_AUX_C_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_AUX_C,
+       },
+       {
+               .name = "AUX D",
+               .domains = ICL_AUX_D_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_AUX_D,
+       },
+       {
+               .name = "AUX E",
+               .domains = ICL_AUX_E_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_AUX_E,
+       },
+       {
+               .name = "AUX F",
+               .domains = ICL_AUX_F_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_AUX_F,
+       },
+       {
+               .name = "AUX TBT1",
+               .domains = ICL_AUX_TBT1_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_AUX_TBT1,
+       },
+       {
+               .name = "AUX TBT2",
+               .domains = ICL_AUX_TBT2_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_AUX_TBT2,
+       },
+       {
+               .name = "AUX TBT3",
+               .domains = ICL_AUX_TBT3_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_AUX_TBT3,
+       },
+       {
+               .name = "AUX TBT4",
+               .domains = ICL_AUX_TBT4_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_AUX_TBT4,
+       },
+       {
+               .name = "power well 4",
+               .domains = ICL_PW_4_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = ICL_DISP_PW_4,
+               .hsw.has_fuses = true,
+               .hsw.irq_pipe_mask = BIT(PIPE_C),
+       },
+};
+
 static int
 sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv,
                                   int disable_power_well)
@@ -2471,7 +2767,7 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
        int requested_dc;
        int max_dc;
 
-       if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) {
+       if (IS_GEN9_BC(dev_priv) || INTEL_INFO(dev_priv)->gen >= 10) {
                max_dc = 2;
                mask = 0;
        } else if (IS_GEN9_LP(dev_priv)) {
@@ -2559,7 +2855,9 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
         * The enabling order will be from lower to higher indexed wells,
         * the disabling order is reversed.
         */
-       if (IS_HASWELL(dev_priv)) {
+       if (IS_ICELAKE(dev_priv)) {
+               set_power_wells(power_domains, icl_power_wells);
+       } else if (IS_HASWELL(dev_priv)) {
                set_power_wells(power_domains, hsw_power_wells);
        } else if (IS_BROADWELL(dev_priv)) {
                set_power_wells(power_domains, bdw_power_wells);
@@ -3026,6 +3324,8 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv)
 static void icl_display_core_init(struct drm_i915_private *dev_priv,
                                  bool resume)
 {
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_well *well;
        enum port port;
        u32 val;
 
@@ -3054,8 +3354,14 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
                I915_WRITE(ICL_PORT_CL_DW5(port), val);
        }
 
-       /* 4. Enable power well 1 (PG1) and aux IO power. */
-       /* FIXME: ICL power wells code not here yet. */
+       /*
+        * 4. Enable Power Well 1 (PG1).
+        *    The AUX IO power wells will be enabled on demand.
+        */
+       mutex_lock(&power_domains->lock);
+       well = lookup_power_well(dev_priv, ICL_DISP_PW_1);
+       intel_power_well_enable(dev_priv, well);
+       mutex_unlock(&power_domains->lock);
 
        /* 5. Enable CDCLK. */
        icl_init_cdclk(dev_priv);
@@ -3073,6 +3379,8 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
 
 static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
 {
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_well *well;
        enum port port;
        u32 val;
 
@@ -3086,8 +3394,15 @@ static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
        /* 3. Disable CD clock */
        icl_uninit_cdclk(dev_priv);
 
-       /* 4. Disable Power Well 1 (PG1) and Aux IO Power */
-       /* FIXME: ICL power wells code not here yet. */
+       /*
+        * 4. Disable Power Well 1 (PG1).
+        *    The AUX IO power wells are toggled on demand, so they are already
+        *    disabled at this point.
+        */
+       mutex_lock(&power_domains->lock);
+       well = lookup_power_well(dev_priv, ICL_DISP_PW_1);
+       intel_power_well_disable(dev_priv, well);
+       mutex_unlock(&power_domains->lock);
 
        /* 5. Disable Comp */
        for (port = PORT_A; port <= PORT_B; port++) {