Message ID | 1478791400-21756-10-git-send-email-ander.conselvan.de.oliveira@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@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@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@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
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,
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@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(-)