public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Matt Atwood <matthew.s.atwood@intel.com>
To: Matt Roper <matthew.d.roper@intel.com>;, intel-gfx@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH v2 42/50] drm/i915/dg2: Add MPLLB programming for HDMI
Date: Fri, 16 Jul 2021 14:13:21 -0700	[thread overview]
Message-ID: <20210716211321.GC19458@msatwood-mobl> (raw)
In-Reply-To: <20210714031540.3539704-43-matthew.d.roper@intel.com>

On Tue, Jul 13, 2021 at 08:15:32PM -0700, Matt Roper wrote:
> At the moment we don't have a proper algorithm that can be used to
> calculate PHY settings for arbitrary HDMI link rates.  The PHY tables
> here should support the regular modes of real-world HDMI monitors.
> 
> Bspec: 54032
> Cc: Matt Atwood <matthew.s.atwood@intel.com>
> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> Signed-off-by: Vandita Kulkarni <vandita.kulkarni@intel.com>
Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c      |  14 +-
>  drivers/gpu/drm/i915/display/intel_display.c  |  47 +++
>  drivers/gpu/drm/i915/display/intel_hdmi.c     |  11 +
>  drivers/gpu/drm/i915/display/intel_snps_phy.c | 286 +++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_snps_phy.h |   7 +
>  drivers/gpu/drm/i915/i915_reg.h               |   3 +
>  6 files changed, 355 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 26a3aa73fcc4..929a95ddb316 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -51,6 +51,7 @@
>  #include "intel_panel.h"
>  #include "intel_pps.h"
>  #include "intel_psr.h"
> +#include "intel_snps_phy.h"
>  #include "intel_sprite.h"
>  #include "intel_tc.h"
>  #include "intel_vdsc.h"
> @@ -3745,6 +3746,15 @@ void intel_ddi_get_clock(struct intel_encoder *encoder,
>  						     &crtc_state->dpll_hw_state);
>  }
>  
> +static void dg2_ddi_get_config(struct intel_encoder *encoder,
> +				struct intel_crtc_state *crtc_state)
> +{
> +	intel_mpllb_readout_hw_state(encoder, &crtc_state->mpllb_state);
> +	crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->mpllb_state);
> +
> +	intel_ddi_get_config(encoder, crtc_state);
> +}
> +
>  static void adls_ddi_get_config(struct intel_encoder *encoder,
>  				struct intel_crtc_state *crtc_state)
>  {
> @@ -4606,7 +4616,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
>  	encoder->cloneable = 0;
>  	encoder->pipe_mask = ~0;
>  
> -	if (IS_ALDERLAKE_S(dev_priv)) {
> +	if (IS_DG2(dev_priv)) {
> +		encoder->get_config = dg2_ddi_get_config;
> +	} else if (IS_ALDERLAKE_S(dev_priv)) {
>  		encoder->enable_clock = adls_ddi_enable_clock;
>  		encoder->disable_clock = adls_ddi_disable_clock;
>  		encoder->is_clock_enabled = adls_ddi_is_clock_enabled;
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 2357b79d6577..6f532b695b29 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -9113,6 +9113,52 @@ verify_shared_dpll_state(struct intel_crtc *crtc,
>  	}
>  }
>  
> +static void
> +verify_mpllb_state(struct intel_atomic_state *state,
> +		   struct intel_crtc_state *new_crtc_state)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_mpllb_state mpllb_hw_state = { 0 };
> +	struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->mpllb_state;
> +	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
> +	struct intel_encoder *encoder;
> +
> +	if (!IS_DG2(i915))
> +		return;
> +
> +	if (!new_crtc_state->hw.active)
> +		return;
> +
> +	encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
> +	intel_mpllb_readout_hw_state(encoder, &mpllb_hw_state);
> +
> +#define MPLLB_CHECK(name) do { \
> +	if (mpllb_sw_state->name != mpllb_hw_state.name) { \
> +		pipe_config_mismatch(false, crtc, "MPLLB:" __stringify(name), \
> +				     "(expected 0x%08x, found 0x%08x)", \
> +				     mpllb_sw_state->name, \
> +				     mpllb_hw_state.name); \
> +	} \
> +} while (0)
> +
> +	MPLLB_CHECK(mpllb_cp);
> +	MPLLB_CHECK(mpllb_div);
> +	MPLLB_CHECK(mpllb_div2);
> +	MPLLB_CHECK(mpllb_fracn1);
> +	MPLLB_CHECK(mpllb_fracn2);
> +	MPLLB_CHECK(mpllb_sscen);
> +	MPLLB_CHECK(mpllb_sscstep);
> +
> +	/*
> +	 * ref_control is handled by the hardware/firemware and never
> +	 * programmed by the software, but the proper values are supplied
> +	 * in the bspec for verification purposes.
> +	 */
> +	MPLLB_CHECK(ref_control);
> +
> +#undef MPLLB_CHECK
> +}
> +
>  static void
>  intel_modeset_verify_crtc(struct intel_crtc *crtc,
>  			  struct intel_atomic_state *state,
> @@ -9126,6 +9172,7 @@ intel_modeset_verify_crtc(struct intel_crtc *crtc,
>  	verify_connector_state(state, crtc);
>  	verify_crtc_state(crtc, old_crtc_state, new_crtc_state);
>  	verify_shared_dpll_state(crtc, old_crtc_state, new_crtc_state);
> +	verify_mpllb_state(state, new_crtc_state);
>  }
>  
>  static void
> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> index 852af2b23540..b04685bb6439 100644
> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> @@ -51,6 +51,7 @@
>  #include "intel_hdmi.h"
>  #include "intel_lspcon.h"
>  #include "intel_panel.h"
> +#include "intel_snps_phy.h"
>  
>  static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
>  {
> @@ -1850,6 +1851,16 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
>  	if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000)
>  		return MODE_CLOCK_RANGE;
>  
> +	/*
> +	 * SNPS PHYs' MPLLB table-based programming can only handle a fixed
> +	 * set of link rates.
> +	 *
> +	 * FIXME: We will hopefully get an algorithmic way of programming
> +	 * the MPLLB for HDMI in the future.
> +	 */
> +	if (IS_DG2(dev_priv))
> +		return intel_snps_phy_check_hdmi_link_rate(clock);
> +
>  	return MODE_OK;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c
> index 6d9205906595..1317b4e94b50 100644
> --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c
> +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
> @@ -3,6 +3,8 @@
>   * Copyright © 2019 Intel Corporation
>   */
>  
> +#include <linux/util_macros.h>
> +
>  #include "intel_de.h"
>  #include "intel_display_types.h"
>  #include "intel_snps_phy.h"
> @@ -375,14 +377,172 @@ static const struct intel_mpllb_state *dg2_edp_tables[] = {
>  	NULL,
>  };
>  
> -int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
> -			   struct intel_encoder *encoder)
> -{
> -	const struct intel_mpllb_state **tables;
> -	int i;
> +/*
> + * HDMI link rates with 100 MHz reference clock.
> + */
> +
> +static const struct intel_mpllb_state dg2_hdmi_25_175 = {
> +	.clock = 25175,
> +	.ref_control =
> +		REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +	.mpllb_cp =
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
> +	.mpllb_div =
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) |
> +		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, 128) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
> +	.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, 143),
> +	.mpllb_fracn2 =
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 36663) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 71),
> +	.mpllb_sscen =
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
> +};
> +
> +static const struct intel_mpllb_state dg2_hdmi_27_0 = {
> +	.clock = 27000,
> +	.ref_control =
> +		REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
> +	.mpllb_cp =
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
> +	.mpllb_div =
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) |
> +		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, 140) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
> +	.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_UP_SPREAD, 1),
> +};
> +
> +static const struct intel_mpllb_state dg2_hdmi_74_25 = {
> +	.clock = 74250,
> +	.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, 15) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
> +	.mpllb_div =
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) |
> +		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, 86) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
> +	.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_UP_SPREAD, 1),
> +};
> +
> +static const struct intel_mpllb_state dg2_hdmi_148_5 = {
> +	.clock = 148500,
> +	.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, 15) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
> +	.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, 3),
> +	.mpllb_div2 =
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
> +	.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_UP_SPREAD, 1),
> +};
> +
> +static const struct intel_mpllb_state dg2_hdmi_594 = {
> +	.clock = 594000,
> +	.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, 15) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
> +	.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, 86) |
> +		REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
> +	.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_UP_SPREAD, 1),
> +};
>  
> +static const struct intel_mpllb_state *dg2_hdmi_tables[] = {
> +	&dg2_hdmi_25_175,
> +	&dg2_hdmi_27_0,
> +	&dg2_hdmi_74_25,
> +	&dg2_hdmi_148_5,
> +	&dg2_hdmi_594,
> +	NULL,
> +};
> +
> +static const struct intel_mpllb_state **
> +intel_mpllb_tables_get(struct intel_crtc_state *crtc_state,
> +		       struct intel_encoder *encoder)
> +{
>  	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
> -		tables = dg2_edp_tables;
> +		return dg2_edp_tables;
>  	} else if (intel_crtc_has_dp_encoder(crtc_state)) {
>  		/*
>  		 * FIXME: Initially we're just enabling the "combo" outputs on
> @@ -397,15 +557,41 @@ int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
>  		 * that to determine which table to use.
>  		 */
>  		if (0)
> -			tables = dg2_dp_38_4_tables;
> +			return dg2_dp_38_4_tables;
>  		else
> -			tables = dg2_dp_100_tables;
> -	} else {
> -		/* TODO: Add HDMI support */
> -		MISSING_CASE(encoder->type);
> -		return -EINVAL;
> +			return dg2_dp_100_tables;
> +	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
> +		return dg2_hdmi_tables;
>  	}
>  
> +	MISSING_CASE(encoder->type);
> +	return 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_HDMI)) {
> +		if (intel_snps_phy_check_hdmi_link_rate(crtc_state->port_clock)
> +		    != MODE_OK) {
> +			/*
> +			 * FIXME: Can only support fixed HDMI frequencies
> +			 * until we have a proper algorithm under a valid
> +			 * license.
> +			 */
> +			DRM_DEBUG_KMS("Can't support HDMI link rate %d\n",
> +				      crtc_state->port_clock);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	tables = intel_mpllb_tables_get(crtc_state, encoder);
> +	if (!tables)
> +		return -EINVAL;
> +
>  	for (i = 0; tables[i]; i++) {
>  		if (crtc_state->port_clock <= tables[i]->clock) {
>  			crtc_state->mpllb_state = *tables[i];
> @@ -515,3 +701,79 @@ void intel_mpllb_disable(struct intel_encoder *encoder)
>  	 * We handle this step in bxt_set_cdclk().
>  	 */
>  }
> +
> +int intel_mpllb_calc_port_clock(struct intel_encoder *encoder,
> +				const struct intel_mpllb_state *pll_state)
> +{
> +	unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
> +	unsigned int multiplier, tx_clk_div, refclk;
> +	bool frac_en;
> +
> +	if (0)
> +		refclk = 38400;
> +	else
> +		refclk = 100000;
> +
> +	refclk >>= REG_FIELD_GET(SNPS_PHY_MPLLB_REF_CLK_DIV, pll_state->mpllb_div2) - 1;
> +
> +	frac_en = REG_FIELD_GET(SNPS_PHY_MPLLB_FRACN_EN, pll_state->mpllb_fracn1);
> +
> +	if (frac_en) {
> +		frac_quot = REG_FIELD_GET(SNPS_PHY_MPLLB_FRACN_QUOT, pll_state->mpllb_fracn2);
> +		frac_rem = REG_FIELD_GET(SNPS_PHY_MPLLB_FRACN_REM, pll_state->mpllb_fracn2);
> +		frac_den = REG_FIELD_GET(SNPS_PHY_MPLLB_FRACN_DEN, pll_state->mpllb_fracn1);
> +	}
> +
> +	multiplier = REG_FIELD_GET(SNPS_PHY_MPLLB_MULTIPLIER, pll_state->mpllb_div2) / 2 + 16;
> +
> +	tx_clk_div = REG_FIELD_GET(SNPS_PHY_MPLLB_TX_CLK_DIV, pll_state->mpllb_div);
> +
> +	return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) +
> +				     DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den),
> +				     10 << (tx_clk_div + 16));
> +}
> +
> +void intel_mpllb_readout_hw_state(struct intel_encoder *encoder,
> +				  struct intel_mpllb_state *pll_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
> +
> +	pll_state->mpllb_cp = intel_de_read(dev_priv, SNPS_PHY_MPLLB_CP(phy));
> +	pll_state->mpllb_div = intel_de_read(dev_priv, SNPS_PHY_MPLLB_DIV(phy));
> +	pll_state->mpllb_div2 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_DIV2(phy));
> +	pll_state->mpllb_sscen = intel_de_read(dev_priv, SNPS_PHY_MPLLB_SSCEN(phy));
> +	pll_state->mpllb_sscstep = intel_de_read(dev_priv, SNPS_PHY_MPLLB_SSCSTEP(phy));
> +	pll_state->mpllb_fracn1 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_FRACN1(phy));
> +	pll_state->mpllb_fracn2 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_FRACN2(phy));
> +
> +	/*
> +	 * REF_CONTROL is under firmware control and never programmed by the
> +	 * driver; we read it only for sanity checking purposes.  The bspec
> +	 * only tells us the expected value for one field in this register,
> +	 * so we'll only read out those specific bits here.
> +	 */
> +	pll_state->ref_control = intel_de_read(dev_priv, SNPS_PHY_REF_CONTROL(phy)) &
> +		SNPS_PHY_REF_CONTROL_REF_RANGE;
> +
> +	/*
> +	 * MPLLB_DIV is programmed twice, once with the software-computed
> +	 * state, then again with the MPLLB_FORCE_EN bit added.  Drop that
> +	 * extra bit during readout so that we return the actual expected
> +	 * software state.
> +	 */
> +	pll_state->mpllb_div &= ~SNPS_PHY_MPLLB_FORCE_EN;
> +}
> +
> +int intel_snps_phy_check_hdmi_link_rate(int clock)
> +{
> +	const struct intel_mpllb_state **tables = dg2_hdmi_tables;
> +	int i;
> +
> +	for (i = 0; tables[i]; i++) {
> +		if (clock == tables[i]->clock)
> +			return MODE_OK;
> +	}
> +
> +	return MODE_CLOCK_RANGE;
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.h b/drivers/gpu/drm/i915/display/intel_snps_phy.h
> index 205ab46f0b67..ca4c2a25182b 100644
> --- a/drivers/gpu/drm/i915/display/intel_snps_phy.h
> +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.h
> @@ -8,11 +8,18 @@
>  
>  struct intel_encoder;
>  struct intel_crtc_state;
> +struct intel_mpllb_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);
> +void intel_mpllb_readout_hw_state(struct intel_encoder *encoder,
> +				  struct intel_mpllb_state *pll_state);
> +int intel_mpllb_calc_port_clock(struct intel_encoder *encoder,
> +				const struct intel_mpllb_state *pll_state);
> +
> +int intel_snps_phy_check_hdmi_link_rate(int clock);
>  
>  #endif /* __INTEL_SNPS_PHY_H__ */
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 1422fbce36cb..92408b4e2730 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2325,12 +2325,15 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
>  
>  #define SNPS_PHY_MPLLB_SSCEN(phy)		_MMIO_SNPS(phy, 0x168014)
>  #define   SNPS_PHY_MPLLB_SSC_EN			REG_BIT(31)
> +#define   SNPS_PHY_MPLLB_SSC_UP_SPREAD		REG_BIT(30)
>  #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_HDMI_PIXEL_CLK_DIV	REG_GENMASK(19, 18)
> +#define   SNPS_PHY_MPLLB_HDMI_DIV		REG_GENMASK(17, 15)
>  #define   SNPS_PHY_MPLLB_REF_CLK_DIV		REG_GENMASK(14, 12)
>  #define   SNPS_PHY_MPLLB_MULTIPLIER		REG_GENMASK(11, 0)
>  
> -- 
> 2.25.4
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2021-07-16 21:13 UTC|newest]

