[Intel-gfx] [PATCH] drm/i915/icl: Add power well support

Imre Deak imre.deak at intel.com
Wed Jun 27 11:59:32 UTC 2018


On Tue, Jun 26, 2018 at 05:28:06PM -0700, Paulo Zanoni wrote:
> Em Ter, 2018-06-26 às 17:22 +0300, Imre Deak escreveu:
> > Add the definition for ICL power wells and their mapping to power
> > domains. On ICL there are 3 power well control registers, we'll
> > select
> > the correct one based on higher bits of the power well ID. The offset
> > for the control and status flags within this register is based on the
> > lower bits of the ID as on older platforms.
> > 
> > As the DC state programming is also the same as on old platforms we
> > can
> > reuse the corresponding helpers. For this we mark here the DC-off
> > power
> > well as shared among multiple platforms.
> > 
> > Other than the above the delta between old platforms and ICL:
> > - Pipe C has its own power well, so we can save some additional power
> > in the
> >   pipe A+B and (non-eDP) pipe A configurations.
> > - Power wells for port E/F DDI/AUX IO and Thunderbolt 1-4 AUX IO
> > 
> > v2:
> > - Rebase on drm-tip after prep patch for this was merged there as
> >   requested by Paulo.
> > - Actually add the new AUX and DDI power well control regs (Rakshmi)
> > 
> > v3:
> > - Fix power well register names in code comments
> > - Add TBT AUX->power well 3 dependency
> > 
> > v4:
> > - Rebase
> > 
> > v5:
> > - Detach AUX power wells from the INIT power domain. These power
> > wells
> >   can only be enabled in a TC/TBT connected state and otherwise not
> >   needed during driver initialization.
> > 
> > Cc: Animesh Manna <animesh.manna at intel.com>
> > Cc: Rakshmi Bhatia <rakshmi.bhatia at intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni at intel.com>
> > Signed-off-by: Imre Deak <imre.deak at intel.com>
> > Reviewed-by: Animesh Manna <animesh.manna at intel.com> (v1)
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h         |  78 +++++++-
> >  drivers/gpu/drm/i915/intel_display.h    |   4 +
> >  drivers/gpu/drm/i915/intel_runtime_pm.c | 329
> > +++++++++++++++++++++++++++++++-
> >  3 files changed, 395 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h
> > index caad19f5f557..865b05ce8d76 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -1045,13 +1045,13 @@ enum i915_power_well_id {
> >  
> >  	/*
> >  	 * HSW/BDW
> > -	 *  - HSW_PWR_WELL_CTL_DRIVER(0) (status bit: id*2, req bit:
> > id*2+1)
> > +	 *  - _HSW_PWR_WELL_CTL1-4 (status bit: id*2, req bit:
> > id*2+1)
> >  	 */
> >  	HSW_DISP_PW_GLOBAL = 15,
> >  
> >  	/*
> >  	 * GEN9+
> > -	 *  - HSW_PWR_WELL_CTL_DRIVER(0) (status bit: id*2, req bit:
> > id*2+1)
> > +	 *  - _HSW_PWR_WELL_CTL1-4 (status bit: id*2, req bit:
> > id*2+1)
> >  	 */
> >  	SKL_DISP_PW_MISC_IO = 0,
> >  	SKL_DISP_PW_DDI_A_E,
> > @@ -1075,17 +1075,54 @@ enum i915_power_well_id {
> >  	SKL_DISP_PW_2,
> >  
> >  	/* - custom power wells */
> > -	SKL_DISP_PW_DC_OFF,
> >  	BXT_DPIO_CMN_A,
> >  	BXT_DPIO_CMN_BC,
> > -	GLK_DPIO_CMN_C,			/* 19 */
> > +	GLK_DPIO_CMN_C,			/* 18 */
> > +
> > +	/*
> > +	 * GEN11+
> > +	 *  - _HSW_PWR_WELL_CTL1-4
> > +	 *    (status bit: (id&15)*2, req bit:(id&15)*2+1)
> > +	 */
> > +	ICL_DISP_PW_1 = 0,
> > +	ICL_DISP_PW_2,
> > +	ICL_DISP_PW_3,
> > +	ICL_DISP_PW_4,
> > +
> > +	/*
> > +	 *  - _HSW_PWR_WELL_CTL_AUX1/2/4
> > +	 *    (status bit: (id&15)*2, req bit:(id&15)*2+1)
> > +	 */
> > +	ICL_DISP_PW_AUX_A = 16,
> > +	ICL_DISP_PW_AUX_B,
> > +	ICL_DISP_PW_AUX_C,
> > +	ICL_DISP_PW_AUX_D,
> > +	ICL_DISP_PW_AUX_E,
> > +	ICL_DISP_PW_AUX_F,
> > +
> > +	ICL_DISP_PW_AUX_TBT1 = 24,
> > +	ICL_DISP_PW_AUX_TBT2,
> > +	ICL_DISP_PW_AUX_TBT3,
> > +	ICL_DISP_PW_AUX_TBT4,
> > +
> > +	/*
> > +	 *  - _HSW_PWR_WELL_CTL_DDI1/2/4
> > +	 *    (status bit: (id&15)*2, req bit:(id&15)*2+1)
> > +	 */
> > +	ICL_DISP_PW_DDI_A = 32,
> > +	ICL_DISP_PW_DDI_B,
> > +	ICL_DISP_PW_DDI_C,
> > +	ICL_DISP_PW_DDI_D,
> > +	ICL_DISP_PW_DDI_E,
> > +	ICL_DISP_PW_DDI_F,                      /* 37 */
> >  
> >  	/*
> >  	 * Multiple platforms.
> >  	 * Must start following the highest ID of any platform.
> >  	 * - custom power wells
> >  	 */
> > -	I915_DISP_PW_ALWAYS_ON = 20,
> > +	SKL_DISP_PW_DC_OFF = 38,
> > +	I915_DISP_PW_ALWAYS_ON,
> >  };
> >  
> >  #define PUNIT_REG_PWRGT_CTRL			0x60
> > @@ -1679,6 +1716,13 @@ enum i915_power_well_id {
> >  #define   IREF1RC_OFFSET_MASK		(0xFF <<
> > IREF1RC_OFFSET_SHIFT)
> >  #define BXT_PORT_CL1CM_DW10(phy)	_BXT_PHY((phy),
> > _PORT_CL1CM_DW10_BC)
> >  
> > +#define _ICL_PORT_CL_DW12_A		0x162030
> > +#define _ICL_PORT_CL_DW12_B		0x6C030
> > +#define   ICL_LANE_ENABLE_AUX		(1 << 0)
> > +#define ICL_PORT_CL_DW12(port)		_MMIO(_PICK((port),
> 
> You can get away with _PIPE instead of _PICK here, which is supposed to
> be a little more efficient.

There's a third instance of the register with a different offset, but
yes we can use _PIPE until that is taken into use. Will change that
along with the checkpatch issues.

> 
> Otherwise, looks correct (minus checkpatch problems).
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
> 
> But I would say the PW code is getting very hard to read. The whole
> magic behind the i915_power_well_id enum values is hard to read, and a
> lot of other magic macros build on top of that.

Not having the usual register definition followed by the definition of
the flags withing the register is not so nice. I considered adding the
register address and request/status flag positions to the power well
descriptors somehow, will look into that.

> I would really love if our code were a little more straightforward,
> less reliant on the magic, even if it were a little bigger. Stuff like
> _HSW_PW_REG_IDX() and others are crazy. Ideally the code would not
> have to rely on the value of the actual enum for anything. But all of
> that is content for a new series.

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


More information about the Intel-gfx mailing list