On Wed, Apr 15, 2015 at 04:42:57PM +0300, Imre Deak wrote:
> From: Vandana Kannan <vandana.kan...@intel.com>
> 
> Add PHY specific display initialization sequence as per BSpec.
> 
> Note that the PHY initialization/uninitialization are done
> at their current place only for simplicity, in a future patch - when more
> of the runtime PM features will be enabled - these will be moved to
> power well#1 and modeset encoder enabling/disabling hooks respectively.
> 
> The call to uninitialize the PHY during system/runtime suspend will be
> added later in this patchset.
> 
> v1: Added function definitions in header files
> v2: Imre's review comments addressed
> - Moved CDCLK related definitions to i915_reg.h
> - Removed defintions for CDCLK frequency
> - Split uninit_cdclk() by adding a phy_uninit function
> - Calculate freq and decimal based on input frequency
> - Program SSA precharge based on input frequency
> - Use wait_for 1ms instead 200us udelay for DE PLL locking
> - Removed initial value for divider, freq, decimal, ratio.
> - Replaced polling loops with wait_for
> - Parameterized latency optim setting
> - Fix the parts where DE PLL has to be disabled.
> - Call CDCLK selection from mode set
> 
> v3: (imre)
> - add note about the plan to move the cdclk/phy init to a better place
> - take rps.hw_lock around pcode access
> - fix DDI PHY timeout value
> - squash in Vandana's "PORT_CL2CM_DW6_A BUN fix",
>   "DDI PHY programming register defn", "Do ddi_phy_init always",
> - move PHY register macros next to the corresponding CHV/VLV macros
> - move DE PLL register macros here from another patch since they are
>   used here first
> - add BXT_ prefix to CDCLK flags
> - s/COMMON_RESET/COMMON_RESET_DIS/ and clarify related code comments
> - fix incorrect read value for the RMW of BXT_PHY_CTL_FAMILY_DDI
> - fix using GT_DISPLAY_EDP_POWER_ON vs. GT_DISPLAY_DDI_POWER_ON
>   when powering on DDI ports
> - fix incorrect port when setting BXT_PORT_TX_DW14_LN for DDI ports
> - add missing masking when programming CDCLK_FREQ_DECIMAL
> - add missing powering on for DDI-C port, rename OCL2_LDOFUSE_PWR_EN
>   to OCL2_LDOFUSE_PWR_DIS to reduce confusion
> - add note about mismatch with bspec in the PORT_REF_DW6 fields
> - factor out PHY init code to a new function, so we can call it for
>   PHY1 and PHY0, instead of open-coding the same
> 
> v4: (ville)
> - split the CDCLK/PHY parts into two patches, update commit message
>   accordingly
> - use the existing dpio_phy enum instead of adding a new one for the
>   same purpose
> - flip the meaning of PHYs so that PHY_A is PHY1 and PHY_BC is PHY0 to
>   better match CHV
> - s/BXT_PHY/_BXT_PHY/
> - use _PIPE for _BXT_PHY instead of open-coding it
> - drop _0_2_0_GTTMMADR suffix from BXT_P_CR_GT_DISP_PWRON
> - define GT_DISPLAY_POWER_ON in a more standard way
> - make a note that the CHV ConfigDB also disagrees about GRC_CODE field
>   definitions
> - fix lane optimization refactoring fumble from v3
> - add per PHY uninit functions to match the init counterparts
> 
> Signed-off-by: Vandana Kannan <vandana.kan...@intel.com> (v2)
> Signed-off-by: Imre Deak <imre.d...@intel.com>

Looking OK. Stuffing some/all of it into a power well and/or into the
port enable/disable code may be the right thing to do later, but this
should at least get it up and running for now.