Thread overview: 88+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-14  3:14 [Intel-gfx] [PATCH v2 00/50] Begin enabling Xe_HP SDV and DG2 platforms Matt Roper
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 01/50] drm/i915: Add XE_HP initial definitions Matt Roper
2021-07-19 18:05   ` Souza, Jose
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 02/50] drm/i915: Fork DG1 interrupt handler Matt Roper
2021-07-19 21:18   ` Matt Atwood
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 03/50] drm/i915/xehp: VDBOX/VEBOX fusing registers are enable-based Matt Roper
2021-07-19 21:20   ` Matt Atwood
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 04/50] drm/i915/gen12: Use fuse info to enable SFC Matt Roper
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 05/50] drm/i915/selftests: Allow for larger engine counts Matt Roper
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 06/50] drm/i915/xehp: Extra media engines - Part 1 (engine definitions) Matt Roper
2021-07-20 23:03   ` Lucas De Marchi
2021-07-20 23:40     ` John Harrison
2021-07-20 23:49       ` Lucas De Marchi
2021-07-21 18:23   ` Lucas De Marchi
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 07/50] drm/i915/xehp: Extra media engines - Part 2 (interrupts) Matt Roper
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 08/50] drm/i915/xehp: Extra media engines - Part 3 (reset) Matt Roper
2021-07-19 18:13   ` Souza, Jose
2021-07-20 20:39   ` Matt Atwood
2021-07-14  3:14 ` [Intel-gfx] [PATCH v2 09/50] drm/i915/xehp: Xe_HP forcewake support Matt Roper
2021-07-20 20:57   ` Matt Atwood
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 10/50] drm/i915/xehp: Define multicast register ranges Matt Roper
2021-07-19 18:19   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 11/50] drm/i915/xehp: Handle new device context ID format Matt Roper
2021-07-20 21:39   ` Matt Atwood
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 12/50] drm/i915/xehp: New engine context offsets Matt Roper
2021-07-20 22:06   ` Matt Atwood
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 13/50] drm/i915/xehp: handle new steering options Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 14/50] drm/i915/xehp: Loop over all gslices for INSTDONE processing Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 15/50] drm/i915/xehpsdv: add initial XeHP SDV definitions Matt Roper
2021-07-19 18:20   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 16/50] drm/i915/xehp: Changes to ss/eu definitions Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 17/50] drm/i915/xehpsdv: Add maximum sseu limits Matt Roper
2021-07-18 13:10   ` Yokoyama, Caz
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 18/50] drm/i915/xehpsdv: Add compute DSS type Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 19/50] drm/i915/xehpsdv: Define steering tables Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 20/50] drm/i915/xehpsdv: Define MOCS table for XeHP SDV Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 21/50] drm/i915/xehpsdv: factor out function to read RP_STATE_CAP Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 22/50] drm/i915/xehpsdv: Read correct RP_STATE_CAP register Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 23/50] drm/i915/dg2: add DG2 platform info Matt Roper
2021-07-19 18:21   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 24/50] drm/i915/dg2: DG2 uses the same sseu limits as XeHP SDV Matt Roper
2021-07-16 16:06   ` Yokoyama, Caz
2021-07-19 18:22   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 25/50] drm/i915/dg2: Add forcewake table Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 26/50] drm/i915/dg2: Update LNCF steering ranges Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 27/50] drm/i915/dg2: Add SQIDI steering Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 28/50] drm/i915/dg2: Add new LRI reg offsets Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 29/50] drm/i915/dg2: Maintain backward-compatible nested batch behavior Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 30/50] drm/i915/dg2: Report INSTDONE_GEOM values in error state Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 31/50] drm/i915/dg2: Define MOCS table for DG2 Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 32/50] drm/i915/dg2: Add fake PCH Matt Roper
2021-07-16 19:52   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 33/50] drm/i915/dg2: Add cdclk table and reference clock Matt Roper
2021-07-16 19:36   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 34/50] drm/i915/dg2: Skip shared DPLL handling Matt Roper
2021-07-16 19:38   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 35/50] drm/i915/dg2: Don't wait for AUX power well enable ACKs Matt Roper
2021-07-16 19:40   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 36/50] drm/i915/dg2: Setup display outputs Matt Roper
2021-07-16 19:40   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 37/50] drm/i915/dg2: Add dbuf programming Matt Roper
2021-07-16 19:45   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 38/50] drm/i915/dg2: Don't program BW_BUDDY registers Matt Roper
2021-07-16 19:47   ` Souza, Jose
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 39/50] drm/i915/dg2: Don't read DRAM info Matt Roper
2021-07-15 17:17   ` Srivatsa, Anusha
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 40/50] drm/i915/dg2: DG2 has fixed memory bandwidth Matt Roper
2021-07-21 17:42   ` Srivatsa, Anusha
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 41/50] drm/i915/dg2: Add MPLLB programming for SNPS PHY Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 42/50] drm/i915/dg2: Add MPLLB programming for HDMI Matt Roper
2021-07-16 21:13   ` Matt Atwood [this message]
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 43/50] drm/i915/dg2: Add vswing programming for SNPS phys Matt Roper
2021-07-16 21:38   ` Matt Atwood
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 44/50] drm/i915/dg2: Update modeset sequences Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 45/50] drm/i915/dg2: Classify DG2 PHY types Matt Roper
2021-07-16 20:50   ` Matt Atwood
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 46/50] drm/i915/dg2: Wait for SNPS PHY calibration during display init Matt Roper
2021-07-16 20:52   ` Matt Atwood
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 47/50] drm/i915/dg2: Update lane disable power state during PSR Matt Roper
2021-07-21 17:55   ` Srivatsa, Anusha
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 48/50] drm/i915/dg2: Add DG2 to the PSR2 defeature list Matt Roper
2021-07-21 17:56   ` Srivatsa, Anusha
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 49/50] drm/i915/dg2: Update to bigjoiner path Matt Roper
2021-07-14  3:15 ` [Intel-gfx] [PATCH v2 50/50] drm/i915/dg2: Configure PCON in DP pre-enable path Matt Roper
2021-07-14  4:23 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for Begin enabling Xe_HP SDV and DG2 platforms (rev5) Patchwork
2021-07-14  4:24 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2021-07-14  4:51 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2021-07-14 15:12 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210716211321.GC19458@msatwood-mobl \
    --to=matthew.s.atwood@intel.com \
    --cc=matthew.d.roper@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox