Reviewed-by: Rodrigo Vivi <rodrigo.v...@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.olive...@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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to