Reviewed-by: Ville Syrjälä <ville.syrj...@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/i915_reg.h  |  96 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_ddi.c | 125 
> +++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |   2 +
>  3 files changed, 223 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index c79bf8d..1903e37 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1117,6 +1117,102 @@ enum skl_disp_power_wells {
>  #define   DPIO_FRC_LATENCY_SHFIT     8
>  #define CHV_TX_DW14(ch, lane) _TXLANE(ch, lane, 0xb8)
>  #define   DPIO_UPAR_SHIFT            30
> +
> +/* BXT PHY registers */
> +#define _BXT_PHY(phy, a, b)          _PIPE((phy), (a), (b))
> +
> +#define BXT_P_CR_GT_DISP_PWRON               0x138090
> +#define   GT_DISPLAY_POWER_ON(phy)   (1 << (phy))
> +
> +#define _PHY_CTL_FAMILY_EDP          0x64C80
> +#define _PHY_CTL_FAMILY_DDI          0x64C90
> +#define   COMMON_RESET_DIS           (1 << 31)
> +#define BXT_PHY_CTL_FAMILY(phy)              _BXT_PHY((phy), 
> _PHY_CTL_FAMILY_DDI, \
> +                                                     _PHY_CTL_FAMILY_EDP)
> +
> +/* BXT PHY common lane registers */
> +#define _PORT_CL1CM_DW0_A            0x162000
> +#define _PORT_CL1CM_DW0_BC           0x6C000
> +#define   PHY_POWER_GOOD             (1 << 16)
> +#define BXT_PORT_CL1CM_DW0(phy)              _BXT_PHY((phy), 
> _PORT_CL1CM_DW0_BC, \
> +                                                     _PORT_CL1CM_DW0_A)
> +
> +#define _PORT_CL1CM_DW9_A            0x162024
> +#define _PORT_CL1CM_DW9_BC           0x6C024
> +#define   IREF0RC_OFFSET_SHIFT               8
> +#define   IREF0RC_OFFSET_MASK                (0xFF << IREF0RC_OFFSET_SHIFT)
> +#define BXT_PORT_CL1CM_DW9(phy)              _BXT_PHY((phy), 
> _PORT_CL1CM_DW9_BC, \
> +                                                     _PORT_CL1CM_DW9_A)
> +
> +#define _PORT_CL1CM_DW10_A           0x162028
> +#define _PORT_CL1CM_DW10_BC          0x6C028
> +#define   IREF1RC_OFFSET_SHIFT               8
> +#define   IREF1RC_OFFSET_MASK                (0xFF << IREF1RC_OFFSET_SHIFT)
> +#define BXT_PORT_CL1CM_DW10(phy)     _BXT_PHY((phy), _PORT_CL1CM_DW10_BC, \
> +                                                     _PORT_CL1CM_DW10_A)
> +
> +#define _PORT_CL1CM_DW28_A           0x162070
> +#define _PORT_CL1CM_DW28_BC          0x6C070
> +#define   OCL1_POWER_DOWN_EN         (1 << 23)
> +#define   DW28_OLDO_DYN_PWR_DOWN_EN  (1 << 22)
> +#define   SUS_CLK_CONFIG             0x3
> +#define BXT_PORT_CL1CM_DW28(phy)     _BXT_PHY((phy), _PORT_CL1CM_DW28_BC, \
> +                                                     _PORT_CL1CM_DW28_A)
> +
> +#define _PORT_CL1CM_DW30_A           0x162078
> +#define _PORT_CL1CM_DW30_BC          0x6C078
> +#define   OCL2_LDOFUSE_PWR_DIS               (1 << 6)
> +#define BXT_PORT_CL1CM_DW30(phy)     _BXT_PHY((phy), _PORT_CL1CM_DW30_BC, \
> +                                                     _PORT_CL1CM_DW30_A)
> +
> +/* Defined for PHY0 only */
> +#define BXT_PORT_CL2CM_DW6_BC                0x6C358
> +#define   DW6_OLDO_DYN_PWR_DOWN_EN   (1 << 28)
> +
> +/* BXT PHY Ref registers */
> +#define _PORT_REF_DW3_A                      0x16218C
> +#define _PORT_REF_DW3_BC             0x6C18C
> +#define   GRC_DONE                   (1 << 22)
> +#define BXT_PORT_REF_DW3(phy)                _BXT_PHY((phy), 
> _PORT_REF_DW3_BC, \
> +                                                     _PORT_REF_DW3_A)
> +
> +#define _PORT_REF_DW6_A                      0x162198
> +#define _PORT_REF_DW6_BC             0x6C198
> +/*
> + * FIXME: BSpec/CHV ConfigDB disagrees on the following two fields, fix them
> + * after testing.
> + */
> +#define   GRC_CODE_SHIFT             23
> +#define   GRC_CODE_MASK                      (0x1FF << GRC_CODE_SHIFT)
> +#define   GRC_CODE_FAST_SHIFT                16
> +#define   GRC_CODE_FAST_MASK         (0x7F << GRC_CODE_FAST_SHIFT)
> +#define   GRC_CODE_SLOW_SHIFT                8
> +#define   GRC_CODE_SLOW_MASK         (0xFF << GRC_CODE_SLOW_SHIFT)
> +#define   GRC_CODE_NOM_MASK          0xFF
> +#define BXT_PORT_REF_DW6(phy)                _BXT_PHY((phy), 
> _PORT_REF_DW6_BC,       \
> +                                                   _PORT_REF_DW6_A)
> +
> +#define _PORT_REF_DW8_A                      0x1621A0
> +#define _PORT_REF_DW8_BC             0x6C1A0
> +#define   GRC_DIS                    (1 << 15)
> +#define   GRC_RDY_OVRD                       (1 << 1)
> +#define BXT_PORT_REF_DW8(phy)                _BXT_PHY((phy), 
> _PORT_REF_DW8_BC,       \
> +                                                   _PORT_REF_DW8_A)
> +
> +/* BXT PHY TX registers */
> +#define _BXT_LANE_OFFSET(lane)           (((lane) >> 1) * 0x200 +    \
> +                                       ((lane) & 1) * 0x80)
> +
> +#define _PORT_TX_DW14_LN0_A          0x162538
> +#define _PORT_TX_DW14_LN0_B          0x6C538
> +#define _PORT_TX_DW14_LN0_C          0x6C938
> +#define   LATENCY_OPTIM_SHIFT                30
> +#define   LATENCY_OPTIM                      (1 << LATENCY_OPTIM_SHIFT)
> +#define BXT_PORT_TX_DW14_LN(port, lane)      (_PORT3((port), 
> _PORT_TX_DW14_LN0_A,   \
> +                                                     _PORT_TX_DW14_LN0_B,   \
> +                                                     _PORT_TX_DW14_LN0_C) + \
> +                                      _BXT_LANE_OFFSET(lane))
> +
>  /*
>   * Fence registers
>   */
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c 
> b/drivers/gpu/drm/i915/intel_ddi.c
> index 25d697b..31cadb8 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1864,6 +1864,130 @@ static void skl_shared_dplls_init(struct 
> drm_i915_private *dev_priv)
>       }
>  }
>  
> +static void broxton_phy_init(struct drm_i915_private *dev_priv,
> +                          enum dpio_phy phy)
> +{
> +     enum port port;
> +     uint32_t val;
> +
> +     val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
> +     val |= GT_DISPLAY_POWER_ON(phy);
> +     I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
> +
> +     /* Considering 10ms timeout until BSpec is updated */
> +     if (wait_for(I915_READ(BXT_PORT_CL1CM_DW0(phy)) & PHY_POWER_GOOD, 10))
> +             DRM_ERROR("timeout during PHY%d power on\n", phy);
> +
> +     for (port =  (phy == DPIO_PHY0 ? PORT_B : PORT_A);
> +          port <= (phy == DPIO_PHY0 ? PORT_C : PORT_A); port++) {
> +             int lane;
> +
> +             for (lane = 0; lane < 4; lane++) {
> +                     val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane));
> +                     /*
> +                      * Note that on CHV this flag is called UPAR, but has
> +                      * the same function.
> +                      */
> +                     val &= ~LATENCY_OPTIM;
> +                     if (lane != 1)
> +                             val |= LATENCY_OPTIM;
> +
> +                     I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val);
> +             }
> +     }
> +
> +     /* Program PLL Rcomp code offset */
> +     val = I915_READ(BXT_PORT_CL1CM_DW9(phy));
> +     val &= ~IREF0RC_OFFSET_MASK;
> +     val |= 0xE4 << IREF0RC_OFFSET_SHIFT;
> +     I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val);
> +
> +     val = I915_READ(BXT_PORT_CL1CM_DW10(phy));
> +     val &= ~IREF1RC_OFFSET_MASK;
> +     val |= 0xE4 << IREF1RC_OFFSET_SHIFT;
> +     I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val);
> +
> +     /* Program power gating */
> +     val = I915_READ(BXT_PORT_CL1CM_DW28(phy));
> +     val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN |
> +             SUS_CLK_CONFIG;
> +     I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val);
> +
> +     if (phy == DPIO_PHY0) {
> +             val = I915_READ(BXT_PORT_CL2CM_DW6_BC);
> +             val |= DW6_OLDO_DYN_PWR_DOWN_EN;
> +             I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val);
> +     }
> +
> +     val = I915_READ(BXT_PORT_CL1CM_DW30(phy));
> +     val &= ~OCL2_LDOFUSE_PWR_DIS;
> +     /*
> +      * On PHY1 disable power on the second channel, since no port is
> +      * connected there. On PHY0 both channels have a port, so leave it
> +      * enabled.
> +      * TODO: port C is only connected on BXT-P, so on BXT0/1 we should
> +      * power down the second channel on PHY0 as well.
> +      */
> +     if (phy == DPIO_PHY1)
> +             val |= OCL2_LDOFUSE_PWR_DIS;
> +     I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val);
> +
> +     if (phy == DPIO_PHY0) {
> +             uint32_t grc_code;
> +             /*
> +              * PHY0 isn't connected to an RCOMP resistor so copy over
> +              * the corresponding calibrated value from PHY1, and disable
> +              * the automatic calibration on PHY0.
> +              */
> +             if (wait_for(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE,
> +                          10))
> +                     DRM_ERROR("timeout waiting for PHY1 GRC\n");
> +
> +             val = I915_READ(BXT_PORT_REF_DW6(DPIO_PHY1));
> +             val = (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT;
> +             grc_code = val << GRC_CODE_FAST_SHIFT |
> +                        val << GRC_CODE_SLOW_SHIFT |
> +                        val;
> +             I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code);
> +
> +             val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0));
> +             val |= GRC_DIS | GRC_RDY_OVRD;
> +             I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val);
> +     }
> +
> +     val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
> +     val |= COMMON_RESET_DIS;
> +     I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
> +}
> +
> +void broxton_ddi_phy_init(struct drm_device *dev)
> +{
> +     /* Enable PHY1 first since it provides Rcomp for PHY0 */
> +     broxton_phy_init(dev->dev_private, DPIO_PHY1);
> +     broxton_phy_init(dev->dev_private, DPIO_PHY0);
> +}
> +
> +static void broxton_phy_uninit(struct drm_i915_private *dev_priv,
> +                            enum dpio_phy phy)
> +{
> +     uint32_t val;
> +
> +     val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
> +     val &= ~COMMON_RESET_DIS;
> +     I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
> +}
> +
> +void broxton_ddi_phy_uninit(struct drm_device *dev)
> +{
> +     struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +     broxton_phy_uninit(dev_priv, DPIO_PHY1);
> +     broxton_phy_uninit(dev_priv, DPIO_PHY0);
> +
> +     /* FIXME: do this in broxton_phy_uninit per phy */
> +     I915_WRITE(BXT_P_CR_GT_DISP_PWRON, 0);
> +}
> +
>  void intel_ddi_pll_init(struct drm_device *dev)
>  {
>       struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -1882,6 +2006,7 @@ void intel_ddi_pll_init(struct drm_device *dev)
>                       DRM_ERROR("LCPLL1 is disabled\n");
>       } else if (IS_BROXTON(dev)) {
>               broxton_init_cdclk(dev);
> +             broxton_ddi_phy_init(dev);
>       } else {
>               /*
>                * The LCPLL register should be turned on by the BIOS. For now
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index 5ba88eb..5266985 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1115,6 +1115,8 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv);
>  void broxton_init_cdclk(struct drm_device *dev);
>  void broxton_uninit_cdclk(struct drm_device *dev);
>  void broxton_set_cdclk(struct drm_device *dev, int frequency);
> +void broxton_ddi_phy_init(struct drm_device *dev);
> +void broxton_ddi_phy_uninit(struct drm_device *dev);
>  void intel_dp_get_m_n(struct intel_crtc *crtc,
>                     struct intel_crtc_state *pipe_config);
>  void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
> -- 
> 2.1.0

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to