Message ID | 20180626142232.22361-1-imre.deak@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Em Ter, 2018-06-26 às 17:22 +0300, Imre Deak escreveu: > 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. > > 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) > --- > drivers/gpu/drm/i915/i915_reg.h | 78 +++++++- > drivers/gpu/drm/i915/intel_display.h | 4 + > drivers/gpu/drm/i915/intel_runtime_pm.c | 329 > +++++++++++++++++++++++++++++++- > 3 files changed, 395 insertions(+), 16 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h > b/drivers/gpu/drm/i915/i915_reg.h > index caad19f5f557..865b05ce8d76 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -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(_PICK((port), You can get away with _PIPE instead of _PICK here, which is supposed to be a little more efficient. Otherwise, looks correct (minus checkpatch problems). Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> But I would say the PW code is getting very hard to read. The whole magic behind the i915_power_well_id enum values is hard to read, and a lot of other magic macros build on top of that. I would really love if our code were a little more straightforward, less reliant on the magic, even if it were a little bigger. Stuff like _HSW_PW_REG_IDX() and others are crazy. Ideally the code would not have to rely on the value of the actual enum for anything. But all of that is content for a new series. > \ > + _ICL_PORT_CL_DW1 > 2_A, \ > + _ICL_PORT_CL_DW1 > 2_B)) > + > #define _PORT_CL1CM_DW28_A 0x162070 > #define _PORT_CL1CM_DW28_BC 0x6C070 > #define OCL1_POWER_DOWN_EN (1 << 23) > @@ -8563,6 +8607,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 > @@ -8572,14 +8624,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_CT > L1)) > + _HSW_PWR_WELL_CT > L1, \ > + _ICL_PWR_WELL_CT > L_AUX1, \ > + _ICL_PWR_WELL_CT > L_DDI1)) > #define HSW_PWR_WELL_CTL_DRIVER(pw) _MMIO(_PICK(_HSW_PW_REG_I > DX(pw), \ > - _HSW_PWR_WELL_CT > L2)) > + _HSW_PWR_WELL_CT > L2, \ > + _ICL_PWR_WELL_CT > L_AUX2, \ > + _ICL_PWR_WELL_CT > L_DDI2)) > +/* KVMR doesn't have a reg for AUX or DDI power well control */ > #define HSW_PWR_WELL_CTL_KVMR _MMIO(_HSW_PWR_WELL_CTL > 3) > #define HSW_PWR_WELL_CTL_DEBUG(pw) _MMIO(_PICK(_HSW_PW_REG_ID > X(pw), \ > - _HSW_PWR_WELL_CT > L4)) > + _HSW_PWR_WELL_CT > L4, \ > + _ICL_PWR_WELL_CT > L_AUX4, \ > + _ICL_PWR_WELL_CT > L_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)) > @@ -8600,6 +8658,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) > diff --git a/drivers/gpu/drm/i915/intel_display.h > b/drivers/gpu/drm/i915/intel_display.h > index dfb02da73ac8..a77dd29db2ec 100644 > --- a/drivers/gpu/drm/i915/intel_display.h > +++ b/drivers/gpu/drm/i915/intel_display.h > @@ -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, > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c > b/drivers/gpu/drm/i915/intel_runtime_pm.c > index 2969787201ef..790670f5fb98 100644 > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c > @@ -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++) {
On Tue, Jun 26, 2018 at 05:28:06PM -0700, Paulo Zanoni wrote: > Em Ter, 2018-06-26 às 17:22 +0300, Imre Deak escreveu: > > 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. > > > > 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) > > --- > > drivers/gpu/drm/i915/i915_reg.h | 78 +++++++- > > drivers/gpu/drm/i915/intel_display.h | 4 + > > drivers/gpu/drm/i915/intel_runtime_pm.c | 329 > > +++++++++++++++++++++++++++++++- > > 3 files changed, 395 insertions(+), 16 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h > > b/drivers/gpu/drm/i915/i915_reg.h > > index caad19f5f557..865b05ce8d76 100644 > > --- a/drivers/gpu/drm/i915/i915_reg.h > > +++ b/drivers/gpu/drm/i915/i915_reg.h > > @@ -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(_PICK((port), > > You can get away with _PIPE instead of _PICK here, which is supposed to > be a little more efficient. There's a third instance of the register with a different offset, but yes we can use _PIPE until that is taken into use. Will change that along with the checkpatch issues. > > Otherwise, looks correct (minus checkpatch problems). > Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > > But I would say the PW code is getting very hard to read. The whole > magic behind the i915_power_well_id enum values is hard to read, and a > lot of other magic macros build on top of that. Not having the usual register definition followed by the definition of the flags withing the register is not so nice. I considered adding the register address and request/status flag positions to the power well descriptors somehow, will look into that. > I would really love if our code were a little more straightforward, > less reliant on the magic, even if it were a little bigger. Stuff like > _HSW_PW_REG_IDX() and others are crazy. Ideally the code would not > have to rely on the value of the actual enum for anything. But all of > that is content for a new series. > > > > \ > > + _ICL_PORT_CL_DW1 > > 2_A, \ > > + _ICL_PORT_CL_DW1 > > 2_B)) > > + > > #define _PORT_CL1CM_DW28_A 0x162070 > > #define _PORT_CL1CM_DW28_BC 0x6C070 > > #define OCL1_POWER_DOWN_EN (1 << 23) > > @@ -8563,6 +8607,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 > > @@ -8572,14 +8624,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_CT > > L1)) > > + _HSW_PWR_WELL_CT > > L1, \ > > + _ICL_PWR_WELL_CT > > L_AUX1, \ > > + _ICL_PWR_WELL_CT > > L_DDI1)) > > #define HSW_PWR_WELL_CTL_DRIVER(pw) _MMIO(_PICK(_HSW_PW_REG_I > > DX(pw), \ > > - _HSW_PWR_WELL_CT > > L2)) > > + _HSW_PWR_WELL_CT > > L2, \ > > + _ICL_PWR_WELL_CT > > L_AUX2, \ > > + _ICL_PWR_WELL_CT > > L_DDI2)) > > +/* KVMR doesn't have a reg for AUX or DDI power well control */ > > #define HSW_PWR_WELL_CTL_KVMR _MMIO(_HSW_PWR_WELL_CTL > > 3) > > #define HSW_PWR_WELL_CTL_DEBUG(pw) _MMIO(_PICK(_HSW_PW_REG_ID > > X(pw), \ > > - _HSW_PWR_WELL_CT > > L4)) > > + _HSW_PWR_WELL_CT > > L4, \ > > + _ICL_PWR_WELL_CT > > L_AUX4, \ > > + _ICL_PWR_WELL_CT > > L_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)) > > @@ -8600,6 +8658,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) > > diff --git a/drivers/gpu/drm/i915/intel_display.h > > b/drivers/gpu/drm/i915/intel_display.h > > index dfb02da73ac8..a77dd29db2ec 100644 > > --- a/drivers/gpu/drm/i915/intel_display.h > > +++ b/drivers/gpu/drm/i915/intel_display.h > > @@ -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, > > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c > > b/drivers/gpu/drm/i915/intel_runtime_pm.c > > index 2969787201ef..790670f5fb98 100644 > > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c > > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c > > @@ -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++) {
On Tue, Jun 26, 2018 at 04:12:24PM +0000, Patchwork wrote: > == Series Details == > > Series: drm/i915/icl: Add power well support > URL : https://patchwork.freedesktop.org/series/45409/ > State : success Pushed it to -dinq with the s/_PICK(_MMIO())/_MMIO_PORT()/ change and the checkpatch warnings fixed. Thanks for the reviews. > > == Summary == > > = CI Bug Log - changes from CI_DRM_4380_full -> Patchwork_9424_full = > > == Summary - WARNING == > > Minor unknown changes coming with Patchwork_9424_full need to be verified > manually. > > If you think the reported changes have nothing to do with the changes > introduced in Patchwork_9424_full, please notify your bug team to allow them > to document this new failure mode, which will reduce false positives in CI. > > > > == Possible new issues == > > Here are the unknown changes that may have been introduced in Patchwork_9424_full: > > === IGT changes === > > ==== Warnings ==== > > igt@gem_exec_schedule@deep-bsd2: > shard-kbl: SKIP -> PASS > > igt@gem_exec_schedule@deep-vebox: > shard-kbl: PASS -> SKIP > > > == Known issues == > > Here are the changes found in Patchwork_9424_full that come from known issues: > > === IGT changes === > > ==== Issues hit ==== > > igt@drv_selftest@live_hangcheck: > shard-apl: PASS -> DMESG-FAIL (fdo#106947, fdo#106560) > > igt@kms_atomic_transition@1x-modeset-transitions-nonblocking: > shard-glk: PASS -> FAIL (fdo#105703) > > igt@kms_flip@2x-flip-vs-expired-vblank: > shard-glk: PASS -> FAIL (fdo#105363) > > igt@kms_flip_tiling@flip-x-tiled: > shard-glk: PASS -> FAIL (fdo#103822, fdo#104724) > > > ==== Possible fixes ==== > > igt@drv_selftest@live_hangcheck: > shard-kbl: DMESG-FAIL (fdo#106947, fdo#106560) -> PASS > > igt@gem_ctx_isolation@rcs0-s3: > shard-kbl: INCOMPLETE (fdo#103665) -> PASS > > igt@kms_flip@plain-flip-ts-check-interruptible: > shard-glk: FAIL (fdo#100368) -> PASS +1 > > igt@kms_flip_tiling@flip-y-tiled: > shard-glk: FAIL (fdo#104724) -> PASS > > > ==== Warnings ==== > > igt@drv_selftest@live_gtt: > shard-glk: FAIL (fdo#105347) -> INCOMPLETE (k.org#198133, fdo#103359) > > > fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368 > fdo#103359 https://bugs.freedesktop.org/show_bug.cgi?id=103359 > fdo#103665 https://bugs.freedesktop.org/show_bug.cgi?id=103665 > fdo#103822 https://bugs.freedesktop.org/show_bug.cgi?id=103822 > fdo#104724 https://bugs.freedesktop.org/show_bug.cgi?id=104724 > fdo#105347 https://bugs.freedesktop.org/show_bug.cgi?id=105347 > fdo#105363 https://bugs.freedesktop.org/show_bug.cgi?id=105363 > fdo#105703 https://bugs.freedesktop.org/show_bug.cgi?id=105703 > fdo#106560 https://bugs.freedesktop.org/show_bug.cgi?id=106560 > fdo#106947 https://bugs.freedesktop.org/show_bug.cgi?id=106947 > k.org#198133 https://bugzilla.kernel.org/show_bug.cgi?id=198133 > > > == Participating hosts (5 -> 5) == > > No changes in participating hosts > > > == Build changes == > > * Linux: CI_DRM_4380 -> Patchwork_9424 > > CI_DRM_4380: e69a5560b14d9c7377744267ffd9963f06734f38 @ git://anongit.freedesktop.org/gfx-ci/linux > IGT_4530: 0e98bf69f146eb72fe3a7c3b19a049b5786f0ca3 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools > Patchwork_9424: 409dfff082a1aca653c41e87af092e1e12e2673d @ git://anongit.freedesktop.org/gfx-ci/linux > piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit > > == Logs == > > For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9424/shards.html
On Wed, 27 Jun 2018, Imre Deak <imre.deak@intel.com> wrote: > Pushed it to -dinq with the s/_PICK(_MMIO())/_MMIO_PORT()/ change and the > checkpatch warnings fixed. Thanks for the reviews. I'd prefer it if actual functional changes were resent to the list for CI instead of fixed in place. BR, Jani.
On Wed, Jun 27, 2018 at 04:52:27PM +0300, Jani Nikula wrote: > On Wed, 27 Jun 2018, Imre Deak <imre.deak@intel.com> wrote: > > Pushed it to -dinq with the s/_PICK(_MMIO())/_MMIO_PORT()/ change and the > > checkpatch warnings fixed. Thanks for the reviews. > > I'd prefer it if actual functional changes were resent to the list for > CI instead of fixed in place. Hm, I considered this a trivial change. Is there a rule that prevents any code changes while merging, or something saying what's considered trivial? > > BR, > Jani. > > -- > Jani Nikula, Intel Open Source Graphics Center
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index caad19f5f557..865b05ce8d76 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -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(_PICK((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) @@ -8563,6 +8607,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 @@ -8572,14 +8624,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)) @@ -8600,6 +8658,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) diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h index dfb02da73ac8..a77dd29db2ec 100644 --- a/drivers/gpu/drm/i915/intel_display.h +++ b/drivers/gpu/drm/i915/intel_display.h @@ -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, diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 2969787201ef..790670f5fb98 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -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++) {