Message ID | 20180720141504.22832-7-imre.deak@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Em Sex, 2018-07-20 às 17:15 +0300, Imre Deak escreveu: > Similarly to the previous patch use a separate request/status HW flag > index defined right after the corresponding control registers instead > of > depending for this on the power well IDs. Since the set of > control/status registers varies among the different power wells (on a > single platform), also add a new i915_power_well_registers struct > that > we populate and assign to each DDI power well as needed. > > Also clarify a bit the code comment describing the function and > layout > of the control registers. > > This also fixes a problem on ICL, where we incorrectly read the KVMR > control register in hsw_power_well_requesters() even for DDI and AUX > power wells. > > Cc: Ville Syrjala <ville.syrjala@linux.intel.com> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com> > Cc: Jani Nikula <jani.nikula@intel.com> > Signed-off-by: Imre Deak <imre.deak@intel.com> > --- > drivers/gpu/drm/i915/gvt/handlers.c | 30 +--- > drivers/gpu/drm/i915/i915_drv.h | 13 ++ > drivers/gpu/drm/i915/i915_reg.h | 126 ++++++++----- > drivers/gpu/drm/i915/intel_display.c | 5 +- > drivers/gpu/drm/i915/intel_runtime_pm.c | 302 > ++++++++++++++++++++++++++------ > 5 files changed, 359 insertions(+), 117 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gvt/handlers.c > b/drivers/gpu/drm/i915/gvt/handlers.c > index 7a58ca555197..79e748569d31 100644 > --- a/drivers/gpu/drm/i915/gvt/handlers.c > +++ b/drivers/gpu/drm/i915/gvt/handlers.c > @@ -1287,12 +1287,12 @@ static int power_well_ctl_mmio_write(struct > intel_vgpu *vgpu, > { > write_vreg(vgpu, offset, p_data, bytes); > > - if (vgpu_vreg(vgpu, offset) & > HSW_PWR_WELL_CTL_REQ(HSW_DISP_PW_GLOBAL)) > + if (vgpu_vreg(vgpu, offset) & > HSW_PWR_WELL_CTL_REQ(HSW_PW_CTL_IDX_GLOBAL)) > vgpu_vreg(vgpu, offset) |= > - HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL); > + HSW_PWR_WELL_CTL_STATE(HSW_PW_CTL_IDX_GLOBAL > ); > else > vgpu_vreg(vgpu, offset) &= > - ~HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL); > + ~HSW_PWR_WELL_CTL_STATE(HSW_PW_CTL_IDX_GLOBA > L); > return 0; > } > > @@ -2443,17 +2443,10 @@ static int init_generic_mmio_info(struct > intel_gvt *gvt) > MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL); > MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL); > MMIO_D(GEN6_PMINTRMSK, D_ALL); > - /* > - * Use an arbitrary power well controlled by the > PWR_WELL_CTL > - * register. > - */ > - MMIO_DH(HSW_PWR_WELL_CTL_BIOS(HSW_DISP_PW_GLOBAL), D_BDW, > NULL, > - power_well_ctl_mmio_write); > - MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL), D_BDW, > NULL, > - power_well_ctl_mmio_write); > - MMIO_DH(HSW_PWR_WELL_CTL_KVMR, D_BDW, NULL, > power_well_ctl_mmio_write); > - MMIO_DH(HSW_PWR_WELL_CTL_DEBUG(HSW_DISP_PW_GLOBAL), D_BDW, > NULL, > - power_well_ctl_mmio_write); > + MMIO_DH(HSW_PWR_WELL_CTL1, D_BDW, NULL, > power_well_ctl_mmio_write); > + MMIO_DH(HSW_PWR_WELL_CTL2, D_BDW, NULL, > power_well_ctl_mmio_write); > + MMIO_DH(HSW_PWR_WELL_CTL3, D_BDW, NULL, > power_well_ctl_mmio_write); > + MMIO_DH(HSW_PWR_WELL_CTL4, D_BDW, NULL, > power_well_ctl_mmio_write); > MMIO_DH(HSW_PWR_WELL_CTL5, D_BDW, NULL, > power_well_ctl_mmio_write); > MMIO_DH(HSW_PWR_WELL_CTL6, D_BDW, NULL, > power_well_ctl_mmio_write); > > @@ -2804,13 +2797,8 @@ static int init_skl_mmio_info(struct intel_gvt > *gvt) > MMIO_F(_MMIO(_DPD_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_SKL_PLUS, > NULL, > dp_aux_ch_ctl_mmio_w > rite); > > - /* > - * Use an arbitrary power well controlled by the > PWR_WELL_CTL > - * register. > - */ > - MMIO_D(HSW_PWR_WELL_CTL_BIOS(SKL_DISP_PW_MISC_IO), > D_SKL_PLUS); > - MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(SKL_DISP_PW_MISC_IO), > D_SKL_PLUS, NULL, > - skl_power_well_ctl_write); > + MMIO_D(HSW_PWR_WELL_CTL1, D_SKL_PLUS); > + MMIO_DH(HSW_PWR_WELL_CTL2, D_SKL_PLUS, NULL, > skl_power_well_ctl_write); > > MMIO_D(_MMIO(0xa210), D_SKL_PLUS); > MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); > diff --git a/drivers/gpu/drm/i915/i915_drv.h > b/drivers/gpu/drm/i915/i915_drv.h > index d31a8ef05d18..d73ce0a7b8f7 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -861,6 +861,13 @@ struct i915_power_well_ops { > struct i915_power_well *power_well); > }; > > +struct i915_power_well_regs { > + i915_reg_t bios; > + i915_reg_t driver; > + i915_reg_t kvmr; > + i915_reg_t debug; > +}; > + > /* Power well structure for haswell */ > struct i915_power_well_desc { > const char *name; > @@ -884,6 +891,12 @@ struct i915_power_well_desc { > enum dpio_phy phy; > } bxt; > struct { > + const struct i915_power_well_regs *regs; > + /* > + * request/status flag index in the power > well > + * constrol/status registers. > + */ > + u8 idx; > /* Mask of pipes whose IRQ logic is backed > by the pw */ > u8 irq_pipe_mask; > /* The pw is backing the VGA functionality > */ > diff --git a/drivers/gpu/drm/i915/i915_reg.h > b/drivers/gpu/drm/i915/i915_reg.h > index f76bb4f3c944..b7022fb8d524 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -8842,46 +8842,78 @@ enum { > #define HSW_AUD_CHICKENBIT _MMIO(0x65f10) > #define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15) > > -/* HSW Power Wells */ > -#define _HSW_PWR_WELL_CTL1 0x45400 > -#define _HSW_PWR_WELL_CTL2 0x45404 > -#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 > - * power well ID (see i915_power_well_id). There are 4 possible > sources of > - * power well requests each source having its own set of control > registers: > - * BIOS, DRIVER, KVMR, DEBUG. > + * HSW-ICL power wells > + * > + * Platforms have up to 3 power well control register sets, each set > + * controlling up to 16 power wells via a request/status HW flag > tuple: > + * - main (HSW_PWR_WELL_CTL[1-4]) > + * - AUX (ICL_PWR_WELL_CTL_AUX[1-4]) > + * - DDI (ICL_PWR_WELL_CTL_DDI[1-4]) > + * Each control register set consists of up to 4 registers used by > different > + * sources that can request a power well to be enabled: > + * - > BIOS (HSW_PWR_WELL_CTL1/ICL_PWR_WELL_CTL_AUX1/ICL_PWR_WELL_CTL_DDI1 > ) > + * - DRIVER > (HSW_PWR_WELL_CTL2/ICL_PWR_WELL_CTL_AUX2/ICL_PWR_WELL_CTL_DDI2) > + * - KVMR (HSW_PWR_WELL_CTL3) (only in the main register set) > + * - > DEBUG (HSW_PWR_WELL_CTL4/ICL_PWR_WELL_CTL_AUX4/ICL_PWR_WELL_CTL_DDI4 > ) > */ > -#define _HSW_PW_REG_IDX(pw) ((pw) >> 4) > -#define _HSW_PW_SHIFT(pw) (((pw) & 0xf) * 2) > -#define HSW_PWR_WELL_CTL_BIOS(pw) _MMIO(_PICK(_HSW_PW_REG_IDX > (pw), \ > - _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, \ > - _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, \ > - _ICL_PWR_WELL_CT > L_AUX4, \ > - _ICL_PWR_WELL_CT > L_DDI4)) > +#define HSW_PWR_WELL_CTL1 _MMIO(0x45400) > +#define HSW_PWR_WELL_CTL2 _MMIO(0x45404) > +#define HSW_PWR_WELL_CTL3 _MMIO(0x45408) > +#define HSW_PWR_WELL_CTL4 _MMIO(0x4540C) > +#define HSW_PWR_WELL_CTL_REQ(pw_idx) (0x2 << > ((pw_idx) * 2)) > +#define HSW_PWR_WELL_CTL_STATE(pw_idx) (0x1 << ((pw_idx) * > 2)) > > -#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)) > +/* HSW/BDW power well */ > +#define HSW_PW_CTL_IDX_GLOBAL 15 > + > +/* SKL/BXT/GLK/CNL power wells */ > +#define SKL_PW_CTL_IDX_PW_2 15 > +#define SKL_PW_CTL_IDX_PW_1 14 > +#define CNL_PW_CTL_IDX_AUX_F 12 > +#define CNL_PW_CTL_IDX_AUX_D 11 > +#define GLK_PW_CTL_IDX_AUX_C 10 > +#define GLK_PW_CTL_IDX_AUX_B 9 > +#define GLK_PW_CTL_IDX_AUX_A 8 > +#define CNL_PW_CTL_IDX_DDI_F 6 > +#define SKL_PW_CTL_IDX_DDI_D 4 > +#define SKL_PW_CTL_IDX_DDI_C 3 > +#define SKL_PW_CTL_IDX_DDI_B 2 > +#define SKL_PW_CTL_IDX_DDI_A_E 1 > +#define GLK_PW_CTL_IDX_DDI_A 1 > +#define SKL_PW_CTL_IDX_MISC_IO 0 > + > +/* ICL- power wells */ Single nitpick for a big patch: my OCD tells me to put a space before '-' or remove it completely because "ICL-" as is can be read as "ICL and older" to the distracted reader. Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > +#define ICL_PW_CTL_IDX_PW_4 3 > +#define ICL_PW_CTL_IDX_PW_3 2 > +#define ICL_PW_CTL_IDX_PW_2 1 > +#define ICL_PW_CTL_IDX_PW_1 0 > + > +#define ICL_PWR_WELL_CTL_AUX1 _MMIO(0x45440) > +#define ICL_PWR_WELL_CTL_AUX2 _MMIO(0x45444) > +#define ICL_PWR_WELL_CTL_AUX4 _MMIO(0x4544C) > +#define ICL_PW_CTL_IDX_AUX_TBT4 11 > +#define ICL_PW_CTL_IDX_AUX_TBT3 10 > +#define ICL_PW_CTL_IDX_AUX_TBT2 9 > +#define ICL_PW_CTL_IDX_AUX_TBT1 8 > +#define ICL_PW_CTL_IDX_AUX_F 5 > +#define ICL_PW_CTL_IDX_AUX_E 4 > +#define ICL_PW_CTL_IDX_AUX_D 3 > +#define ICL_PW_CTL_IDX_AUX_C 2 > +#define ICL_PW_CTL_IDX_AUX_B 1 > +#define ICL_PW_CTL_IDX_AUX_A 0 > + > +#define ICL_PWR_WELL_CTL_DDI1 _MMIO(0x45450) > +#define ICL_PWR_WELL_CTL_DDI2 _MMIO(0x45454) > +#define ICL_PWR_WELL_CTL_DDI4 _MMIO(0x4545C) > +#define ICL_PW_CTL_IDX_DDI_F 5 > +#define ICL_PW_CTL_IDX_DDI_E 4 > +#define ICL_PW_CTL_IDX_DDI_D 3 > +#define ICL_PW_CTL_IDX_DDI_C 2 > +#define ICL_PW_CTL_IDX_DDI_B 1 > +#define ICL_PW_CTL_IDX_DDI_A 0 > + > +/* HSW- power well misc debug registers */ > #define HSW_PWR_WELL_CTL5 _MMIO(0x45410) > #define HSW_PWR_WELL_ENABLE_SINGLE_STEP (1 << 31) > #define HSW_PWR_WELL_PWR_GATE_OVERRIDE (1 << 20) > @@ -8897,18 +8929,26 @@ enum skl_power_gate { > > #define SKL_FUSE_STATUS _MMIO(0x42000 > ) > #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) > +/* > + * PG0 is HW controlled, so doesn't have a corresponding power well > control knob > + * SKL_DISP_PW1_IDX..SKL_DISP_PW2_IDX -> PG1..PG2 > + */ > +#define SKL_PW_CTL_IDX_TO_PG(pw_idx) \ > + ((pw_idx) - SKL_PW_CTL_IDX_PW_1 + SKL_PG1) > +/* > + * PG0 is HW controlled, so doesn't have a corresponding power well > control knob > + * ICL_DISP_PW1_IDX..ICL_DISP_PW4_IDX -> PG1..PG4 > + */ > +#define ICL_PW_CTL_IDX_TO_PG(pw_idx) \ > + ((pw_idx) - ICL_PW_CTL_IDX_PW_1 + SKL_PG1) > #define SKL_FUSE_PG_DIST_STATUS(pg) (1 << (27 - > (pg))) > > -#define _CNL_AUX_REG_IDX(pw) ((pw) - 9) > +#define _CNL_AUX_REG_IDX(pw_idx) ((pw_idx) - > GLK_PW_CTL_IDX_AUX_B) > #define _CNL_AUX_ANAOVRD1_B 0x162250 > #define _CNL_AUX_ANAOVRD1_C 0x162210 > #define _CNL_AUX_ANAOVRD1_D 0x1622D0 > #define _CNL_AUX_ANAOVRD1_F 0x162A90 > -#define CNL_AUX_ANAOVRD1(pw) _MMIO(_PICK(_CNL_AUX_REG > _IDX(pw), \ > +#define CNL_AUX_ANAOVRD1(pw_idx) _MMIO(_PICK(_CNL_AUX_REG_IDX > (pw_idx), \ > _CNL_AUX_ANAOVRD > 1_B, \ > _CNL_AUX_ANAOVRD > 1_C, \ > _CNL_AUX_ANAOVRD > 1_D, \ > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index 87e4cfbfd096..640ec5df4d62 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -8973,7 +8973,7 @@ static void assert_can_disable_lcpll(struct > drm_i915_private *dev_priv) > I915_STATE_WARN(crtc->active, "CRTC for pipe %c > enabled\n", > pipe_name(crtc->pipe)); > > - I915_STATE_WARN(I915_READ(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_P > W_GLOBAL)), > + I915_STATE_WARN(I915_READ(HSW_PWR_WELL_CTL2), > "Display power well on\n"); > I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL > enabled\n"); > I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, > "WRPLL1 enabled\n"); > @@ -16052,8 +16052,7 @@ intel_display_capture_error_state(struct > drm_i915_private *dev_priv) > return NULL; > > if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) > - error->power_well_driver = > - I915_READ(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_P > W_GLOBAL)); > + error->power_well_driver = > I915_READ(HSW_PWR_WELL_CTL2); > > for_each_pipe(dev_priv, i) { > error->pipe[i].power_domain_on = > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c > b/drivers/gpu/drm/i915/intel_runtime_pm.c > index 05d8cdab08cc..5527504d664f 100644 > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c > @@ -323,26 +323,29 @@ static void hsw_power_well_pre_disable(struct > drm_i915_private *dev_priv, > static void hsw_wait_for_power_well_enable(struct drm_i915_private > *dev_priv, > struct i915_power_well > *power_well) > { > - enum i915_power_well_id id = power_well->desc->id; > + const struct i915_power_well_regs *regs = power_well->desc- > >hsw.regs; > + int pw_idx = power_well->desc->hsw.idx; > > /* Timeout for PW1:10 us, AUX:not specified, other PWs:20 > us. */ > WARN_ON(intel_wait_for_register(dev_priv, > - HSW_PWR_WELL_CTL_DRIVER(id), > - HSW_PWR_WELL_CTL_STATE(id), > - HSW_PWR_WELL_CTL_STATE(id), > + regs->driver, > + HSW_PWR_WELL_CTL_STATE(pw_id > x), > + HSW_PWR_WELL_CTL_STATE(pw_id > x), > 1)); > } > > static u32 hsw_power_well_requesters(struct drm_i915_private > *dev_priv, > - enum i915_power_well_id id) > + const struct > i915_power_well_regs *regs, > + int pw_idx) > { > - u32 req_mask = HSW_PWR_WELL_CTL_REQ(id); > + u32 req_mask = HSW_PWR_WELL_CTL_REQ(pw_idx); > u32 ret; > > - ret = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)) & req_mask ? 1 : > 0; > - ret |= I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & req_mask ? 2 > : 0; > - ret |= I915_READ(HSW_PWR_WELL_CTL_KVMR) & req_mask ? 4 : 0; > - ret |= I915_READ(HSW_PWR_WELL_CTL_DEBUG(id)) & req_mask ? 8 > : 0; > + ret = I915_READ(regs->bios) & req_mask ? 1 : 0; > + ret |= I915_READ(regs->driver) & req_mask ? 2 : 0; > + if (regs->kvmr.reg) > + ret |= I915_READ(regs->kvmr) & req_mask ? 4 : 0; > + ret |= I915_READ(regs->debug) & req_mask ? 8 : 0; > > return ret; > } > @@ -350,7 +353,8 @@ static u32 hsw_power_well_requesters(struct > drm_i915_private *dev_priv, > static void hsw_wait_for_power_well_disable(struct drm_i915_private > *dev_priv, > struct i915_power_well > *power_well) > { > - enum i915_power_well_id id = power_well->desc->id; > + const struct i915_power_well_regs *regs = power_well->desc- > >hsw.regs; > + int pw_idx = power_well->desc->hsw.idx; > bool disabled; > u32 reqs; > > @@ -363,9 +367,9 @@ static void > hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, > * Skip the wait in case any of the request bits are set and > print a > * diagnostic message. > */ > - wait_for((disabled = > !(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & > - HSW_PWR_WELL_CTL_STATE(id))) || > - (reqs = hsw_power_well_requesters(dev_priv, id)), > 1); > + wait_for((disabled = !(I915_READ(regs->driver) & > + HSW_PWR_WELL_CTL_STATE(pw_idx))) || > + (reqs = hsw_power_well_requesters(dev_priv, regs, > pw_idx)), 1); > if (disabled) > return; > > @@ -386,14 +390,15 @@ static void > gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv, > static void hsw_power_well_enable(struct drm_i915_private *dev_priv, > struct i915_power_well > *power_well) > { > - enum i915_power_well_id id = power_well->desc->id; > + const struct i915_power_well_regs *regs = power_well->desc- > >hsw.regs; > + int pw_idx = power_well->desc->hsw.idx; > bool wait_fuses = power_well->desc->hsw.has_fuses; > enum skl_power_gate uninitialized_var(pg); > u32 val; > > if (wait_fuses) { > - pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_TO_PG(id) : > - SKL_PW_TO_PG(id); > + pg = INTEL_GEN(dev_priv) >= 11 ? > ICL_PW_CTL_IDX_TO_PG(pw_idx) : > + SKL_PW_CTL_IDX_TO_P > G(pw_idx); > /* > * For PW1 we have to wait both for the PW0/PG0 fuse > state > * before enabling the power well and PW1/PG1's own > fuse > @@ -405,17 +410,17 @@ static void hsw_power_well_enable(struct > drm_i915_private *dev_priv, > gen9_wait_for_power_well_fuses(dev_priv, > SKL_PG0); > } > > - 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(regs->driver); > + I915_WRITE(regs->driver, val | > HSW_PWR_WELL_CTL_REQ(pw_idx)); > hsw_wait_for_power_well_enable(dev_priv, power_well); > > /* Display WA #1178: cnl */ > if (IS_CANNONLAKE(dev_priv) && > - (id == CNL_DISP_PW_AUX_B || id == CNL_DISP_PW_AUX_C || > - id == CNL_DISP_PW_AUX_D || id == CNL_DISP_PW_AUX_F)) { > - val = I915_READ(CNL_AUX_ANAOVRD1(id)); > + pw_idx >= GLK_PW_CTL_IDX_AUX_B && > + pw_idx <= CNL_PW_CTL_IDX_AUX_F) { > + val = I915_READ(CNL_AUX_ANAOVRD1(pw_idx)); > val |= CNL_AUX_ANAOVRD1_ENABLE | > CNL_AUX_ANAOVRD1_LDO_BYPASS; > - I915_WRITE(CNL_AUX_ANAOVRD1(id), val); > + I915_WRITE(CNL_AUX_ANAOVRD1(pw_idx), val); > } > > if (wait_fuses) > @@ -429,30 +434,31 @@ static void hsw_power_well_enable(struct > drm_i915_private *dev_priv, > static void hsw_power_well_disable(struct drm_i915_private > *dev_priv, > struct i915_power_well > *power_well) > { > - enum i915_power_well_id id = power_well->desc->id; > + const struct i915_power_well_regs *regs = power_well->desc- > >hsw.regs; > + int pw_idx = power_well->desc->hsw.idx; > u32 val; > > hsw_power_well_pre_disable(dev_priv, > power_well->desc- > >hsw.irq_pipe_mask); > > - 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(regs->driver); > + I915_WRITE(regs->driver, val & > ~HSW_PWR_WELL_CTL_REQ(pw_idx)); > hsw_wait_for_power_well_disable(dev_priv, power_well); > } > > -#define ICL_AUX_PW_TO_PORT(pw) ((pw) - ICL_DISP_PW_AUX_A) > +#define ICL_AUX_PW_TO_PORT(pw_idx) ((pw_idx) - > ICL_PW_CTL_IDX_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->desc->id; > - enum port port = ICL_AUX_PW_TO_PORT(id); > + const struct i915_power_well_regs *regs = power_well->desc- > >hsw.regs; > + int pw_idx = power_well->desc->hsw.idx; > + enum port port = ICL_AUX_PW_TO_PORT(pw_idx); > 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(regs->driver); > + I915_WRITE(regs->driver, val | > HSW_PWR_WELL_CTL_REQ(pw_idx)); > > val = I915_READ(ICL_PORT_CL_DW12(port)); > I915_WRITE(ICL_PORT_CL_DW12(port), val | > ICL_LANE_ENABLE_AUX); > @@ -464,16 +470,16 @@ 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->desc->id; > - enum port port = ICL_AUX_PW_TO_PORT(id); > + const struct i915_power_well_regs *regs = power_well->desc- > >hsw.regs; > + int pw_idx = power_well->desc->hsw.idx; > + enum port port = ICL_AUX_PW_TO_PORT(pw_idx); > 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)); > + val = I915_READ(regs->driver); > + I915_WRITE(regs->driver, val & > ~HSW_PWR_WELL_CTL_REQ(pw_idx)); > > hsw_wait_for_power_well_disable(dev_priv, power_well); > } > @@ -486,22 +492,22 @@ icl_combo_phy_aux_power_well_disable(struct > drm_i915_private *dev_priv, > static bool hsw_power_well_enabled(struct drm_i915_private > *dev_priv, > struct i915_power_well > *power_well) > { > - enum i915_power_well_id id = power_well->desc->id; > - u32 mask = HSW_PWR_WELL_CTL_REQ(id) | > HSW_PWR_WELL_CTL_STATE(id); > + const struct i915_power_well_regs *regs = power_well->desc- > >hsw.regs; > + int pw_idx = power_well->desc->hsw.idx; > + u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx) | > + HSW_PWR_WELL_CTL_STATE(pw_idx); > > - return (I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & mask) == > mask; > + return (I915_READ(regs->driver) & mask) == mask; > } > > static void assert_can_enable_dc9(struct drm_i915_private *dev_priv) > { > - enum i915_power_well_id id = SKL_DISP_PW_2; > - > WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9), > "DC9 already programmed to be enabled.\n"); > WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5, > "DC5 still not disabled to enable DC9.\n"); > - WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & > - HSW_PWR_WELL_CTL_REQ(id), > + WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL2) & > + HSW_PWR_WELL_CTL_REQ(SKL_PW_CTL_IDX_PW_2), > "Power well 2 on.\n"); > WARN_ONCE(intel_irqs_enabled(dev_priv), > "Interrupts not disabled yet.\n"); > @@ -725,17 +731,18 @@ static void skl_enable_dc6(struct > drm_i915_private *dev_priv) > static void hsw_power_well_sync_hw(struct drm_i915_private > *dev_priv, > struct i915_power_well > *power_well) > { > - enum i915_power_well_id id = power_well->desc->id; > - u32 mask = HSW_PWR_WELL_CTL_REQ(id); > - u32 bios_req = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)); > + const struct i915_power_well_regs *regs = power_well->desc- > >hsw.regs; > + int pw_idx = power_well->desc->hsw.idx; > + u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx); > + u32 bios_req = I915_READ(regs->bios); > > /* Take over the request bit if set by BIOS. */ > if (bios_req & mask) { > - u32 drv_req = > I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)); > + u32 drv_req = I915_READ(regs->driver); > > if (!(drv_req & mask)) > - I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), > drv_req | mask); > - I915_WRITE(HSW_PWR_WELL_CTL_BIOS(id), bios_req & > ~mask); > + I915_WRITE(regs->driver, drv_req | mask); > + I915_WRITE(regs->bios, bios_req & ~mask); > } > } > > @@ -2108,6 +2115,13 @@ static const struct i915_power_well_ops > bxt_dpio_cmn_power_well_ops = { > .is_enabled = bxt_dpio_cmn_power_well_enabled, > }; > > +static const struct i915_power_well_regs hsw_power_well_regs = { > + .bios = HSW_PWR_WELL_CTL1, > + .driver = HSW_PWR_WELL_CTL2, > + .kvmr = HSW_PWR_WELL_CTL3, > + .debug = HSW_PWR_WELL_CTL4, > +}; > + > static const struct i915_power_well_desc hsw_power_wells[] = { > { > .name = "always-on", > @@ -2122,6 +2136,8 @@ static const struct i915_power_well_desc > hsw_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = HSW_DISP_PW_GLOBAL, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, > .hsw.has_vga = true, > }, > }, > @@ -2141,6 +2157,8 @@ static const struct i915_power_well_desc > bdw_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = HSW_DISP_PW_GLOBAL, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, > .hsw.irq_pipe_mask = BIT(PIPE_B) | > BIT(PIPE_C), > .hsw.has_vga = true, > }, > @@ -2310,6 +2328,8 @@ static const struct i915_power_well_desc > skl_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_1, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_PW_1, > .hsw.has_fuses = true, > }, > }, > @@ -2319,6 +2339,10 @@ static const struct i915_power_well_desc > skl_power_wells[] = { > .domains = 0, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_MISC_IO, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_MISC_IO, > + }, > }, > { > .name = "DC off", > @@ -2332,6 +2356,8 @@ static const struct i915_power_well_desc > skl_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_2, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_PW_2, > .hsw.irq_pipe_mask = BIT(PIPE_B) | > BIT(PIPE_C), > .hsw.has_vga = true, > .hsw.has_fuses = true, > @@ -2342,24 +2368,40 @@ static const struct i915_power_well_desc > skl_power_wells[] = { > .domains = SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_A_E, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_A_E, > + }, > }, > { > .name = "DDI B IO power well", > .domains = SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_B, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, > + }, > }, > { > .name = "DDI C IO power well", > .domains = SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_C, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, > + }, > }, > { > .name = "DDI D IO power well", > .domains = SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_D, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_D, > + }, > }, > }; > > @@ -2377,6 +2419,8 @@ static const struct i915_power_well_desc > bxt_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_1, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_PW_1, > .hsw.has_fuses = true, > }, > }, > @@ -2392,6 +2436,8 @@ static const struct i915_power_well_desc > bxt_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_2, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_PW_2, > .hsw.irq_pipe_mask = BIT(PIPE_B) | > BIT(PIPE_C), > .hsw.has_vga = true, > .hsw.has_fuses = true, > @@ -2432,6 +2478,8 @@ static const struct i915_power_well_desc > glk_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_1, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_PW_1, > .hsw.has_fuses = true, > }, > }, > @@ -2447,6 +2495,8 @@ static const struct i915_power_well_desc > glk_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_2, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_PW_2, > .hsw.irq_pipe_mask = BIT(PIPE_B) | > BIT(PIPE_C), > .hsw.has_vga = true, > .hsw.has_fuses = true, > @@ -2484,36 +2534,60 @@ static const struct i915_power_well_desc > glk_power_wells[] = { > .domains = GLK_DISPLAY_AUX_A_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = GLK_DISP_PW_AUX_A, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = GLK_PW_CTL_IDX_AUX_A, > + }, > }, > { > .name = "AUX B", > .domains = GLK_DISPLAY_AUX_B_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = GLK_DISP_PW_AUX_B, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = GLK_PW_CTL_IDX_AUX_B, > + }, > }, > { > .name = "AUX C", > .domains = GLK_DISPLAY_AUX_C_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = GLK_DISP_PW_AUX_C, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = GLK_PW_CTL_IDX_AUX_C, > + }, > }, > { > .name = "DDI A IO power well", > .domains = GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = GLK_DISP_PW_DDI_A, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = GLK_PW_CTL_IDX_DDI_A, > + }, > }, > { > .name = "DDI B IO power well", > .domains = GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_B, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, > + }, > }, > { > .name = "DDI C IO power well", > .domains = GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_C, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, > + }, > }, > }; > > @@ -2532,6 +2606,8 @@ static const struct i915_power_well_desc > cnl_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_1, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_PW_1, > .hsw.has_fuses = true, > }, > }, > @@ -2540,24 +2616,40 @@ static const struct i915_power_well_desc > cnl_power_wells[] = { > .domains = CNL_DISPLAY_AUX_A_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = CNL_DISP_PW_AUX_A, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = GLK_PW_CTL_IDX_AUX_A, > + }, > }, > { > .name = "AUX B", > .domains = CNL_DISPLAY_AUX_B_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = CNL_DISP_PW_AUX_B, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = GLK_PW_CTL_IDX_AUX_B, > + }, > }, > { > .name = "AUX C", > .domains = CNL_DISPLAY_AUX_C_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = CNL_DISP_PW_AUX_C, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = GLK_PW_CTL_IDX_AUX_C, > + }, > }, > { > .name = "AUX D", > .domains = CNL_DISPLAY_AUX_D_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = CNL_DISP_PW_AUX_D, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = CNL_PW_CTL_IDX_AUX_D, > + }, > }, > { > .name = "DC off", > @@ -2571,6 +2663,8 @@ static const struct i915_power_well_desc > cnl_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_2, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_PW_2, > .hsw.irq_pipe_mask = BIT(PIPE_B) | > BIT(PIPE_C), > .hsw.has_vga = true, > .hsw.has_fuses = true, > @@ -2581,36 +2675,60 @@ static const struct i915_power_well_desc > cnl_power_wells[] = { > .domains = CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = CNL_DISP_PW_DDI_A, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = GLK_PW_CTL_IDX_DDI_A, > + }, > }, > { > .name = "DDI B IO power well", > .domains = CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_B, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, > + }, > }, > { > .name = "DDI C IO power well", > .domains = CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_C, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, > + }, > }, > { > .name = "DDI D IO power well", > .domains = CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = SKL_DISP_PW_DDI_D, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = SKL_PW_CTL_IDX_DDI_D, > + }, > }, > { > .name = "DDI F IO power well", > .domains = CNL_DISPLAY_DDI_F_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = CNL_DISP_PW_DDI_F, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = CNL_PW_CTL_IDX_DDI_F, > + }, > }, > { > .name = "AUX F", > .domains = CNL_DISPLAY_AUX_F_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = CNL_DISP_PW_AUX_F, > + { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = CNL_PW_CTL_IDX_AUX_F, > + }, > }, > }; > > @@ -2621,6 +2739,18 @@ static const struct i915_power_well_ops > icl_combo_phy_aux_power_well_ops = { > .is_enabled = hsw_power_well_enabled, > }; > > +static const struct i915_power_well_regs icl_aux_power_well_regs = { > + .bios = ICL_PWR_WELL_CTL_AUX1, > + .driver = ICL_PWR_WELL_CTL_AUX2, > + .debug = ICL_PWR_WELL_CTL_AUX4, > +}; > + > +static const struct i915_power_well_regs icl_ddi_power_well_regs = { > + .bios = ICL_PWR_WELL_CTL_DDI1, > + .driver = ICL_PWR_WELL_CTL_DDI2, > + .debug = ICL_PWR_WELL_CTL_DDI4, > +}; > + > static const struct i915_power_well_desc icl_power_wells[] = { > { > .name = "always-on", > @@ -2636,6 +2766,8 @@ static const struct i915_power_well_desc > icl_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_1, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_PW_1, > .hsw.has_fuses = true, > }, > }, > @@ -2645,6 +2777,8 @@ static const struct i915_power_well_desc > icl_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_2, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_PW_2, > .hsw.has_fuses = true, > }, > }, > @@ -2660,6 +2794,8 @@ static const struct i915_power_well_desc > icl_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_3, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_PW_3, > .hsw.irq_pipe_mask = BIT(PIPE_B), > .hsw.has_vga = true, > .hsw.has_fuses = true, > @@ -2670,96 +2806,160 @@ static const struct i915_power_well_desc > icl_power_wells[] = { > .domains = ICL_DDI_IO_A_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_DDI_A, > + { > + .hsw.regs = &icl_ddi_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_DDI_A, > + }, > }, > { > .name = "DDI B IO", > .domains = ICL_DDI_IO_B_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_DDI_B, > + { > + .hsw.regs = &icl_ddi_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_DDI_B, > + }, > }, > { > .name = "DDI C IO", > .domains = ICL_DDI_IO_C_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_DDI_C, > + { > + .hsw.regs = &icl_ddi_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_DDI_C, > + }, > }, > { > .name = "DDI D IO", > .domains = ICL_DDI_IO_D_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_DDI_D, > + { > + .hsw.regs = &icl_ddi_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_DDI_D, > + }, > }, > { > .name = "DDI E IO", > .domains = ICL_DDI_IO_E_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_DDI_E, > + { > + .hsw.regs = &icl_ddi_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_DDI_E, > + }, > }, > { > .name = "DDI F IO", > .domains = ICL_DDI_IO_F_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_DDI_F, > + { > + .hsw.regs = &icl_ddi_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_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, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_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, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_B, > + }, > }, > { > .name = "AUX C", > .domains = ICL_AUX_C_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_AUX_C, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_C, > + }, > }, > { > .name = "AUX D", > .domains = ICL_AUX_D_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_AUX_D, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_D, > + }, > }, > { > .name = "AUX E", > .domains = ICL_AUX_E_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_AUX_E, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_E, > + }, > }, > { > .name = "AUX F", > .domains = ICL_AUX_F_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_AUX_F, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_F, > + }, > }, > { > .name = "AUX TBT1", > .domains = ICL_AUX_TBT1_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_AUX_TBT1, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT1, > + }, > }, > { > .name = "AUX TBT2", > .domains = ICL_AUX_TBT2_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_AUX_TBT2, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT2, > + }, > }, > { > .name = "AUX TBT3", > .domains = ICL_AUX_TBT3_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_AUX_TBT3, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT3, > + }, > }, > { > .name = "AUX TBT4", > .domains = ICL_AUX_TBT4_IO_POWER_DOMAINS, > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_AUX_TBT4, > + { > + .hsw.regs = &icl_aux_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT4, > + }, > }, > { > .name = "power well 4", > @@ -2767,6 +2967,8 @@ static const struct i915_power_well_desc > icl_power_wells[] = { > .ops = &hsw_power_well_ops, > .id = ICL_DISP_PW_4, > { > + .hsw.regs = &hsw_power_well_regs, > + .hsw.idx = ICL_PW_CTL_IDX_PW_4, > .hsw.has_fuses = true, > .hsw.irq_pipe_mask = BIT(PIPE_C), > },
On Thu, Aug 02, 2018 at 01:40:55PM -0700, Paulo Zanoni wrote: > Em Sex, 2018-07-20 às 17:15 +0300, Imre Deak escreveu: > > Similarly to the previous patch use a separate request/status HW flag > > index defined right after the corresponding control registers instead > > of > > depending for this on the power well IDs. Since the set of > > control/status registers varies among the different power wells (on a > > single platform), also add a new i915_power_well_registers struct > > that > > we populate and assign to each DDI power well as needed. > > > > Also clarify a bit the code comment describing the function and > > layout > > of the control registers. > > > > This also fixes a problem on ICL, where we incorrectly read the KVMR > > control register in hsw_power_well_requesters() even for DDI and AUX > > power wells. > > > > Cc: Ville Syrjala <ville.syrjala@linux.intel.com> > > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com> > > Cc: Jani Nikula <jani.nikula@intel.com> > > Signed-off-by: Imre Deak <imre.deak@intel.com> > > --- > > drivers/gpu/drm/i915/gvt/handlers.c | 30 +--- > > drivers/gpu/drm/i915/i915_drv.h | 13 ++ > > drivers/gpu/drm/i915/i915_reg.h | 126 ++++++++----- > > drivers/gpu/drm/i915/intel_display.c | 5 +- > > drivers/gpu/drm/i915/intel_runtime_pm.c | 302 > > ++++++++++++++++++++++++++------ > > 5 files changed, 359 insertions(+), 117 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/gvt/handlers.c > > b/drivers/gpu/drm/i915/gvt/handlers.c > > index 7a58ca555197..79e748569d31 100644 > > --- a/drivers/gpu/drm/i915/gvt/handlers.c > > +++ b/drivers/gpu/drm/i915/gvt/handlers.c > > @@ -1287,12 +1287,12 @@ static int power_well_ctl_mmio_write(struct > > intel_vgpu *vgpu, > > { > > write_vreg(vgpu, offset, p_data, bytes); > > > > - if (vgpu_vreg(vgpu, offset) & > > HSW_PWR_WELL_CTL_REQ(HSW_DISP_PW_GLOBAL)) > > + if (vgpu_vreg(vgpu, offset) & > > HSW_PWR_WELL_CTL_REQ(HSW_PW_CTL_IDX_GLOBAL)) > > vgpu_vreg(vgpu, offset) |= > > - HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL); > > + HSW_PWR_WELL_CTL_STATE(HSW_PW_CTL_IDX_GLOBAL > > ); > > else > > vgpu_vreg(vgpu, offset) &= > > - ~HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL); > > + ~HSW_PWR_WELL_CTL_STATE(HSW_PW_CTL_IDX_GLOBA > > L); > > return 0; > > } > > > > @@ -2443,17 +2443,10 @@ static int init_generic_mmio_info(struct > > intel_gvt *gvt) > > MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL); > > MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL); > > MMIO_D(GEN6_PMINTRMSK, D_ALL); > > - /* > > - * Use an arbitrary power well controlled by the > > PWR_WELL_CTL > > - * register. > > - */ > > - MMIO_DH(HSW_PWR_WELL_CTL_BIOS(HSW_DISP_PW_GLOBAL), D_BDW, > > NULL, > > - power_well_ctl_mmio_write); > > - MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL), D_BDW, > > NULL, > > - power_well_ctl_mmio_write); > > - MMIO_DH(HSW_PWR_WELL_CTL_KVMR, D_BDW, NULL, > > power_well_ctl_mmio_write); > > - MMIO_DH(HSW_PWR_WELL_CTL_DEBUG(HSW_DISP_PW_GLOBAL), D_BDW, > > NULL, > > - power_well_ctl_mmio_write); > > + MMIO_DH(HSW_PWR_WELL_CTL1, D_BDW, NULL, > > power_well_ctl_mmio_write); > > + MMIO_DH(HSW_PWR_WELL_CTL2, D_BDW, NULL, > > power_well_ctl_mmio_write); > > + MMIO_DH(HSW_PWR_WELL_CTL3, D_BDW, NULL, > > power_well_ctl_mmio_write); > > + MMIO_DH(HSW_PWR_WELL_CTL4, D_BDW, NULL, > > power_well_ctl_mmio_write); > > MMIO_DH(HSW_PWR_WELL_CTL5, D_BDW, NULL, > > power_well_ctl_mmio_write); > > MMIO_DH(HSW_PWR_WELL_CTL6, D_BDW, NULL, > > power_well_ctl_mmio_write); > > > > @@ -2804,13 +2797,8 @@ static int init_skl_mmio_info(struct intel_gvt > > *gvt) > > MMIO_F(_MMIO(_DPD_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_SKL_PLUS, > > NULL, > > dp_aux_ch_ctl_mmio_w > > rite); > > > > - /* > > - * Use an arbitrary power well controlled by the > > PWR_WELL_CTL > > - * register. > > - */ > > - MMIO_D(HSW_PWR_WELL_CTL_BIOS(SKL_DISP_PW_MISC_IO), > > D_SKL_PLUS); > > - MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(SKL_DISP_PW_MISC_IO), > > D_SKL_PLUS, NULL, > > - skl_power_well_ctl_write); > > + MMIO_D(HSW_PWR_WELL_CTL1, D_SKL_PLUS); > > + MMIO_DH(HSW_PWR_WELL_CTL2, D_SKL_PLUS, NULL, > > skl_power_well_ctl_write); > > > > MMIO_D(_MMIO(0xa210), D_SKL_PLUS); > > MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); > > diff --git a/drivers/gpu/drm/i915/i915_drv.h > > b/drivers/gpu/drm/i915/i915_drv.h > > index d31a8ef05d18..d73ce0a7b8f7 100644 > > --- a/drivers/gpu/drm/i915/i915_drv.h > > +++ b/drivers/gpu/drm/i915/i915_drv.h > > @@ -861,6 +861,13 @@ struct i915_power_well_ops { > > struct i915_power_well *power_well); > > }; > > > > +struct i915_power_well_regs { > > + i915_reg_t bios; > > + i915_reg_t driver; > > + i915_reg_t kvmr; > > + i915_reg_t debug; > > +}; > > + > > /* Power well structure for haswell */ > > struct i915_power_well_desc { > > const char *name; > > @@ -884,6 +891,12 @@ struct i915_power_well_desc { > > enum dpio_phy phy; > > } bxt; > > struct { > > + const struct i915_power_well_regs *regs; > > + /* > > + * request/status flag index in the power > > well > > + * constrol/status registers. > > + */ > > + u8 idx; > > /* Mask of pipes whose IRQ logic is backed > > by the pw */ > > u8 irq_pipe_mask; > > /* The pw is backing the VGA functionality > > */ > > diff --git a/drivers/gpu/drm/i915/i915_reg.h > > b/drivers/gpu/drm/i915/i915_reg.h > > index f76bb4f3c944..b7022fb8d524 100644 > > --- a/drivers/gpu/drm/i915/i915_reg.h > > +++ b/drivers/gpu/drm/i915/i915_reg.h > > @@ -8842,46 +8842,78 @@ enum { > > #define HSW_AUD_CHICKENBIT _MMIO(0x65f10) > > #define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15) > > > > -/* HSW Power Wells */ > > -#define _HSW_PWR_WELL_CTL1 0x45400 > > -#define _HSW_PWR_WELL_CTL2 0x45404 > > -#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 > > - * power well ID (see i915_power_well_id). There are 4 possible > > sources of > > - * power well requests each source having its own set of control > > registers: > > - * BIOS, DRIVER, KVMR, DEBUG. > > + * HSW-ICL power wells > > + * > > + * Platforms have up to 3 power well control register sets, each set > > + * controlling up to 16 power wells via a request/status HW flag > > tuple: > > + * - main (HSW_PWR_WELL_CTL[1-4]) > > + * - AUX (ICL_PWR_WELL_CTL_AUX[1-4]) > > + * - DDI (ICL_PWR_WELL_CTL_DDI[1-4]) > > + * Each control register set consists of up to 4 registers used by > > different > > + * sources that can request a power well to be enabled: > > + * - > > BIOS (HSW_PWR_WELL_CTL1/ICL_PWR_WELL_CTL_AUX1/ICL_PWR_WELL_CTL_DDI1 > > ) > > + * - DRIVER > > (HSW_PWR_WELL_CTL2/ICL_PWR_WELL_CTL_AUX2/ICL_PWR_WELL_CTL_DDI2) > > + * - KVMR (HSW_PWR_WELL_CTL3) (only in the main register set) > > + * - > > DEBUG (HSW_PWR_WELL_CTL4/ICL_PWR_WELL_CTL_AUX4/ICL_PWR_WELL_CTL_DDI4 > > ) > > */ > > -#define _HSW_PW_REG_IDX(pw) ((pw) >> 4) > > -#define _HSW_PW_SHIFT(pw) (((pw) & 0xf) * 2) > > -#define HSW_PWR_WELL_CTL_BIOS(pw) _MMIO(_PICK(_HSW_PW_REG_IDX > > (pw), \ > > - _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, \ > > - _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, \ > > - _ICL_PWR_WELL_CT > > L_AUX4, \ > > - _ICL_PWR_WELL_CT > > L_DDI4)) > > +#define HSW_PWR_WELL_CTL1 _MMIO(0x45400) > > +#define HSW_PWR_WELL_CTL2 _MMIO(0x45404) > > +#define HSW_PWR_WELL_CTL3 _MMIO(0x45408) > > +#define HSW_PWR_WELL_CTL4 _MMIO(0x4540C) > > +#define HSW_PWR_WELL_CTL_REQ(pw_idx) (0x2 << > > ((pw_idx) * 2)) > > +#define HSW_PWR_WELL_CTL_STATE(pw_idx) (0x1 << ((pw_idx) * > > 2)) > > > > -#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)) > > +/* HSW/BDW power well */ > > +#define HSW_PW_CTL_IDX_GLOBAL 15 > > + > > +/* SKL/BXT/GLK/CNL power wells */ > > +#define SKL_PW_CTL_IDX_PW_2 15 > > +#define SKL_PW_CTL_IDX_PW_1 14 > > +#define CNL_PW_CTL_IDX_AUX_F 12 > > +#define CNL_PW_CTL_IDX_AUX_D 11 > > +#define GLK_PW_CTL_IDX_AUX_C 10 > > +#define GLK_PW_CTL_IDX_AUX_B 9 > > +#define GLK_PW_CTL_IDX_AUX_A 8 > > +#define CNL_PW_CTL_IDX_DDI_F 6 > > +#define SKL_PW_CTL_IDX_DDI_D 4 > > +#define SKL_PW_CTL_IDX_DDI_C 3 > > +#define SKL_PW_CTL_IDX_DDI_B 2 > > +#define SKL_PW_CTL_IDX_DDI_A_E 1 > > +#define GLK_PW_CTL_IDX_DDI_A 1 > > +#define SKL_PW_CTL_IDX_MISC_IO 0 > > + > > +/* ICL- power wells */ > > Single nitpick for a big patch: my OCD tells me to put a space before > '-' or remove it completely because "ICL-" as is can be read as "ICL > and older" to the distracted reader. Ok. > > Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > > > > +#define ICL_PW_CTL_IDX_PW_4 3 > > +#define ICL_PW_CTL_IDX_PW_3 2 > > +#define ICL_PW_CTL_IDX_PW_2 1 > > +#define ICL_PW_CTL_IDX_PW_1 0 > > + > > +#define ICL_PWR_WELL_CTL_AUX1 _MMIO(0x45440) > > +#define ICL_PWR_WELL_CTL_AUX2 _MMIO(0x45444) > > +#define ICL_PWR_WELL_CTL_AUX4 _MMIO(0x4544C) > > +#define ICL_PW_CTL_IDX_AUX_TBT4 11 > > +#define ICL_PW_CTL_IDX_AUX_TBT3 10 > > +#define ICL_PW_CTL_IDX_AUX_TBT2 9 > > +#define ICL_PW_CTL_IDX_AUX_TBT1 8 > > +#define ICL_PW_CTL_IDX_AUX_F 5 > > +#define ICL_PW_CTL_IDX_AUX_E 4 > > +#define ICL_PW_CTL_IDX_AUX_D 3 > > +#define ICL_PW_CTL_IDX_AUX_C 2 > > +#define ICL_PW_CTL_IDX_AUX_B 1 > > +#define ICL_PW_CTL_IDX_AUX_A 0 > > + > > +#define ICL_PWR_WELL_CTL_DDI1 _MMIO(0x45450) > > +#define ICL_PWR_WELL_CTL_DDI2 _MMIO(0x45454) > > +#define ICL_PWR_WELL_CTL_DDI4 _MMIO(0x4545C) > > +#define ICL_PW_CTL_IDX_DDI_F 5 > > +#define ICL_PW_CTL_IDX_DDI_E 4 > > +#define ICL_PW_CTL_IDX_DDI_D 3 > > +#define ICL_PW_CTL_IDX_DDI_C 2 > > +#define ICL_PW_CTL_IDX_DDI_B 1 > > +#define ICL_PW_CTL_IDX_DDI_A 0 > > + > > +/* HSW- power well misc debug registers */ > > #define HSW_PWR_WELL_CTL5 _MMIO(0x45410) > > #define HSW_PWR_WELL_ENABLE_SINGLE_STEP (1 << 31) > > #define HSW_PWR_WELL_PWR_GATE_OVERRIDE (1 << 20) > > @@ -8897,18 +8929,26 @@ enum skl_power_gate { > > > > #define SKL_FUSE_STATUS _MMIO(0x42000 > > ) > > #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) > > +/* > > + * PG0 is HW controlled, so doesn't have a corresponding power well > > control knob > > + * SKL_DISP_PW1_IDX..SKL_DISP_PW2_IDX -> PG1..PG2 > > + */ > > +#define SKL_PW_CTL_IDX_TO_PG(pw_idx) \ > > + ((pw_idx) - SKL_PW_CTL_IDX_PW_1 + SKL_PG1) > > +/* > > + * PG0 is HW controlled, so doesn't have a corresponding power well > > control knob > > + * ICL_DISP_PW1_IDX..ICL_DISP_PW4_IDX -> PG1..PG4 > > + */ > > +#define ICL_PW_CTL_IDX_TO_PG(pw_idx) \ > > + ((pw_idx) - ICL_PW_CTL_IDX_PW_1 + SKL_PG1) > > #define SKL_FUSE_PG_DIST_STATUS(pg) (1 << (27 - > > (pg))) > > > > -#define _CNL_AUX_REG_IDX(pw) ((pw) - 9) > > +#define _CNL_AUX_REG_IDX(pw_idx) ((pw_idx) - > > GLK_PW_CTL_IDX_AUX_B) > > #define _CNL_AUX_ANAOVRD1_B 0x162250 > > #define _CNL_AUX_ANAOVRD1_C 0x162210 > > #define _CNL_AUX_ANAOVRD1_D 0x1622D0 > > #define _CNL_AUX_ANAOVRD1_F 0x162A90 > > -#define CNL_AUX_ANAOVRD1(pw) _MMIO(_PICK(_CNL_AUX_REG > > _IDX(pw), \ > > +#define CNL_AUX_ANAOVRD1(pw_idx) _MMIO(_PICK(_CNL_AUX_REG_IDX > > (pw_idx), \ > > _CNL_AUX_ANAOVRD > > 1_B, \ > > _CNL_AUX_ANAOVRD > > 1_C, \ > > _CNL_AUX_ANAOVRD > > 1_D, \ > > diff --git a/drivers/gpu/drm/i915/intel_display.c > > b/drivers/gpu/drm/i915/intel_display.c > > index 87e4cfbfd096..640ec5df4d62 100644 > > --- a/drivers/gpu/drm/i915/intel_display.c > > +++ b/drivers/gpu/drm/i915/intel_display.c > > @@ -8973,7 +8973,7 @@ static void assert_can_disable_lcpll(struct > > drm_i915_private *dev_priv) > > I915_STATE_WARN(crtc->active, "CRTC for pipe %c > > enabled\n", > > pipe_name(crtc->pipe)); > > > > - I915_STATE_WARN(I915_READ(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_P > > W_GLOBAL)), > > + I915_STATE_WARN(I915_READ(HSW_PWR_WELL_CTL2), > > "Display power well on\n"); > > I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL > > enabled\n"); > > I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, > > "WRPLL1 enabled\n"); > > @@ -16052,8 +16052,7 @@ intel_display_capture_error_state(struct > > drm_i915_private *dev_priv) > > return NULL; > > > > if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) > > - error->power_well_driver = > > - I915_READ(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_P > > W_GLOBAL)); > > + error->power_well_driver = > > I915_READ(HSW_PWR_WELL_CTL2); > > > > for_each_pipe(dev_priv, i) { > > error->pipe[i].power_domain_on = > > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c > > b/drivers/gpu/drm/i915/intel_runtime_pm.c > > index 05d8cdab08cc..5527504d664f 100644 > > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c > > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c > > @@ -323,26 +323,29 @@ static void hsw_power_well_pre_disable(struct > > drm_i915_private *dev_priv, > > static void hsw_wait_for_power_well_enable(struct drm_i915_private > > *dev_priv, > > struct i915_power_well > > *power_well) > > { > > - enum i915_power_well_id id = power_well->desc->id; > > + const struct i915_power_well_regs *regs = power_well->desc- > > >hsw.regs; > > + int pw_idx = power_well->desc->hsw.idx; > > > > /* Timeout for PW1:10 us, AUX:not specified, other PWs:20 > > us. */ > > WARN_ON(intel_wait_for_register(dev_priv, > > - HSW_PWR_WELL_CTL_DRIVER(id), > > - HSW_PWR_WELL_CTL_STATE(id), > > - HSW_PWR_WELL_CTL_STATE(id), > > + regs->driver, > > + HSW_PWR_WELL_CTL_STATE(pw_id > > x), > > + HSW_PWR_WELL_CTL_STATE(pw_id > > x), > > 1)); > > } > > > > static u32 hsw_power_well_requesters(struct drm_i915_private > > *dev_priv, > > - enum i915_power_well_id id) > > + const struct > > i915_power_well_regs *regs, > > + int pw_idx) > > { > > - u32 req_mask = HSW_PWR_WELL_CTL_REQ(id); > > + u32 req_mask = HSW_PWR_WELL_CTL_REQ(pw_idx); > > u32 ret; > > > > - ret = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)) & req_mask ? 1 : > > 0; > > - ret |= I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & req_mask ? 2 > > : 0; > > - ret |= I915_READ(HSW_PWR_WELL_CTL_KVMR) & req_mask ? 4 : 0; > > - ret |= I915_READ(HSW_PWR_WELL_CTL_DEBUG(id)) & req_mask ? 8 > > : 0; > > + ret = I915_READ(regs->bios) & req_mask ? 1 : 0; > > + ret |= I915_READ(regs->driver) & req_mask ? 2 : 0; > > + if (regs->kvmr.reg) > > + ret |= I915_READ(regs->kvmr) & req_mask ? 4 : 0; > > + ret |= I915_READ(regs->debug) & req_mask ? 8 : 0; > > > > return ret; > > } > > @@ -350,7 +353,8 @@ static u32 hsw_power_well_requesters(struct > > drm_i915_private *dev_priv, > > static void hsw_wait_for_power_well_disable(struct drm_i915_private > > *dev_priv, > > struct i915_power_well > > *power_well) > > { > > - enum i915_power_well_id id = power_well->desc->id; > > + const struct i915_power_well_regs *regs = power_well->desc- > > >hsw.regs; > > + int pw_idx = power_well->desc->hsw.idx; > > bool disabled; > > u32 reqs; > > > > @@ -363,9 +367,9 @@ static void > > hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, > > * Skip the wait in case any of the request bits are set and > > print a > > * diagnostic message. > > */ > > - wait_for((disabled = > > !(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & > > - HSW_PWR_WELL_CTL_STATE(id))) || > > - (reqs = hsw_power_well_requesters(dev_priv, id)), > > 1); > > + wait_for((disabled = !(I915_READ(regs->driver) & > > + HSW_PWR_WELL_CTL_STATE(pw_idx))) || > > + (reqs = hsw_power_well_requesters(dev_priv, regs, > > pw_idx)), 1); > > if (disabled) > > return; > > > > @@ -386,14 +390,15 @@ static void > > gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv, > > static void hsw_power_well_enable(struct drm_i915_private *dev_priv, > > struct i915_power_well > > *power_well) > > { > > - enum i915_power_well_id id = power_well->desc->id; > > + const struct i915_power_well_regs *regs = power_well->desc- > > >hsw.regs; > > + int pw_idx = power_well->desc->hsw.idx; > > bool wait_fuses = power_well->desc->hsw.has_fuses; > > enum skl_power_gate uninitialized_var(pg); > > u32 val; > > > > if (wait_fuses) { > > - pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_TO_PG(id) : > > - SKL_PW_TO_PG(id); > > + pg = INTEL_GEN(dev_priv) >= 11 ? > > ICL_PW_CTL_IDX_TO_PG(pw_idx) : > > + SKL_PW_CTL_IDX_TO_P > > G(pw_idx); > > /* > > * For PW1 we have to wait both for the PW0/PG0 fuse > > state > > * before enabling the power well and PW1/PG1's own > > fuse > > @@ -405,17 +410,17 @@ static void hsw_power_well_enable(struct > > drm_i915_private *dev_priv, > > gen9_wait_for_power_well_fuses(dev_priv, > > SKL_PG0); > > } > > > > - 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(regs->driver); > > + I915_WRITE(regs->driver, val | > > HSW_PWR_WELL_CTL_REQ(pw_idx)); > > hsw_wait_for_power_well_enable(dev_priv, power_well); > > > > /* Display WA #1178: cnl */ > > if (IS_CANNONLAKE(dev_priv) && > > - (id == CNL_DISP_PW_AUX_B || id == CNL_DISP_PW_AUX_C || > > - id == CNL_DISP_PW_AUX_D || id == CNL_DISP_PW_AUX_F)) { > > - val = I915_READ(CNL_AUX_ANAOVRD1(id)); > > + pw_idx >= GLK_PW_CTL_IDX_AUX_B && > > + pw_idx <= CNL_PW_CTL_IDX_AUX_F) { > > + val = I915_READ(CNL_AUX_ANAOVRD1(pw_idx)); > > val |= CNL_AUX_ANAOVRD1_ENABLE | > > CNL_AUX_ANAOVRD1_LDO_BYPASS; > > - I915_WRITE(CNL_AUX_ANAOVRD1(id), val); > > + I915_WRITE(CNL_AUX_ANAOVRD1(pw_idx), val); > > } > > > > if (wait_fuses) > > @@ -429,30 +434,31 @@ static void hsw_power_well_enable(struct > > drm_i915_private *dev_priv, > > static void hsw_power_well_disable(struct drm_i915_private > > *dev_priv, > > struct i915_power_well > > *power_well) > > { > > - enum i915_power_well_id id = power_well->desc->id; > > + const struct i915_power_well_regs *regs = power_well->desc- > > >hsw.regs; > > + int pw_idx = power_well->desc->hsw.idx; > > u32 val; > > > > hsw_power_well_pre_disable(dev_priv, > > power_well->desc- > > >hsw.irq_pipe_mask); > > > > - 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(regs->driver); > > + I915_WRITE(regs->driver, val & > > ~HSW_PWR_WELL_CTL_REQ(pw_idx)); > > hsw_wait_for_power_well_disable(dev_priv, power_well); > > } > > > > -#define ICL_AUX_PW_TO_PORT(pw) ((pw) - ICL_DISP_PW_AUX_A) > > +#define ICL_AUX_PW_TO_PORT(pw_idx) ((pw_idx) - > > ICL_PW_CTL_IDX_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->desc->id; > > - enum port port = ICL_AUX_PW_TO_PORT(id); > > + const struct i915_power_well_regs *regs = power_well->desc- > > >hsw.regs; > > + int pw_idx = power_well->desc->hsw.idx; > > + enum port port = ICL_AUX_PW_TO_PORT(pw_idx); > > 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(regs->driver); > > + I915_WRITE(regs->driver, val | > > HSW_PWR_WELL_CTL_REQ(pw_idx)); > > > > val = I915_READ(ICL_PORT_CL_DW12(port)); > > I915_WRITE(ICL_PORT_CL_DW12(port), val | > > ICL_LANE_ENABLE_AUX); > > @@ -464,16 +470,16 @@ 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->desc->id; > > - enum port port = ICL_AUX_PW_TO_PORT(id); > > + const struct i915_power_well_regs *regs = power_well->desc- > > >hsw.regs; > > + int pw_idx = power_well->desc->hsw.idx; > > + enum port port = ICL_AUX_PW_TO_PORT(pw_idx); > > 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)); > > + val = I915_READ(regs->driver); > > + I915_WRITE(regs->driver, val & > > ~HSW_PWR_WELL_CTL_REQ(pw_idx)); > > > > hsw_wait_for_power_well_disable(dev_priv, power_well); > > } > > @@ -486,22 +492,22 @@ icl_combo_phy_aux_power_well_disable(struct > > drm_i915_private *dev_priv, > > static bool hsw_power_well_enabled(struct drm_i915_private > > *dev_priv, > > struct i915_power_well > > *power_well) > > { > > - enum i915_power_well_id id = power_well->desc->id; > > - u32 mask = HSW_PWR_WELL_CTL_REQ(id) | > > HSW_PWR_WELL_CTL_STATE(id); > > + const struct i915_power_well_regs *regs = power_well->desc- > > >hsw.regs; > > + int pw_idx = power_well->desc->hsw.idx; > > + u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx) | > > + HSW_PWR_WELL_CTL_STATE(pw_idx); > > > > - return (I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & mask) == > > mask; > > + return (I915_READ(regs->driver) & mask) == mask; > > } > > > > static void assert_can_enable_dc9(struct drm_i915_private *dev_priv) > > { > > - enum i915_power_well_id id = SKL_DISP_PW_2; > > - > > WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9), > > "DC9 already programmed to be enabled.\n"); > > WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5, > > "DC5 still not disabled to enable DC9.\n"); > > - WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & > > - HSW_PWR_WELL_CTL_REQ(id), > > + WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL2) & > > + HSW_PWR_WELL_CTL_REQ(SKL_PW_CTL_IDX_PW_2), > > "Power well 2 on.\n"); > > WARN_ONCE(intel_irqs_enabled(dev_priv), > > "Interrupts not disabled yet.\n"); > > @@ -725,17 +731,18 @@ static void skl_enable_dc6(struct > > drm_i915_private *dev_priv) > > static void hsw_power_well_sync_hw(struct drm_i915_private > > *dev_priv, > > struct i915_power_well > > *power_well) > > { > > - enum i915_power_well_id id = power_well->desc->id; > > - u32 mask = HSW_PWR_WELL_CTL_REQ(id); > > - u32 bios_req = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)); > > + const struct i915_power_well_regs *regs = power_well->desc- > > >hsw.regs; > > + int pw_idx = power_well->desc->hsw.idx; > > + u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx); > > + u32 bios_req = I915_READ(regs->bios); > > > > /* Take over the request bit if set by BIOS. */ > > if (bios_req & mask) { > > - u32 drv_req = > > I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)); > > + u32 drv_req = I915_READ(regs->driver); > > > > if (!(drv_req & mask)) > > - I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), > > drv_req | mask); > > - I915_WRITE(HSW_PWR_WELL_CTL_BIOS(id), bios_req & > > ~mask); > > + I915_WRITE(regs->driver, drv_req | mask); > > + I915_WRITE(regs->bios, bios_req & ~mask); > > } > > } > > > > @@ -2108,6 +2115,13 @@ static const struct i915_power_well_ops > > bxt_dpio_cmn_power_well_ops = { > > .is_enabled = bxt_dpio_cmn_power_well_enabled, > > }; > > > > +static const struct i915_power_well_regs hsw_power_well_regs = { > > + .bios = HSW_PWR_WELL_CTL1, > > + .driver = HSW_PWR_WELL_CTL2, > > + .kvmr = HSW_PWR_WELL_CTL3, > > + .debug = HSW_PWR_WELL_CTL4, > > +}; > > + > > static const struct i915_power_well_desc hsw_power_wells[] = { > > { > > .name = "always-on", > > @@ -2122,6 +2136,8 @@ static const struct i915_power_well_desc > > hsw_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = HSW_DISP_PW_GLOBAL, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, > > .hsw.has_vga = true, > > }, > > }, > > @@ -2141,6 +2157,8 @@ static const struct i915_power_well_desc > > bdw_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = HSW_DISP_PW_GLOBAL, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, > > .hsw.irq_pipe_mask = BIT(PIPE_B) | > > BIT(PIPE_C), > > .hsw.has_vga = true, > > }, > > @@ -2310,6 +2328,8 @@ static const struct i915_power_well_desc > > skl_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_1, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_PW_1, > > .hsw.has_fuses = true, > > }, > > }, > > @@ -2319,6 +2339,10 @@ static const struct i915_power_well_desc > > skl_power_wells[] = { > > .domains = 0, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_MISC_IO, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_MISC_IO, > > + }, > > }, > > { > > .name = "DC off", > > @@ -2332,6 +2356,8 @@ static const struct i915_power_well_desc > > skl_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_2, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_PW_2, > > .hsw.irq_pipe_mask = BIT(PIPE_B) | > > BIT(PIPE_C), > > .hsw.has_vga = true, > > .hsw.has_fuses = true, > > @@ -2342,24 +2368,40 @@ static const struct i915_power_well_desc > > skl_power_wells[] = { > > .domains = SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_A_E, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_A_E, > > + }, > > }, > > { > > .name = "DDI B IO power well", > > .domains = SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_B, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, > > + }, > > }, > > { > > .name = "DDI C IO power well", > > .domains = SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_C, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, > > + }, > > }, > > { > > .name = "DDI D IO power well", > > .domains = SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_D, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_D, > > + }, > > }, > > }; > > > > @@ -2377,6 +2419,8 @@ static const struct i915_power_well_desc > > bxt_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_1, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_PW_1, > > .hsw.has_fuses = true, > > }, > > }, > > @@ -2392,6 +2436,8 @@ static const struct i915_power_well_desc > > bxt_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_2, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_PW_2, > > .hsw.irq_pipe_mask = BIT(PIPE_B) | > > BIT(PIPE_C), > > .hsw.has_vga = true, > > .hsw.has_fuses = true, > > @@ -2432,6 +2478,8 @@ static const struct i915_power_well_desc > > glk_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_1, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_PW_1, > > .hsw.has_fuses = true, > > }, > > }, > > @@ -2447,6 +2495,8 @@ static const struct i915_power_well_desc > > glk_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_2, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_PW_2, > > .hsw.irq_pipe_mask = BIT(PIPE_B) | > > BIT(PIPE_C), > > .hsw.has_vga = true, > > .hsw.has_fuses = true, > > @@ -2484,36 +2534,60 @@ static const struct i915_power_well_desc > > glk_power_wells[] = { > > .domains = GLK_DISPLAY_AUX_A_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = GLK_DISP_PW_AUX_A, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = GLK_PW_CTL_IDX_AUX_A, > > + }, > > }, > > { > > .name = "AUX B", > > .domains = GLK_DISPLAY_AUX_B_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = GLK_DISP_PW_AUX_B, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = GLK_PW_CTL_IDX_AUX_B, > > + }, > > }, > > { > > .name = "AUX C", > > .domains = GLK_DISPLAY_AUX_C_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = GLK_DISP_PW_AUX_C, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = GLK_PW_CTL_IDX_AUX_C, > > + }, > > }, > > { > > .name = "DDI A IO power well", > > .domains = GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = GLK_DISP_PW_DDI_A, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = GLK_PW_CTL_IDX_DDI_A, > > + }, > > }, > > { > > .name = "DDI B IO power well", > > .domains = GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_B, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, > > + }, > > }, > > { > > .name = "DDI C IO power well", > > .domains = GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_C, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, > > + }, > > }, > > }; > > > > @@ -2532,6 +2606,8 @@ static const struct i915_power_well_desc > > cnl_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_1, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_PW_1, > > .hsw.has_fuses = true, > > }, > > }, > > @@ -2540,24 +2616,40 @@ static const struct i915_power_well_desc > > cnl_power_wells[] = { > > .domains = CNL_DISPLAY_AUX_A_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = CNL_DISP_PW_AUX_A, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = GLK_PW_CTL_IDX_AUX_A, > > + }, > > }, > > { > > .name = "AUX B", > > .domains = CNL_DISPLAY_AUX_B_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = CNL_DISP_PW_AUX_B, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = GLK_PW_CTL_IDX_AUX_B, > > + }, > > }, > > { > > .name = "AUX C", > > .domains = CNL_DISPLAY_AUX_C_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = CNL_DISP_PW_AUX_C, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = GLK_PW_CTL_IDX_AUX_C, > > + }, > > }, > > { > > .name = "AUX D", > > .domains = CNL_DISPLAY_AUX_D_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = CNL_DISP_PW_AUX_D, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = CNL_PW_CTL_IDX_AUX_D, > > + }, > > }, > > { > > .name = "DC off", > > @@ -2571,6 +2663,8 @@ static const struct i915_power_well_desc > > cnl_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_2, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_PW_2, > > .hsw.irq_pipe_mask = BIT(PIPE_B) | > > BIT(PIPE_C), > > .hsw.has_vga = true, > > .hsw.has_fuses = true, > > @@ -2581,36 +2675,60 @@ static const struct i915_power_well_desc > > cnl_power_wells[] = { > > .domains = CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = CNL_DISP_PW_DDI_A, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = GLK_PW_CTL_IDX_DDI_A, > > + }, > > }, > > { > > .name = "DDI B IO power well", > > .domains = CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_B, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, > > + }, > > }, > > { > > .name = "DDI C IO power well", > > .domains = CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_C, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, > > + }, > > }, > > { > > .name = "DDI D IO power well", > > .domains = CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = SKL_DISP_PW_DDI_D, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = SKL_PW_CTL_IDX_DDI_D, > > + }, > > }, > > { > > .name = "DDI F IO power well", > > .domains = CNL_DISPLAY_DDI_F_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = CNL_DISP_PW_DDI_F, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = CNL_PW_CTL_IDX_DDI_F, > > + }, > > }, > > { > > .name = "AUX F", > > .domains = CNL_DISPLAY_AUX_F_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = CNL_DISP_PW_AUX_F, > > + { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = CNL_PW_CTL_IDX_AUX_F, > > + }, > > }, > > }; > > > > @@ -2621,6 +2739,18 @@ static const struct i915_power_well_ops > > icl_combo_phy_aux_power_well_ops = { > > .is_enabled = hsw_power_well_enabled, > > }; > > > > +static const struct i915_power_well_regs icl_aux_power_well_regs = { > > + .bios = ICL_PWR_WELL_CTL_AUX1, > > + .driver = ICL_PWR_WELL_CTL_AUX2, > > + .debug = ICL_PWR_WELL_CTL_AUX4, > > +}; > > + > > +static const struct i915_power_well_regs icl_ddi_power_well_regs = { > > + .bios = ICL_PWR_WELL_CTL_DDI1, > > + .driver = ICL_PWR_WELL_CTL_DDI2, > > + .debug = ICL_PWR_WELL_CTL_DDI4, > > +}; > > + > > static const struct i915_power_well_desc icl_power_wells[] = { > > { > > .name = "always-on", > > @@ -2636,6 +2766,8 @@ static const struct i915_power_well_desc > > icl_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_1, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_PW_1, > > .hsw.has_fuses = true, > > }, > > }, > > @@ -2645,6 +2777,8 @@ static const struct i915_power_well_desc > > icl_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_2, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_PW_2, > > .hsw.has_fuses = true, > > }, > > }, > > @@ -2660,6 +2794,8 @@ static const struct i915_power_well_desc > > icl_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_3, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_PW_3, > > .hsw.irq_pipe_mask = BIT(PIPE_B), > > .hsw.has_vga = true, > > .hsw.has_fuses = true, > > @@ -2670,96 +2806,160 @@ static const struct i915_power_well_desc > > icl_power_wells[] = { > > .domains = ICL_DDI_IO_A_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_DDI_A, > > + { > > + .hsw.regs = &icl_ddi_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_DDI_A, > > + }, > > }, > > { > > .name = "DDI B IO", > > .domains = ICL_DDI_IO_B_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_DDI_B, > > + { > > + .hsw.regs = &icl_ddi_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_DDI_B, > > + }, > > }, > > { > > .name = "DDI C IO", > > .domains = ICL_DDI_IO_C_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_DDI_C, > > + { > > + .hsw.regs = &icl_ddi_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_DDI_C, > > + }, > > }, > > { > > .name = "DDI D IO", > > .domains = ICL_DDI_IO_D_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_DDI_D, > > + { > > + .hsw.regs = &icl_ddi_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_DDI_D, > > + }, > > }, > > { > > .name = "DDI E IO", > > .domains = ICL_DDI_IO_E_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_DDI_E, > > + { > > + .hsw.regs = &icl_ddi_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_DDI_E, > > + }, > > }, > > { > > .name = "DDI F IO", > > .domains = ICL_DDI_IO_F_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_DDI_F, > > + { > > + .hsw.regs = &icl_ddi_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_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, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_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, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_B, > > + }, > > }, > > { > > .name = "AUX C", > > .domains = ICL_AUX_C_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_AUX_C, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_C, > > + }, > > }, > > { > > .name = "AUX D", > > .domains = ICL_AUX_D_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_AUX_D, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_D, > > + }, > > }, > > { > > .name = "AUX E", > > .domains = ICL_AUX_E_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_AUX_E, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_E, > > + }, > > }, > > { > > .name = "AUX F", > > .domains = ICL_AUX_F_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_AUX_F, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_F, > > + }, > > }, > > { > > .name = "AUX TBT1", > > .domains = ICL_AUX_TBT1_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_AUX_TBT1, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT1, > > + }, > > }, > > { > > .name = "AUX TBT2", > > .domains = ICL_AUX_TBT2_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_AUX_TBT2, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT2, > > + }, > > }, > > { > > .name = "AUX TBT3", > > .domains = ICL_AUX_TBT3_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_AUX_TBT3, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT3, > > + }, > > }, > > { > > .name = "AUX TBT4", > > .domains = ICL_AUX_TBT4_IO_POWER_DOMAINS, > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_AUX_TBT4, > > + { > > + .hsw.regs = &icl_aux_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT4, > > + }, > > }, > > { > > .name = "power well 4", > > @@ -2767,6 +2967,8 @@ static const struct i915_power_well_desc > > icl_power_wells[] = { > > .ops = &hsw_power_well_ops, > > .id = ICL_DISP_PW_4, > > { > > + .hsw.regs = &hsw_power_well_regs, > > + .hsw.idx = ICL_PW_CTL_IDX_PW_4, > > .hsw.has_fuses = true, > > .hsw.irq_pipe_mask = BIT(PIPE_C), > > },
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 7a58ca555197..79e748569d31 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1287,12 +1287,12 @@ static int power_well_ctl_mmio_write(struct intel_vgpu *vgpu, { write_vreg(vgpu, offset, p_data, bytes); - if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_CTL_REQ(HSW_DISP_PW_GLOBAL)) + if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_CTL_REQ(HSW_PW_CTL_IDX_GLOBAL)) vgpu_vreg(vgpu, offset) |= - HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL); + HSW_PWR_WELL_CTL_STATE(HSW_PW_CTL_IDX_GLOBAL); else vgpu_vreg(vgpu, offset) &= - ~HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL); + ~HSW_PWR_WELL_CTL_STATE(HSW_PW_CTL_IDX_GLOBAL); return 0; } @@ -2443,17 +2443,10 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL); MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL); MMIO_D(GEN6_PMINTRMSK, D_ALL); - /* - * Use an arbitrary power well controlled by the PWR_WELL_CTL - * register. - */ - MMIO_DH(HSW_PWR_WELL_CTL_BIOS(HSW_DISP_PW_GLOBAL), D_BDW, NULL, - power_well_ctl_mmio_write); - MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL), D_BDW, NULL, - power_well_ctl_mmio_write); - MMIO_DH(HSW_PWR_WELL_CTL_KVMR, D_BDW, NULL, power_well_ctl_mmio_write); - MMIO_DH(HSW_PWR_WELL_CTL_DEBUG(HSW_DISP_PW_GLOBAL), D_BDW, NULL, - power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_CTL1, D_BDW, NULL, power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_CTL2, D_BDW, NULL, power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_CTL3, D_BDW, NULL, power_well_ctl_mmio_write); + MMIO_DH(HSW_PWR_WELL_CTL4, D_BDW, NULL, power_well_ctl_mmio_write); MMIO_DH(HSW_PWR_WELL_CTL5, D_BDW, NULL, power_well_ctl_mmio_write); MMIO_DH(HSW_PWR_WELL_CTL6, D_BDW, NULL, power_well_ctl_mmio_write); @@ -2804,13 +2797,8 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_F(_MMIO(_DPD_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL, dp_aux_ch_ctl_mmio_write); - /* - * Use an arbitrary power well controlled by the PWR_WELL_CTL - * register. - */ - MMIO_D(HSW_PWR_WELL_CTL_BIOS(SKL_DISP_PW_MISC_IO), D_SKL_PLUS); - MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(SKL_DISP_PW_MISC_IO), D_SKL_PLUS, NULL, - skl_power_well_ctl_write); + MMIO_D(HSW_PWR_WELL_CTL1, D_SKL_PLUS); + MMIO_DH(HSW_PWR_WELL_CTL2, D_SKL_PLUS, NULL, skl_power_well_ctl_write); MMIO_D(_MMIO(0xa210), D_SKL_PLUS); MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d31a8ef05d18..d73ce0a7b8f7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -861,6 +861,13 @@ struct i915_power_well_ops { struct i915_power_well *power_well); }; +struct i915_power_well_regs { + i915_reg_t bios; + i915_reg_t driver; + i915_reg_t kvmr; + i915_reg_t debug; +}; + /* Power well structure for haswell */ struct i915_power_well_desc { const char *name; @@ -884,6 +891,12 @@ struct i915_power_well_desc { enum dpio_phy phy; } bxt; struct { + const struct i915_power_well_regs *regs; + /* + * request/status flag index in the power well + * constrol/status registers. + */ + u8 idx; /* Mask of pipes whose IRQ logic is backed by the pw */ u8 irq_pipe_mask; /* The pw is backing the VGA functionality */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f76bb4f3c944..b7022fb8d524 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8842,46 +8842,78 @@ enum { #define HSW_AUD_CHICKENBIT _MMIO(0x65f10) #define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15) -/* HSW Power Wells */ -#define _HSW_PWR_WELL_CTL1 0x45400 -#define _HSW_PWR_WELL_CTL2 0x45404 -#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 - * power well ID (see i915_power_well_id). There are 4 possible sources of - * power well requests each source having its own set of control registers: - * BIOS, DRIVER, KVMR, DEBUG. + * HSW-ICL power wells + * + * Platforms have up to 3 power well control register sets, each set + * controlling up to 16 power wells via a request/status HW flag tuple: + * - main (HSW_PWR_WELL_CTL[1-4]) + * - AUX (ICL_PWR_WELL_CTL_AUX[1-4]) + * - DDI (ICL_PWR_WELL_CTL_DDI[1-4]) + * Each control register set consists of up to 4 registers used by different + * sources that can request a power well to be enabled: + * - BIOS (HSW_PWR_WELL_CTL1/ICL_PWR_WELL_CTL_AUX1/ICL_PWR_WELL_CTL_DDI1) + * - DRIVER (HSW_PWR_WELL_CTL2/ICL_PWR_WELL_CTL_AUX2/ICL_PWR_WELL_CTL_DDI2) + * - KVMR (HSW_PWR_WELL_CTL3) (only in the main register set) + * - DEBUG (HSW_PWR_WELL_CTL4/ICL_PWR_WELL_CTL_AUX4/ICL_PWR_WELL_CTL_DDI4) */ -#define _HSW_PW_REG_IDX(pw) ((pw) >> 4) -#define _HSW_PW_SHIFT(pw) (((pw) & 0xf) * 2) -#define HSW_PWR_WELL_CTL_BIOS(pw) _MMIO(_PICK(_HSW_PW_REG_IDX(pw), \ - _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, \ - _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, \ - _ICL_PWR_WELL_CTL_AUX4, \ - _ICL_PWR_WELL_CTL_DDI4)) +#define HSW_PWR_WELL_CTL1 _MMIO(0x45400) +#define HSW_PWR_WELL_CTL2 _MMIO(0x45404) +#define HSW_PWR_WELL_CTL3 _MMIO(0x45408) +#define HSW_PWR_WELL_CTL4 _MMIO(0x4540C) +#define HSW_PWR_WELL_CTL_REQ(pw_idx) (0x2 << ((pw_idx) * 2)) +#define HSW_PWR_WELL_CTL_STATE(pw_idx) (0x1 << ((pw_idx) * 2)) -#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)) +/* HSW/BDW power well */ +#define HSW_PW_CTL_IDX_GLOBAL 15 + +/* SKL/BXT/GLK/CNL power wells */ +#define SKL_PW_CTL_IDX_PW_2 15 +#define SKL_PW_CTL_IDX_PW_1 14 +#define CNL_PW_CTL_IDX_AUX_F 12 +#define CNL_PW_CTL_IDX_AUX_D 11 +#define GLK_PW_CTL_IDX_AUX_C 10 +#define GLK_PW_CTL_IDX_AUX_B 9 +#define GLK_PW_CTL_IDX_AUX_A 8 +#define CNL_PW_CTL_IDX_DDI_F 6 +#define SKL_PW_CTL_IDX_DDI_D 4 +#define SKL_PW_CTL_IDX_DDI_C 3 +#define SKL_PW_CTL_IDX_DDI_B 2 +#define SKL_PW_CTL_IDX_DDI_A_E 1 +#define GLK_PW_CTL_IDX_DDI_A 1 +#define SKL_PW_CTL_IDX_MISC_IO 0 + +/* ICL- power wells */ +#define ICL_PW_CTL_IDX_PW_4 3 +#define ICL_PW_CTL_IDX_PW_3 2 +#define ICL_PW_CTL_IDX_PW_2 1 +#define ICL_PW_CTL_IDX_PW_1 0 + +#define ICL_PWR_WELL_CTL_AUX1 _MMIO(0x45440) +#define ICL_PWR_WELL_CTL_AUX2 _MMIO(0x45444) +#define ICL_PWR_WELL_CTL_AUX4 _MMIO(0x4544C) +#define ICL_PW_CTL_IDX_AUX_TBT4 11 +#define ICL_PW_CTL_IDX_AUX_TBT3 10 +#define ICL_PW_CTL_IDX_AUX_TBT2 9 +#define ICL_PW_CTL_IDX_AUX_TBT1 8 +#define ICL_PW_CTL_IDX_AUX_F 5 +#define ICL_PW_CTL_IDX_AUX_E 4 +#define ICL_PW_CTL_IDX_AUX_D 3 +#define ICL_PW_CTL_IDX_AUX_C 2 +#define ICL_PW_CTL_IDX_AUX_B 1 +#define ICL_PW_CTL_IDX_AUX_A 0 + +#define ICL_PWR_WELL_CTL_DDI1 _MMIO(0x45450) +#define ICL_PWR_WELL_CTL_DDI2 _MMIO(0x45454) +#define ICL_PWR_WELL_CTL_DDI4 _MMIO(0x4545C) +#define ICL_PW_CTL_IDX_DDI_F 5 +#define ICL_PW_CTL_IDX_DDI_E 4 +#define ICL_PW_CTL_IDX_DDI_D 3 +#define ICL_PW_CTL_IDX_DDI_C 2 +#define ICL_PW_CTL_IDX_DDI_B 1 +#define ICL_PW_CTL_IDX_DDI_A 0 + +/* HSW- power well misc debug registers */ #define HSW_PWR_WELL_CTL5 _MMIO(0x45410) #define HSW_PWR_WELL_ENABLE_SINGLE_STEP (1 << 31) #define HSW_PWR_WELL_PWR_GATE_OVERRIDE (1 << 20) @@ -8897,18 +8929,26 @@ enum skl_power_gate { #define SKL_FUSE_STATUS _MMIO(0x42000) #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) +/* + * PG0 is HW controlled, so doesn't have a corresponding power well control knob + * SKL_DISP_PW1_IDX..SKL_DISP_PW2_IDX -> PG1..PG2 + */ +#define SKL_PW_CTL_IDX_TO_PG(pw_idx) \ + ((pw_idx) - SKL_PW_CTL_IDX_PW_1 + SKL_PG1) +/* + * PG0 is HW controlled, so doesn't have a corresponding power well control knob + * ICL_DISP_PW1_IDX..ICL_DISP_PW4_IDX -> PG1..PG4 + */ +#define ICL_PW_CTL_IDX_TO_PG(pw_idx) \ + ((pw_idx) - ICL_PW_CTL_IDX_PW_1 + SKL_PG1) #define SKL_FUSE_PG_DIST_STATUS(pg) (1 << (27 - (pg))) -#define _CNL_AUX_REG_IDX(pw) ((pw) - 9) +#define _CNL_AUX_REG_IDX(pw_idx) ((pw_idx) - GLK_PW_CTL_IDX_AUX_B) #define _CNL_AUX_ANAOVRD1_B 0x162250 #define _CNL_AUX_ANAOVRD1_C 0x162210 #define _CNL_AUX_ANAOVRD1_D 0x1622D0 #define _CNL_AUX_ANAOVRD1_F 0x162A90 -#define CNL_AUX_ANAOVRD1(pw) _MMIO(_PICK(_CNL_AUX_REG_IDX(pw), \ +#define CNL_AUX_ANAOVRD1(pw_idx) _MMIO(_PICK(_CNL_AUX_REG_IDX(pw_idx), \ _CNL_AUX_ANAOVRD1_B, \ _CNL_AUX_ANAOVRD1_C, \ _CNL_AUX_ANAOVRD1_D, \ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 87e4cfbfd096..640ec5df4d62 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8973,7 +8973,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); - I915_STATE_WARN(I915_READ(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL)), + I915_STATE_WARN(I915_READ(HSW_PWR_WELL_CTL2), "Display power well on\n"); I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n"); I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n"); @@ -16052,8 +16052,7 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv) return NULL; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) - error->power_well_driver = - I915_READ(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL)); + error->power_well_driver = I915_READ(HSW_PWR_WELL_CTL2); for_each_pipe(dev_priv, i) { error->pipe[i].power_domain_on = diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 05d8cdab08cc..5527504d664f 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -323,26 +323,29 @@ static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv, static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum i915_power_well_id id = power_well->desc->id; + const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + int pw_idx = power_well->desc->hsw.idx; /* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */ WARN_ON(intel_wait_for_register(dev_priv, - HSW_PWR_WELL_CTL_DRIVER(id), - HSW_PWR_WELL_CTL_STATE(id), - HSW_PWR_WELL_CTL_STATE(id), + regs->driver, + HSW_PWR_WELL_CTL_STATE(pw_idx), + HSW_PWR_WELL_CTL_STATE(pw_idx), 1)); } static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv, - enum i915_power_well_id id) + const struct i915_power_well_regs *regs, + int pw_idx) { - u32 req_mask = HSW_PWR_WELL_CTL_REQ(id); + u32 req_mask = HSW_PWR_WELL_CTL_REQ(pw_idx); u32 ret; - ret = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)) & req_mask ? 1 : 0; - ret |= I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & req_mask ? 2 : 0; - ret |= I915_READ(HSW_PWR_WELL_CTL_KVMR) & req_mask ? 4 : 0; - ret |= I915_READ(HSW_PWR_WELL_CTL_DEBUG(id)) & req_mask ? 8 : 0; + ret = I915_READ(regs->bios) & req_mask ? 1 : 0; + ret |= I915_READ(regs->driver) & req_mask ? 2 : 0; + if (regs->kvmr.reg) + ret |= I915_READ(regs->kvmr) & req_mask ? 4 : 0; + ret |= I915_READ(regs->debug) & req_mask ? 8 : 0; return ret; } @@ -350,7 +353,8 @@ static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv, static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum i915_power_well_id id = power_well->desc->id; + const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + int pw_idx = power_well->desc->hsw.idx; bool disabled; u32 reqs; @@ -363,9 +367,9 @@ static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, * Skip the wait in case any of the request bits are set and print a * diagnostic message. */ - wait_for((disabled = !(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & - HSW_PWR_WELL_CTL_STATE(id))) || - (reqs = hsw_power_well_requesters(dev_priv, id)), 1); + wait_for((disabled = !(I915_READ(regs->driver) & + HSW_PWR_WELL_CTL_STATE(pw_idx))) || + (reqs = hsw_power_well_requesters(dev_priv, regs, pw_idx)), 1); if (disabled) return; @@ -386,14 +390,15 @@ static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv, static void hsw_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum i915_power_well_id id = power_well->desc->id; + const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + int pw_idx = power_well->desc->hsw.idx; bool wait_fuses = power_well->desc->hsw.has_fuses; enum skl_power_gate uninitialized_var(pg); u32 val; if (wait_fuses) { - pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_TO_PG(id) : - SKL_PW_TO_PG(id); + pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_CTL_IDX_TO_PG(pw_idx) : + SKL_PW_CTL_IDX_TO_PG(pw_idx); /* * For PW1 we have to wait both for the PW0/PG0 fuse state * before enabling the power well and PW1/PG1's own fuse @@ -405,17 +410,17 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv, gen9_wait_for_power_well_fuses(dev_priv, SKL_PG0); } - 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(regs->driver); + I915_WRITE(regs->driver, val | HSW_PWR_WELL_CTL_REQ(pw_idx)); hsw_wait_for_power_well_enable(dev_priv, power_well); /* Display WA #1178: cnl */ if (IS_CANNONLAKE(dev_priv) && - (id == CNL_DISP_PW_AUX_B || id == CNL_DISP_PW_AUX_C || - id == CNL_DISP_PW_AUX_D || id == CNL_DISP_PW_AUX_F)) { - val = I915_READ(CNL_AUX_ANAOVRD1(id)); + pw_idx >= GLK_PW_CTL_IDX_AUX_B && + pw_idx <= CNL_PW_CTL_IDX_AUX_F) { + val = I915_READ(CNL_AUX_ANAOVRD1(pw_idx)); val |= CNL_AUX_ANAOVRD1_ENABLE | CNL_AUX_ANAOVRD1_LDO_BYPASS; - I915_WRITE(CNL_AUX_ANAOVRD1(id), val); + I915_WRITE(CNL_AUX_ANAOVRD1(pw_idx), val); } if (wait_fuses) @@ -429,30 +434,31 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv, static void hsw_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum i915_power_well_id id = power_well->desc->id; + const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + int pw_idx = power_well->desc->hsw.idx; u32 val; hsw_power_well_pre_disable(dev_priv, power_well->desc->hsw.irq_pipe_mask); - 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(regs->driver); + I915_WRITE(regs->driver, val & ~HSW_PWR_WELL_CTL_REQ(pw_idx)); hsw_wait_for_power_well_disable(dev_priv, power_well); } -#define ICL_AUX_PW_TO_PORT(pw) ((pw) - ICL_DISP_PW_AUX_A) +#define ICL_AUX_PW_TO_PORT(pw_idx) ((pw_idx) - ICL_PW_CTL_IDX_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->desc->id; - enum port port = ICL_AUX_PW_TO_PORT(id); + const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + int pw_idx = power_well->desc->hsw.idx; + enum port port = ICL_AUX_PW_TO_PORT(pw_idx); 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(regs->driver); + I915_WRITE(regs->driver, val | HSW_PWR_WELL_CTL_REQ(pw_idx)); val = I915_READ(ICL_PORT_CL_DW12(port)); I915_WRITE(ICL_PORT_CL_DW12(port), val | ICL_LANE_ENABLE_AUX); @@ -464,16 +470,16 @@ 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->desc->id; - enum port port = ICL_AUX_PW_TO_PORT(id); + const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + int pw_idx = power_well->desc->hsw.idx; + enum port port = ICL_AUX_PW_TO_PORT(pw_idx); 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)); + val = I915_READ(regs->driver); + I915_WRITE(regs->driver, val & ~HSW_PWR_WELL_CTL_REQ(pw_idx)); hsw_wait_for_power_well_disable(dev_priv, power_well); } @@ -486,22 +492,22 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum i915_power_well_id id = power_well->desc->id; - u32 mask = HSW_PWR_WELL_CTL_REQ(id) | HSW_PWR_WELL_CTL_STATE(id); + const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + int pw_idx = power_well->desc->hsw.idx; + u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx) | + HSW_PWR_WELL_CTL_STATE(pw_idx); - return (I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & mask) == mask; + return (I915_READ(regs->driver) & mask) == mask; } static void assert_can_enable_dc9(struct drm_i915_private *dev_priv) { - enum i915_power_well_id id = SKL_DISP_PW_2; - WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9), "DC9 already programmed to be enabled.\n"); WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5, "DC5 still not disabled to enable DC9.\n"); - WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & - HSW_PWR_WELL_CTL_REQ(id), + WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL2) & + HSW_PWR_WELL_CTL_REQ(SKL_PW_CTL_IDX_PW_2), "Power well 2 on.\n"); WARN_ONCE(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n"); @@ -725,17 +731,18 @@ static void skl_enable_dc6(struct drm_i915_private *dev_priv) static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum i915_power_well_id id = power_well->desc->id; - u32 mask = HSW_PWR_WELL_CTL_REQ(id); - u32 bios_req = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)); + const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + int pw_idx = power_well->desc->hsw.idx; + u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx); + u32 bios_req = I915_READ(regs->bios); /* Take over the request bit if set by BIOS. */ if (bios_req & mask) { - u32 drv_req = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)); + u32 drv_req = I915_READ(regs->driver); if (!(drv_req & mask)) - I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), drv_req | mask); - I915_WRITE(HSW_PWR_WELL_CTL_BIOS(id), bios_req & ~mask); + I915_WRITE(regs->driver, drv_req | mask); + I915_WRITE(regs->bios, bios_req & ~mask); } } @@ -2108,6 +2115,13 @@ static const struct i915_power_well_ops bxt_dpio_cmn_power_well_ops = { .is_enabled = bxt_dpio_cmn_power_well_enabled, }; +static const struct i915_power_well_regs hsw_power_well_regs = { + .bios = HSW_PWR_WELL_CTL1, + .driver = HSW_PWR_WELL_CTL2, + .kvmr = HSW_PWR_WELL_CTL3, + .debug = HSW_PWR_WELL_CTL4, +}; + static const struct i915_power_well_desc hsw_power_wells[] = { { .name = "always-on", @@ -2122,6 +2136,8 @@ static const struct i915_power_well_desc hsw_power_wells[] = { .ops = &hsw_power_well_ops, .id = HSW_DISP_PW_GLOBAL, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, .hsw.has_vga = true, }, }, @@ -2141,6 +2157,8 @@ static const struct i915_power_well_desc bdw_power_wells[] = { .ops = &hsw_power_well_ops, .id = HSW_DISP_PW_GLOBAL, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, }, @@ -2310,6 +2328,8 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, }, @@ -2319,6 +2339,10 @@ static const struct i915_power_well_desc skl_power_wells[] = { .domains = 0, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_MISC_IO, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_MISC_IO, + }, }, { .name = "DC off", @@ -2332,6 +2356,8 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, .hsw.has_fuses = true, @@ -2342,24 +2368,40 @@ static const struct i915_power_well_desc skl_power_wells[] = { .domains = SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_A_E, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_A_E, + }, }, { .name = "DDI B IO power well", .domains = SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_B, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, + }, }, { .name = "DDI C IO power well", .domains = SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_C, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, + }, }, { .name = "DDI D IO power well", .domains = SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_D, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_D, + }, }, }; @@ -2377,6 +2419,8 @@ static const struct i915_power_well_desc bxt_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, }, @@ -2392,6 +2436,8 @@ static const struct i915_power_well_desc bxt_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, .hsw.has_fuses = true, @@ -2432,6 +2478,8 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, }, @@ -2447,6 +2495,8 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, .hsw.has_fuses = true, @@ -2484,36 +2534,60 @@ static const struct i915_power_well_desc glk_power_wells[] = { .domains = GLK_DISPLAY_AUX_A_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = GLK_DISP_PW_AUX_A, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = GLK_PW_CTL_IDX_AUX_A, + }, }, { .name = "AUX B", .domains = GLK_DISPLAY_AUX_B_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = GLK_DISP_PW_AUX_B, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = GLK_PW_CTL_IDX_AUX_B, + }, }, { .name = "AUX C", .domains = GLK_DISPLAY_AUX_C_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = GLK_DISP_PW_AUX_C, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = GLK_PW_CTL_IDX_AUX_C, + }, }, { .name = "DDI A IO power well", .domains = GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = GLK_DISP_PW_DDI_A, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = GLK_PW_CTL_IDX_DDI_A, + }, }, { .name = "DDI B IO power well", .domains = GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_B, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, + }, }, { .name = "DDI C IO power well", .domains = GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_C, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, + }, }, }; @@ -2532,6 +2606,8 @@ static const struct i915_power_well_desc cnl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, }, @@ -2540,24 +2616,40 @@ static const struct i915_power_well_desc cnl_power_wells[] = { .domains = CNL_DISPLAY_AUX_A_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_A, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = GLK_PW_CTL_IDX_AUX_A, + }, }, { .name = "AUX B", .domains = CNL_DISPLAY_AUX_B_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_B, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = GLK_PW_CTL_IDX_AUX_B, + }, }, { .name = "AUX C", .domains = CNL_DISPLAY_AUX_C_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_C, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = GLK_PW_CTL_IDX_AUX_C, + }, }, { .name = "AUX D", .domains = CNL_DISPLAY_AUX_D_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_D, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = CNL_PW_CTL_IDX_AUX_D, + }, }, { .name = "DC off", @@ -2571,6 +2663,8 @@ static const struct i915_power_well_desc cnl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, .hsw.has_fuses = true, @@ -2581,36 +2675,60 @@ static const struct i915_power_well_desc cnl_power_wells[] = { .domains = CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_DDI_A, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = GLK_PW_CTL_IDX_DDI_A, + }, }, { .name = "DDI B IO power well", .domains = CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_B, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_B, + }, }, { .name = "DDI C IO power well", .domains = CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_C, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_C, + }, }, { .name = "DDI D IO power well", .domains = CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_D, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = SKL_PW_CTL_IDX_DDI_D, + }, }, { .name = "DDI F IO power well", .domains = CNL_DISPLAY_DDI_F_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_DDI_F, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = CNL_PW_CTL_IDX_DDI_F, + }, }, { .name = "AUX F", .domains = CNL_DISPLAY_AUX_F_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_F, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = CNL_PW_CTL_IDX_AUX_F, + }, }, }; @@ -2621,6 +2739,18 @@ static const struct i915_power_well_ops icl_combo_phy_aux_power_well_ops = { .is_enabled = hsw_power_well_enabled, }; +static const struct i915_power_well_regs icl_aux_power_well_regs = { + .bios = ICL_PWR_WELL_CTL_AUX1, + .driver = ICL_PWR_WELL_CTL_AUX2, + .debug = ICL_PWR_WELL_CTL_AUX4, +}; + +static const struct i915_power_well_regs icl_ddi_power_well_regs = { + .bios = ICL_PWR_WELL_CTL_DDI1, + .driver = ICL_PWR_WELL_CTL_DDI2, + .debug = ICL_PWR_WELL_CTL_DDI4, +}; + static const struct i915_power_well_desc icl_power_wells[] = { { .name = "always-on", @@ -2636,6 +2766,8 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_1, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, }, @@ -2645,6 +2777,8 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_2, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_fuses = true, }, }, @@ -2660,6 +2794,8 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, .hsw.has_fuses = true, @@ -2670,96 +2806,160 @@ static const struct i915_power_well_desc icl_power_wells[] = { .domains = ICL_DDI_IO_A_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_DDI_A, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_A, + }, }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_DDI_B, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_B, + }, }, { .name = "DDI C IO", .domains = ICL_DDI_IO_C_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_DDI_C, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_C, + }, }, { .name = "DDI D IO", .domains = ICL_DDI_IO_D_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_DDI_D, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_D, + }, }, { .name = "DDI E IO", .domains = ICL_DDI_IO_E_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_DDI_E, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_E, + }, }, { .name = "DDI F IO", .domains = ICL_DDI_IO_F_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_DDI_F, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_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, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_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, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_B, + }, }, { .name = "AUX C", .domains = ICL_AUX_C_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_AUX_C, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_C, + }, }, { .name = "AUX D", .domains = ICL_AUX_D_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_AUX_D, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_D, + }, }, { .name = "AUX E", .domains = ICL_AUX_E_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_AUX_E, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_E, + }, }, { .name = "AUX F", .domains = ICL_AUX_F_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_AUX_F, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_F, + }, }, { .name = "AUX TBT1", .domains = ICL_AUX_TBT1_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_AUX_TBT1, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT1, + }, }, { .name = "AUX TBT2", .domains = ICL_AUX_TBT2_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_AUX_TBT2, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT2, + }, }, { .name = "AUX TBT3", .domains = ICL_AUX_TBT3_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_AUX_TBT3, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT3, + }, }, { .name = "AUX TBT4", .domains = ICL_AUX_TBT4_IO_POWER_DOMAINS, .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_AUX_TBT4, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT4, + }, }, { .name = "power well 4", @@ -2767,6 +2967,8 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_4, { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), },
Similarly to the previous patch use a separate request/status HW flag index defined right after the corresponding control registers instead of depending for this on the power well IDs. Since the set of control/status registers varies among the different power wells (on a single platform), also add a new i915_power_well_registers struct that we populate and assign to each DDI power well as needed. Also clarify a bit the code comment describing the function and layout of the control registers. This also fixes a problem on ICL, where we incorrectly read the KVMR control register in hsw_power_well_requesters() even for DDI and AUX power wells. Cc: Ville Syrjala <ville.syrjala@linux.intel.com> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com> Cc: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> --- drivers/gpu/drm/i915/gvt/handlers.c | 30 +--- drivers/gpu/drm/i915/i915_drv.h | 13 ++ drivers/gpu/drm/i915/i915_reg.h | 126 ++++++++----- drivers/gpu/drm/i915/intel_display.c | 5 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 302 ++++++++++++++++++++++++++------ 5 files changed, 359 insertions(+), 117 deletions(-)