[Intel-gfx] [PATCH 09/15] drm/i915/glk: Implement Geminilake DDI init sequence

Rodrigo Vivi rodrigo.vivi at gmail.com
Fri Nov 11 01:27:14 UTC 2016


Reviewed-by: Rodrigo Vivi <rodrigo.vivi at intel.com>

On Thu, Nov 10, 2016 at 05:23:14PM +0200, Ander Conselvan de Oliveira wrote:
> Implement the DDI initsequence and add information about the different
> phys in GLK.
> 
> v2: Rebase on the move of phys to be power wells.
> 
> v3: Rebase on addition of struct bxt_ddi_phy_info.
> 
> Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h         |   5 +-
>  drivers/gpu/drm/i915/i915_reg.h         |  17 +++--
>  drivers/gpu/drm/i915/intel_dpio_phy.c   | 114 +++++++++++++++++++++++++++-----
>  drivers/gpu/drm/i915/intel_dpll_mgr.c   |   4 +-
>  drivers/gpu/drm/i915/intel_runtime_pm.c |  39 +++++++++++
>  5 files changed, 155 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 4bb745a..f497396 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -207,7 +207,8 @@ enum dpio_channel {
>  
>  enum dpio_phy {
>  	DPIO_PHY0,
> -	DPIO_PHY1
> +	DPIO_PHY1,
> +	DPIO_PHY2,
>  };
>  
>  enum intel_display_power_domain {
> @@ -3888,7 +3889,7 @@ u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg);
>  void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
>  
>  /* intel_dpio_phy.c */
> -void bxt_port_to_phy_channel(enum port port,
> +void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
>  			     enum dpio_phy *phy, enum dpio_channel *ch);
>  void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
>  				  enum port port, u32 margin, u32 scale,
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 78a3347..d78a3e6 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -62,6 +62,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
>  #define _PORT3(port, a, b, c) ((port) == PORT_A ? (a) : \
>  			       (port) == PORT_B ? (b) : (c))
>  #define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PORT3(pipe, a, b, c))
> +#define _PHY3(phy, a, b, c) ((phy) == DPIO_PHY0 ? (a) : \
> +			     (phy) == DPIO_PHY1 ? (b) : (c))
> +#define _MMIO_PHY3(phy, a, b, c) _MMIO(_PHY3(phy, a, b, c))
>  
>  #define _MASKED_FIELD(mask, value) ({					   \
>  	if (__builtin_constant_p(mask))					   \
> @@ -726,6 +729,7 @@ enum skl_disp_power_wells {
>  
>  	BXT_DPIO_CMN_A,
>  	BXT_DPIO_CMN_BC,
> +	GLK_DPIO_CMN_C,
>  };
>  
>  #define SKL_POWER_WELL_STATE(pw) (1 << ((pw) * 2))
> @@ -1194,8 +1198,10 @@ enum skl_disp_power_wells {
>  /* BXT PHY registers */
>  #define _BXT_PHY0_BASE			0x6C000
>  #define _BXT_PHY1_BASE			0x162000
> -#define BXT_PHY_BASE(phy)		_PIPE((phy), _BXT_PHY0_BASE, \
> -						     _BXT_PHY1_BASE)
> +#define _BXT_PHY2_BASE			0x163000
> +#define BXT_PHY_BASE(phy)		_PHY3((phy), _BXT_PHY0_BASE, \
> +						     _BXT_PHY1_BASE, \
> +						     _BXT_PHY2_BASE)
>  
>  #define _BXT_PHY(phy, reg)						\
>  	_MMIO(BXT_PHY_BASE(phy) - _BXT_PHY0_BASE + (reg))
> @@ -1207,7 +1213,6 @@ enum skl_disp_power_wells {
>  	_MMIO(_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1))
>  
>  #define BXT_P_CR_GT_DISP_PWRON		_MMIO(0x138090)
> -#define   GT_DISPLAY_POWER_ON(phy)	(1 << (phy))
>  
>  #define _BXT_PHY_CTL_DDI_A		0x64C00
>  #define _BXT_PHY_CTL_DDI_B		0x64C10
> @@ -1220,9 +1225,11 @@ enum skl_disp_power_wells {
>  
>  #define _PHY_CTL_FAMILY_EDP		0x64C80
>  #define _PHY_CTL_FAMILY_DDI		0x64C90
> +#define _PHY_CTL_FAMILY_DDI_C		0x64CA0
>  #define   COMMON_RESET_DIS		(1 << 31)
> -#define BXT_PHY_CTL_FAMILY(phy)		_MMIO_PIPE((phy), _PHY_CTL_FAMILY_DDI, \
> -							  _PHY_CTL_FAMILY_EDP)
> +#define BXT_PHY_CTL_FAMILY(phy)		_MMIO_PHY3((phy), _PHY_CTL_FAMILY_DDI, \
> +							  _PHY_CTL_FAMILY_EDP, \
> +							  _PHY_CTL_FAMILY_DDI_C)
>  
>  /* BXT PHY PLL registers */
>  #define _PORT_PLL_A			0x46074
> diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c
> index 7a8e82d..4ff601d 100644
> --- a/drivers/gpu/drm/i915/intel_dpio_phy.c
> +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c
> @@ -131,6 +131,18 @@ struct bxt_ddi_phy_info {
>  	enum dpio_phy rcomp_phy;
>  
>  	/**
> +	 * @reset_delay: delay in us to wait before setting the common reset
> +	 * bit in BXT_PHY_CTL_FAMILY, which effectively enables the phy.
> +	 */
> +	int reset_delay;
> +
> +	/**
> +	 * @pwron_mask: Mask with the appropriate bit set that would cause the
> +	 * punit to power this phy if written to BXT_P_CR_GT_DISP_PWRON.
> +	 */
> +	u32 pwron_mask;
> +
> +	/**
>  	 * @channel: struct containing per channel information.
>  	 */
>  	struct {
> @@ -145,6 +157,7 @@ static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = {
>  	[DPIO_PHY0] = {
>  		.dual_channel = true,
>  		.rcomp_phy = DPIO_PHY1,
> +		.pwron_mask = BIT(0),
>  
>  		.channel = {
>  			[DPIO_CH0] = { .port = PORT_B },
> @@ -154,6 +167,7 @@ static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = {
>  	[DPIO_PHY1] = {
>  		.dual_channel = false,
>  		.rcomp_phy = -1,
> +		.pwron_mask = BIT(1),
>  
>  		.channel = {
>  			[DPIO_CH0] = { .port = PORT_A },
> @@ -161,20 +175,77 @@ static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = {
>  	},
>  };
>  
> +static const struct bxt_ddi_phy_info glk_ddi_phy_info[] = {
> +	[DPIO_PHY0] = {
> +		.dual_channel = false,
> +		.rcomp_phy = DPIO_PHY1,
> +		.pwron_mask = BIT(0),
> +		.reset_delay = 20,
> +
> +		.channel = {
> +			[DPIO_CH0] = { .port = PORT_B },
> +		}
> +	},
> +	[DPIO_PHY1] = {
> +		.dual_channel = false,
> +		.rcomp_phy = -1,
> +		.pwron_mask = BIT(3),
> +		.reset_delay = 20,
> +
> +		.channel = {
> +			[DPIO_CH0] = { .port = PORT_A },
> +		}
> +	},
> +	[DPIO_PHY2] = {
> +		.dual_channel = false,
> +		.rcomp_phy = DPIO_PHY1,
> +		.pwron_mask = BIT(1),
> +		.reset_delay = 20,
> +
> +		.channel = {
> +			[DPIO_CH0] = { .port = PORT_C },
> +		}
> +	},
> +};
> +
>  static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info)
>  {
>  	return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) |
>  		BIT(phy_info->channel[DPIO_CH0].port);
>  }
>  
> -void bxt_port_to_phy_channel(enum port port,
> +static const struct bxt_ddi_phy_info *
> +bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count)
> +{
> +	if (IS_GEMINILAKE(dev_priv)) {
> +		*count =  ARRAY_SIZE(glk_ddi_phy_info);
> +		return glk_ddi_phy_info;
> +	} else {
> +		*count =  ARRAY_SIZE(bxt_ddi_phy_info);
> +		return bxt_ddi_phy_info;
> +	}
> +}
> +
> +static const struct bxt_ddi_phy_info *
> +bxt_get_phy_info(struct drm_i915_private *dev_priv, enum dpio_phy phy)
> +{
> +	int count;
> +	const struct bxt_ddi_phy_info *phy_list =
> +		bxt_get_phy_list(dev_priv, &count);
> +
> +	return &phy_list[phy];
> +}
> +
> +void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
>  			     enum dpio_phy *phy, enum dpio_channel *ch)
>  {
> -	const struct bxt_ddi_phy_info *phy_info;
> -	int i;
> +	const struct bxt_ddi_phy_info *phy_info, *phys;
> +	int i, count;
> +
> +	phys = bxt_get_phy_list(dev_priv, &count);
>  
> -	for (i = 0; i < ARRAY_SIZE(bxt_ddi_phy_info); i++) {
> -		phy_info = &bxt_ddi_phy_info[i];
> +	for (i = 0; i < count; i++) {
> +		phy_info = &phys[i];
>  
>  		if (port == phy_info->channel[DPIO_CH0].port) {
>  			*phy = i;
> @@ -203,7 +274,7 @@ void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
>  	enum dpio_phy phy;
>  	enum dpio_channel ch;
>  
> -	bxt_port_to_phy_channel(port, &phy, &ch);
> +	bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
>  
>  	/*
>  	 * While we write to the group register to program all lanes at once we
> @@ -241,10 +312,12 @@ void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
>  bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
>  			    enum dpio_phy phy)
>  {
> -	const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
> +	const struct bxt_ddi_phy_info *phy_info;
>  	enum port port;
>  
> -	if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy)))
> +	phy_info = bxt_get_phy_info(dev_priv, phy);
> +
> +	if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & phy_info->pwron_mask))
>  		return false;
>  
>  	if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
> @@ -306,9 +379,11 @@ static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv,
>  static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv,
>  			      enum dpio_phy phy)
>  {
> -	const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
> +	const struct bxt_ddi_phy_info *phy_info;
>  	u32 val;
>  
> +	phy_info = bxt_get_phy_info(dev_priv, phy);
> +
>  	if (bxt_ddi_phy_is_enabled(dev_priv, phy)) {
>  		/* Still read out the GRC value for state verification */
>  		if (phy_info->rcomp_phy != -1)
> @@ -326,7 +401,7 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv,
>  	}
>  
>  	val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
> -	val |= GT_DISPLAY_POWER_ON(phy);
> +	val |= phy_info->pwron_mask;
>  	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
>  
>  	/*
> @@ -384,6 +459,9 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv,
>  		I915_WRITE(BXT_PORT_REF_DW8(phy), val);
>  	}
>  
> +	if (phy_info->reset_delay)
> +		udelay(phy_info->reset_delay);
> +
>  	val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
>  	val |= COMMON_RESET_DIS;
>  	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
> @@ -395,20 +473,24 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv,
>  
>  void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
>  {
> +	const struct bxt_ddi_phy_info *phy_info;
>  	uint32_t val;
>  
> +	phy_info = bxt_get_phy_info(dev_priv, phy);
> +
>  	val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
>  	val &= ~COMMON_RESET_DIS;
>  	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
>  
>  	val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
> -	val &= ~GT_DISPLAY_POWER_ON(phy);
> +	val &= ~phy_info->pwron_mask;
>  	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
>  }
>  
>  void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
>  {
> -	const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
> +	const struct bxt_ddi_phy_info *phy_info =
> +		bxt_get_phy_info(dev_priv, phy);
>  	enum dpio_phy rcomp_phy = phy_info->rcomp_phy;
>  	bool was_enabled;
>  
> @@ -461,10 +543,12 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
>  bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
>  			      enum dpio_phy phy)
>  {
> -	const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
> +	const struct bxt_ddi_phy_info *phy_info;
>  	uint32_t mask;
>  	bool ok;
>  
> +	phy_info = bxt_get_phy_info(dev_priv, phy);
> +
>  #define _CHK(reg, mask, exp, fmt, ...)					\
>  	__phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt,	\
>  			       ## __VA_ARGS__)
> @@ -540,7 +624,7 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
>  	enum dpio_channel ch;
>  	int lane;
>  
> -	bxt_port_to_phy_channel(port, &phy, &ch);
> +	bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
>  
>  	for (lane = 0; lane < 4; lane++) {
>  		u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane));
> @@ -568,7 +652,7 @@ bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
>  	int lane;
>  	uint8_t mask;
>  
> -	bxt_port_to_phy_channel(port, &phy, &ch);
> +	bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
>  
>  	mask = 0;
>  	for (lane = 0; lane < 4; lane++) {
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index 8205c1c..0311fd4 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> @@ -1374,7 +1374,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
>  	enum dpio_phy phy;
>  	enum dpio_channel ch;
>  
> -	bxt_port_to_phy_channel(port, &phy, &ch);
> +	bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
>  
>  	/* Non-SSC reference */
>  	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
> @@ -1492,7 +1492,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  	enum dpio_phy phy;
>  	enum dpio_channel ch;
>  
> -	bxt_port_to_phy_channel(port, &phy, &ch);
> +	bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
>  
>  	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
>  		return false;
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 683c15b..30d5112 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -477,6 +477,18 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  #define GLK_DISPLAY_DDI_C_POWER_DOMAINS (		\
>  	BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
>  	BIT(POWER_DOMAIN_INIT))
> +#define GLK_DPIO_CMN_A_POWER_DOMAINS (			\
> +	BIT(POWER_DOMAIN_PORT_DDI_A_LANES) |		\
> +	BIT(POWER_DOMAIN_AUX_A) |			\
> +	BIT(POWER_DOMAIN_INIT))
> +#define GLK_DPIO_CMN_B_POWER_DOMAINS (			\
> +	BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
> +	BIT(POWER_DOMAIN_AUX_B) |			\
> +	BIT(POWER_DOMAIN_INIT))
> +#define GLK_DPIO_CMN_C_POWER_DOMAINS (			\
> +	BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
> +	BIT(POWER_DOMAIN_AUX_C) |			\
> +	BIT(POWER_DOMAIN_INIT))
>  #define GLK_DISPLAY_AUX_A_POWER_DOMAINS (		\
>  	BIT(POWER_DOMAIN_AUX_A) |		\
>  	BIT(POWER_DOMAIN_INIT))
> @@ -926,6 +938,12 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv)
>  	power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC);
>  	if (power_well->count > 0)
>  		bxt_ddi_phy_verify_state(dev_priv, power_well->data);
> +
> +	if (IS_GEMINILAKE(dev_priv)) {
> +		power_well = lookup_power_well(dev_priv, GLK_DPIO_CMN_C);
> +		if (power_well->count > 0)
> +			bxt_ddi_phy_verify_state(dev_priv, power_well->data);
> +	}
>  }
>  
>  static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
> @@ -2219,6 +2237,27 @@ static struct i915_power_well glk_power_wells[] = {
>  		.id = SKL_DISP_PW_2,
>  	},
>  	{
> +		.name = "dpio-common-a",
> +		.domains = GLK_DPIO_CMN_A_POWER_DOMAINS,
> +		.ops = &bxt_dpio_cmn_power_well_ops,
> +		.id = BXT_DPIO_CMN_A,
> +		.data = DPIO_PHY1,
> +	},
> +	{
> +		.name = "dpio-common-b",
> +		.domains = GLK_DPIO_CMN_B_POWER_DOMAINS,
> +		.ops = &bxt_dpio_cmn_power_well_ops,
> +		.id = BXT_DPIO_CMN_BC,
> +		.data = DPIO_PHY0,
> +	},
> +	{
> +		.name = "dpio-common-c",
> +		.domains = GLK_DPIO_CMN_C_POWER_DOMAINS,
> +		.ops = &bxt_dpio_cmn_power_well_ops,
> +		.id = GLK_DPIO_CMN_C,
> +		.data = DPIO_PHY2,
> +	},
> +	{
>  		.name = "AUX A",
>  		.domains = GLK_DISPLAY_AUX_A_POWER_DOMAINS,
>  		.ops = &skl_power_well_ops,
> -- 
> 2.5.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx


More information about the Intel-gfx mailing list