On Fri, Jul 23, 2021 at 10:42:32AM -0700, Matt Roper wrote:
> DG2's SNPS PHYs incorporate a dedicated port PLL called MPLLB which
> takes the place of the shared DPLLs we've used on past platforms.  Let's
> add the MPLLB programming sequences; they'll be plugged into the rest of
> the code in future patches.
> 
> Bspec: 54032
> Bspec: 53881
> Cc: Lucas De Marchi <lucas.demar...@intel.com>
> Signed-off-by: Matt Roper <matthew.d.ro...@intel.com>
> Signed-off-by: Vandita Kulkarni <vandita.kulka...@intel.com>
> Signed-off-by: Jani Nikula <jani.nik...@intel.com>
> Signed-off-by: Nidhi Gupta <nidhi1.gu...@intel.com>
Reviewed-by: Matt Atwood <matthew.s.atw...@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |   1 +
>  drivers/gpu/drm/i915/display/intel_display.c  |   1 +
>  .../drm/i915/display/intel_display_types.h    |  17 +-
>  drivers/gpu/drm/i915/display/intel_dpll.c     |  12 +-
>  drivers/gpu/drm/i915/display/intel_snps_phy.c | 517 ++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_snps_phy.h |  18 +
>  drivers/gpu/drm/i915/i915_reg.h               |  56 ++
>  7 files changed, 616 insertions(+), 6 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_snps_phy.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_snps_phy.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 10b3bb6207ba..d87dbf87cfda 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -267,6 +267,7 @@ i915-y += \
>       display/intel_pps.o \
>       display/intel_qp_tables.o \
>       display/intel_sdvo.o \
> +     display/intel_snps_phy.o \
>       display/intel_tv.o \
>       display/intel_vdsc.o \
>       display/intel_vrr.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 400f062d785a..8e88ef5407d8 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -59,6 +59,7 @@
>  #include "display/intel_hdmi.h"
>  #include "display/intel_lvds.h"
>  #include "display/intel_sdvo.h"
> +#include "display/intel_snps_phy.h"
>  #include "display/intel_tv.h"
>  #include "display/intel_vdsc.h"
>  #include "display/intel_vrr.h"
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 19d8d3eefbc2..00320d89d266 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -884,6 +884,18 @@ enum intel_output_format {
>       INTEL_OUTPUT_FORMAT_YCBCR444,
>  };
>  
> +struct intel_mpllb_state {
> +     u32 clock; /* in KHz */
> +     u32 ref_control;
> +     u32 mpllb_cp;
> +     u32 mpllb_div;
> +     u32 mpllb_div2;
> +     u32 mpllb_fracn1;
> +     u32 mpllb_fracn2;
> +     u32 mpllb_sscen;
> +     u32 mpllb_sscstep;
> +};
> +
>  struct intel_crtc_state {
>       /*
>        * uapi (drm) state. This is the software state shown to userspace.
> @@ -1018,7 +1030,10 @@ struct intel_crtc_state {
>       struct intel_shared_dpll *shared_dpll;
>  
>       /* Actual register state of the dpll, for shared dpll cross-checking. */
> -     struct intel_dpll_hw_state dpll_hw_state;
> +     union {
> +             struct intel_dpll_hw_state dpll_hw_state;
> +             struct intel_mpllb_state mpllb_state;
> +     };
>  
>       /*
>        * ICL reserved DPLLs for the CRTC/port. The active PLL is selected by
> diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c 
> b/drivers/gpu/drm/i915/display/intel_dpll.c
> index 89635da9f6f6..14515e62c05e 100644
> --- a/drivers/gpu/drm/i915/display/intel_dpll.c
> +++ b/drivers/gpu/drm/i915/display/intel_dpll.c
> @@ -11,6 +11,7 @@
>  #include "intel_lvds.h"
>  #include "intel_panel.h"
>  #include "intel_sideband.h"
> +#include "display/intel_snps_phy.h"
>  
>  struct intel_limit {
>       struct {
> @@ -923,12 +924,13 @@ static int hsw_crtc_compute_clock(struct intel_crtc 
> *crtc,
>       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>       struct intel_atomic_state *state =
>               to_intel_atomic_state(crtc_state->uapi.state);
> +     struct intel_encoder *encoder =
> +             intel_get_crtc_new_encoder(state, crtc_state);
>  
> -     if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
> -         DISPLAY_VER(dev_priv) >= 11) {
> -             struct intel_encoder *encoder =
> -                     intel_get_crtc_new_encoder(state, crtc_state);
> -
> +     if (IS_DG2(dev_priv)) {
> +             return intel_mpllb_calc_state(crtc_state, encoder);
> +     } else if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
> +                DISPLAY_VER(dev_priv) >= 11) {
>               if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
>                       drm_dbg_kms(&dev_priv->drm,
>                                   "failed to find PLL for pipe %c\n",
> diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c 
> b/drivers/gpu/drm/i915/display/intel_snps_phy.c
> new file mode 100644
> index 000000000000..6d9205906595
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
> @@ -0,0 +1,517 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#include "intel_de.h"
> +#include "intel_display_types.h"
> +#include "intel_snps_phy.h"
> +
> +/**
> + * DOC: Synopsis PHY support
> + *
> + * Synopsis PHYs are primarily programmed by looking up magic register values
> + * in tables rather than calculating the necessary values at runtime.
> + *
> + * Of special note is that the SNPS PHYs include a dedicated port PLL, known 
> as
> + * an "MPLLB."  The MPLLB replaces the shared DPLL functionality used on 
> other
> + * platforms and must be programming directly during the modeset sequence
> + * since it is not handled by the shared DPLL framework as on other 
> platforms.
> + */
> +
> +/*
> + * Basic DP link rates with 100 MHz reference clock.
> + */
> +
> +static const struct intel_mpllb_state dg2_dp_rbr_100 = {
> +     .clock = 162000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 226),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 3),
> +};
> +
> +static const struct intel_mpllb_state dg2_dp_hbr1_100 = {
> +     .clock = 270000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 184),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
> +};
> +
> +static const struct intel_mpllb_state dg2_dp_hbr2_100 = {
> +     .clock = 540000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 184),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
> +};
> +
> +static const struct intel_mpllb_state dg2_dp_hbr3_100 = {
> +     .clock = 810000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 19) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 292),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
> +};
> +
> +static const struct intel_mpllb_state *dg2_dp_100_tables[] = {
> +     &dg2_dp_rbr_100,
> +     &dg2_dp_hbr1_100,
> +     &dg2_dp_hbr2_100,
> +     &dg2_dp_hbr3_100,
> +     NULL,
> +};
> +
> +/*
> + * Basic DP link rates with 38.4 MHz reference clock.
> + */
> +
> +static const struct intel_mpllb_state dg2_dp_rbr_38_4 = {
> +     .clock = 162000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 1),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 25) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 304),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 49152),
> +};
> +
> +static const struct intel_mpllb_state dg2_dp_hbr1_38_4 = {
> +     .clock = 270000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 1),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 25) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 248),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 40960),
> +};
> +
> +static const struct intel_mpllb_state dg2_dp_hbr2_38_4 = {
> +     .clock = 540000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 1),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 25) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 248),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 40960),
> +};
> +
> +static const struct intel_mpllb_state dg2_dp_hbr3_38_4 = {
> +     .clock = 810000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 1),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 26) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 388),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 61440),
> +};
> +
> +static const struct intel_mpllb_state *dg2_dp_38_4_tables[] = {
> +     &dg2_dp_rbr_38_4,
> +     &dg2_dp_hbr1_38_4,
> +     &dg2_dp_hbr2_38_4,
> +     &dg2_dp_hbr3_38_4,
> +     NULL,
> +};
> +
> +/*
> + * eDP link rates with 100 MHz reference clock.
> + */
> +
> +static const struct intel_mpllb_state dg2_edp_r216 = {
> +     .clock = 216000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 19) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 312),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 4),
> +     .mpllb_sscen =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_PEAK, 50961),
> +     .mpllb_sscstep =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_STEPSIZE, 65752),
> +};
> +
> +static const struct intel_mpllb_state dg2_edp_r243 = {
> +     .clock = 243000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 356),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 2),
> +     .mpllb_sscen =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_PEAK, 57331),
> +     .mpllb_sscstep =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_STEPSIZE, 73971),
> +};
> +
> +static const struct intel_mpllb_state dg2_edp_r324 = {
> +     .clock = 324000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 226),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 3),
> +     .mpllb_sscen =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_PEAK, 38221),
> +     .mpllb_sscstep =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_STEPSIZE, 49314),
> +};
> +
> +static const struct intel_mpllb_state dg2_edp_r432 = {
> +     .clock = 432000,
> +     .ref_control =
> +             REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +     .mpllb_cp =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 19) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
> +     .mpllb_div =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
> +     .mpllb_div2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 312),
> +     .mpllb_fracn1 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
> +     .mpllb_fracn2 =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 4),
> +     .mpllb_sscen =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_EN, 1) |
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_PEAK, 50961),
> +     .mpllb_sscstep =
> +             REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_STEPSIZE, 65752),
> +};
> +
> +static const struct intel_mpllb_state *dg2_edp_tables[] = {
> +     &dg2_dp_rbr_100,
> +     &dg2_edp_r216,
> +     &dg2_edp_r243,
> +     &dg2_dp_hbr1_100,
> +     &dg2_edp_r324,
> +     &dg2_edp_r432,
> +     &dg2_dp_hbr2_100,
> +     &dg2_dp_hbr3_100,
> +     NULL,
> +};
> +
> +int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
> +                        struct intel_encoder *encoder)
> +{
> +     const struct intel_mpllb_state **tables;
> +     int i;
> +
> +     if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
> +             tables = dg2_edp_tables;
> +     } else if (intel_crtc_has_dp_encoder(crtc_state)) {
> +             /*
> +              * FIXME: Initially we're just enabling the "combo" outputs on
> +              * port A-D.  The MPLLB for those ports takes an input from the
> +              * "Display Filter PLL" which always has an output frequency
> +              * of 100 MHz, hence the use of the _100 tables below.
> +              *
> +              * Once we enable port TC1 it will either use the same 100 MHz
> +              * "Display Filter PLL" (when strapped to support a native
> +              * display connection) or different 38.4 MHz "Filter PLL" when
> +              * strapped to support a USB connection, so we'll need to check
> +              * that to determine which table to use.
> +              */
> +             if (0)
> +                     tables = dg2_dp_38_4_tables;
> +             else
> +                     tables = dg2_dp_100_tables;
> +     } else {
> +             /* TODO: Add HDMI support */
> +             MISSING_CASE(encoder->type);
> +             return -EINVAL;
> +     }
> +
> +     for (i = 0; tables[i]; i++) {
> +             if (crtc_state->port_clock <= tables[i]->clock) {
> +                     crtc_state->mpllb_state = *tables[i];
> +                     return 0;
> +             }
> +     }
> +
> +     return -EINVAL;
> +}
> +
> +void intel_mpllb_enable(struct intel_encoder *encoder,
> +                     const struct intel_crtc_state *crtc_state)
> +{
> +     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +     const struct intel_mpllb_state *pll_state = &crtc_state->mpllb_state;
> +     enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
> +     i915_reg_t enable_reg = (phy <= PHY_D ?
> +                              DG2_PLL_ENABLE(phy) : MG_PLL_ENABLE(0));
> +
> +     /*
> +      * 3. Software programs the following PLL registers for the desired
> +      * frequency.
> +      */
> +     intel_de_write(dev_priv, SNPS_PHY_MPLLB_CP(phy), pll_state->mpllb_cp);
> +     intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV(phy), pll_state->mpllb_div);
> +     intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV2(phy), 
> pll_state->mpllb_div2);
> +     intel_de_write(dev_priv, SNPS_PHY_MPLLB_SSCEN(phy), 
> pll_state->mpllb_sscen);
> +     intel_de_write(dev_priv, SNPS_PHY_MPLLB_SSCSTEP(phy), 
> pll_state->mpllb_sscstep);
> +     intel_de_write(dev_priv, SNPS_PHY_MPLLB_FRACN1(phy), 
> pll_state->mpllb_fracn1);
> +     intel_de_write(dev_priv, SNPS_PHY_MPLLB_FRACN2(phy), 
> pll_state->mpllb_fracn2);
> +
> +     /*
> +      * 4. If the frequency will result in a change to the voltage
> +      * requirement, follow the Display Voltage Frequency Switching -
> +      * Sequence Before Frequency Change.
> +      *
> +      * We handle this step in bxt_set_cdclk().
> +      */
> +
> +     /* 5. Software sets DPLL_ENABLE [PLL Enable] to "1". */
> +     intel_uncore_rmw(&dev_priv->uncore, enable_reg, 0, PLL_ENABLE);
> +
> +     /*
> +      * 9. Software sets SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "1". This
> +      * will keep the PLL running during the DDI lane programming and any
> +      * typeC DP cable disconnect. Do not set the force before enabling the
> +      * PLL because that will start the PLL before it has sampled the
> +      * divider values.
> +      */
> +     intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV(phy),
> +                    pll_state->mpllb_div | SNPS_PHY_MPLLB_FORCE_EN);
> +
> +     /*
> +      * 10. Software polls on register DPLL_ENABLE [PLL Lock] to confirm PLL
> +      * is locked at new settings. This register bit is sampling PHY
> +      * dp_mpllb_state interface signal.
> +      */
> +     if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_LOCK, 5))
> +             DRM_ERROR("Port %c PLL not locked\n", phy_name(phy));
> +
> +     /*
> +      * 11. If the frequency will result in a change to the voltage
> +      * requirement, follow the Display Voltage Frequency Switching -
> +      * Sequence After Frequency Change.
> +      *
> +      * We handle this step in bxt_set_cdclk().
> +      */
> +}
> +
> +void intel_mpllb_disable(struct intel_encoder *encoder)
> +{
> +     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +     enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
> +     i915_reg_t enable_reg = (phy <= PHY_D ?
> +                              DG2_PLL_ENABLE(phy) : MG_PLL_ENABLE(0));
> +
> +     /*
> +      * 1. If the frequency will result in a change to the voltage
> +      * requirement, follow the Display Voltage Frequency Switching -
> +      * Sequence Before Frequency Change.
> +      *
> +      * We handle this step in bxt_set_cdclk().
> +      */
> +
> +     /* 2. Software programs DPLL_ENABLE [PLL Enable] to "0" */
> +     intel_uncore_rmw(&dev_priv->uncore, enable_reg, PLL_ENABLE, 0);
> +
> +     /*
> +      * 4. Software programs SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "0".
> +      * This will allow the PLL to stop running.
> +      */
> +     intel_uncore_rmw(&dev_priv->uncore, SNPS_PHY_MPLLB_DIV(phy),
> +                      SNPS_PHY_MPLLB_FORCE_EN, 0);
> +
> +     /*
> +      * 5. Software polls DPLL_ENABLE [PLL Lock] for PHY acknowledgment
> +      * (dp_txX_ack) that the new transmitter setting request is completed.
> +      */
> +     if (intel_de_wait_for_clear(dev_priv, enable_reg, PLL_LOCK, 5))
> +             DRM_ERROR("Port %c PLL not locked\n", phy_name(phy));
> +
> +     /*
> +      * 6. If the frequency will result in a change to the voltage
> +      * requirement, follow the Display Voltage Frequency Switching -
> +      * Sequence After Frequency Change.
> +      *
> +      * We handle this step in bxt_set_cdclk().
> +      */
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.h 
> b/drivers/gpu/drm/i915/display/intel_snps_phy.h
> new file mode 100644
> index 000000000000..205ab46f0b67
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#ifndef __INTEL_SNPS_PHY_H__
> +#define __INTEL_SNPS_PHY_H__
> +
> +struct intel_encoder;
> +struct intel_crtc_state;
> +
> +int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
> +                        struct intel_encoder *encoder);
> +void intel_mpllb_enable(struct intel_encoder *encoder,
> +                     const struct intel_crtc_state *crtc_state);
> +void intel_mpllb_disable(struct intel_encoder *encoder);
> +
> +#endif /* __INTEL_SNPS_PHY_H__ */
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 45cc76f88738..37d82cbfba6b 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2286,6 +2286,57 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
>  #define   MG_DP_MODE_CFG_DP_X2_MODE                  (1 << 7)
>  #define   MG_DP_MODE_CFG_DP_X1_MODE                  (1 << 6)
>  
> +/*
> + * DG2 SNPS PHY registers (TC1 = PHY_E)
> + */
> +#define _SNPS_PHY_A_BASE                     0x168000
> +#define _SNPS_PHY_B_BASE                     0x169000
> +#define _SNPS_PHY(phy)                               _PHY(phy, \
> +                                                  _SNPS_PHY_A_BASE, \
> +                                                  _SNPS_PHY_B_BASE)
> +#define _SNPS2(phy, reg)                     (_SNPS_PHY(phy) - \
> +                                              _SNPS_PHY_A_BASE + (reg))
> +#define _MMIO_SNPS(phy, reg)                 _MMIO(_SNPS2(phy, reg))
> +#define _MMIO_SNPS_LN(ln, phy, reg)          _MMIO(_SNPS2(phy, \
> +                                                          (reg) + (ln) * 
> 0x10))
> +
> +#define SNPS_PHY_MPLLB_CP(phy)                       _MMIO_SNPS(phy, 
> 0x168000)
> +#define   SNPS_PHY_MPLLB_CP_INT                      REG_GENMASK(31, 25)
> +#define   SNPS_PHY_MPLLB_CP_INT_GS           REG_GENMASK(23, 17)
> +#define   SNPS_PHY_MPLLB_CP_PROP             REG_GENMASK(15, 9)
> +#define   SNPS_PHY_MPLLB_CP_PROP_GS          REG_GENMASK(7, 1)
> +
> +#define SNPS_PHY_MPLLB_DIV(phy)                      _MMIO_SNPS(phy, 
> 0x168004)
> +#define   SNPS_PHY_MPLLB_FORCE_EN            REG_BIT(31)
> +#define   SNPS_PHY_MPLLB_DIV5_CLK_EN         REG_BIT(29)
> +#define   SNPS_PHY_MPLLB_V2I                 REG_GENMASK(27, 26)
> +#define   SNPS_PHY_MPLLB_FREQ_VCO            REG_GENMASK(25, 24)
> +#define   SNPS_PHY_MPLLB_PMIX_EN             REG_BIT(10)
> +#define   SNPS_PHY_MPLLB_TX_CLK_DIV          REG_GENMASK(7, 5)
> +
> +#define SNPS_PHY_MPLLB_FRACN1(phy)           _MMIO_SNPS(phy, 0x168008)
> +#define   SNPS_PHY_MPLLB_FRACN_EN            REG_BIT(31)
> +#define   SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN REG_BIT(30)
> +#define   SNPS_PHY_MPLLB_FRACN_DEN           REG_GENMASK(15, 0)
> +
> +#define SNPS_PHY_MPLLB_FRACN2(phy)           _MMIO_SNPS(phy, 0x16800C)
> +#define   SNPS_PHY_MPLLB_FRACN_REM           REG_GENMASK(31, 16)
> +#define   SNPS_PHY_MPLLB_FRACN_QUOT          REG_GENMASK(15, 0)
> +
> +#define SNPS_PHY_MPLLB_SSCEN(phy)            _MMIO_SNPS(phy, 0x168014)
> +#define   SNPS_PHY_MPLLB_SSC_EN                      REG_BIT(31)
> +#define   SNPS_PHY_MPLLB_SSC_PEAK            REG_GENMASK(29, 10)
> +
> +#define SNPS_PHY_MPLLB_SSCSTEP(phy)          _MMIO_SNPS(phy, 0x168018)
> +#define   SNPS_PHY_MPLLB_SSC_STEPSIZE                REG_GENMASK(31, 11)
> +
> +#define SNPS_PHY_MPLLB_DIV2(phy)             _MMIO_SNPS(phy, 0x16801C)
> +#define   SNPS_PHY_MPLLB_REF_CLK_DIV         REG_GENMASK(14, 12)
> +#define   SNPS_PHY_MPLLB_MULTIPLIER          REG_GENMASK(11, 0)
> +
> +#define SNPS_PHY_REF_CONTROL(phy)            _MMIO_SNPS(phy, 0x168188)
> +#define   SNPS_PHY_REF_CONTROL_REF_RANGE     REG_GENMASK(31, 27)
> +
>  /* The spec defines this only for BXT PHY0, but lets assume that this
>   * would exist for PHY1 too if it had a second channel.
>   */
> @@ -10608,6 +10659,11 @@ enum skl_power_gate {
>  #define CNL_DPLL_ENABLE(pll) _MMIO_PLL3(pll, DPLL0_ENABLE, DPLL1_ENABLE, \
>                                          _ADLS_DPLL2_ENABLE, 
> _ADLS_DPLL3_ENABLE)
>  
> +#define _DG2_PLL3_ENABLE     0x4601C
> +
> +#define DG2_PLL_ENABLE(pll) _MMIO_PLL3(pll, DPLL0_ENABLE, DPLL1_ENABLE, \
> +                                    _ADLS_DPLL2_ENABLE, _DG2_PLL3_ENABLE)
> +
>  #define TBT_PLL_ENABLE               _MMIO(0x46020)
>  
>  #define _MG_PLL1_ENABLE              0x46030
> -- 
> 2.25.4
> 
> _______________________________________________
> 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