diff mbox series

[1/2] drm/i915/display: Drop crtc_state from C10/C20 pll programming

Message ID 20250129130105.198817-2-mika.kahola@intel.com (mailing list archive)
State New
Headers show
Series drm/i915/display: Allow display PHYs to reset power state | expand

Commit Message

Kahola, Mika Jan. 29, 2025, 1:01 p.m. UTC
For PLL programming for C10 and C20 we don't need to
carry crtc_state but instead use only necessary parts
of the crtc_state i.e. pll_state.

Signed-off-by: Mika Kahola <mika.kahola@intel.com>
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 109 +++++++++++--------
 1 file changed, 64 insertions(+), 45 deletions(-)

Comments

Jani Nikula Jan. 29, 2025, 2:40 p.m. UTC | #1
On Wed, 29 Jan 2025, Mika Kahola <mika.kahola@intel.com> wrote:
> For PLL programming for C10 and C20 we don't need to
> carry crtc_state but instead use only necessary parts
> of the crtc_state i.e. pll_state.

This is not a good enough justification alone. Usually we pass
crtc_state around because we're going to need more stuff from there
anyway. In that case, someone's going to have to reverse this, or pass a
bunch more parameters than just "is_dp".

I see that you're doing this because you actually need this in a context
that doens't have crtc_state. Then *that* needs to be the rationale.

Even so, there's a good chance this will bite us later.


BR,
Jani.


>
> Signed-off-by: Mika Kahola <mika.kahola@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_cx0_phy.c | 109 +++++++++++--------
>  1 file changed, 64 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> index 48b0b9755b2b..bffe3d4bbe8b 100644
> --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> @@ -2021,13 +2021,12 @@ intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
>  	return NULL;
>  }
>  
> -static void intel_cx0pll_update_ssc(struct intel_crtc_state *crtc_state,
> -				    struct intel_encoder *encoder)
> +static void intel_cx0pll_update_ssc(struct intel_encoder *encoder,
> +				    struct intel_cx0pll_state *pll_state, bool is_dp)
>  {
>  	struct intel_display *display = to_intel_display(encoder);
> -	struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
>  
> -	if (intel_crtc_has_dp_encoder(crtc_state)) {
> +	if (is_dp) {
>  		if (intel_panel_use_ssc(display)) {
>  			struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>  			pll_state->ssc_enabled =
> @@ -2036,11 +2035,10 @@ static void intel_cx0pll_update_ssc(struct intel_crtc_state *crtc_state,
>  	}
>  }
>  
> -static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
> -				    struct intel_encoder *encoder)
> +static void intel_c10pll_update_pll(struct intel_encoder *encoder,
> +				    struct intel_cx0pll_state *pll_state, bool is_dp)
>  {
>  	struct intel_display *display = to_intel_display(encoder);
> -	struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
>  	int i;
>  
>  	if (pll_state->ssc_enabled)
> @@ -2051,32 +2049,49 @@ static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
>  		pll_state->c10.pll[i] = 0;
>  }
>  
> +static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
> +					      const struct intel_c10pll_state * const *tables, int port_clock, bool is_dp,
> +					      struct intel_cx0pll_state *pll_state)
> +{
> +	int i;
> +
> +	for (i = 0; tables[i]; i++) {
> +		if (port_clock == tables[i]->clock) {
> +			pll_state->c10 = *tables[i];
> +			intel_cx0pll_update_ssc(encoder, pll_state, is_dp);
> +			intel_c10pll_update_pll(encoder, pll_state, is_dp);
> +			pll_state->use_c10 = true;
> +
> +			return 0;
> +		}
> +	}
> +
> +	return -EINVAL;
> +}
> +
>  static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
>  				   struct intel_encoder *encoder)
>  {
>  	const struct intel_c10pll_state * const *tables;
> -	int i;
> +	int val;
>  
>  	tables = intel_c10pll_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->dpll_hw_state.cx0pll.c10 = *tables[i];
> -			intel_cx0pll_update_ssc(crtc_state, encoder);
> -			intel_c10pll_update_pll(crtc_state, encoder);
> -			crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
> -
> -			return 0;
> -		}
> -	}
> +	val = intel_c10pll_calc_state_from_table(encoder, tables,
> +						 crtc_state->port_clock, intel_crtc_has_dp_encoder(crtc_state),
> +						 &crtc_state->dpll_hw_state.cx0pll);
> +	if (val == 0)
> +		return 0;
>  
>  	/* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */
>  	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
>  		intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10,
>  						   crtc_state->port_clock);
> -		intel_c10pll_update_pll(crtc_state, encoder);
> +		intel_c10pll_update_pll(encoder,
> +					&crtc_state->dpll_hw_state.cx0pll,
> +					intel_crtc_has_dp_encoder(crtc_state));
>  		crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
>  
>  		return 0;
> @@ -2112,10 +2127,9 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
>  }
>  
>  static void intel_c10_pll_program(struct intel_display *display,
> -				  const struct intel_crtc_state *crtc_state,
> -				  struct intel_encoder *encoder)
> +				  struct intel_encoder *encoder,
> +				  const struct intel_c10pll_state *pll_state)
>  {
> -	const struct intel_c10pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c10;
>  	int i;
>  
>  	intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
> @@ -2334,7 +2348,9 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
>  	for (i = 0; tables[i]; i++) {
>  		if (crtc_state->port_clock == tables[i]->clock) {
>  			crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i];
> -			intel_cx0pll_update_ssc(crtc_state, encoder);
> +			intel_cx0pll_update_ssc(encoder,
> +						&crtc_state->dpll_hw_state.cx0pll,
> +						intel_crtc_has_dp_encoder(crtc_state));
>  			crtc_state->dpll_hw_state.cx0pll.use_c10 = false;
>  			return 0;
>  		}
> @@ -2600,19 +2616,14 @@ static int intel_get_c20_custom_width(u32 clock, bool dp)
>  }
>  
>  static void intel_c20_pll_program(struct intel_display *display,
> -				  const struct intel_crtc_state *crtc_state,
> -				  struct intel_encoder *encoder)
> +				  struct intel_encoder *encoder,
> +				  const struct intel_c20pll_state *pll_state,
> +				  int clock, bool dp)
>  {
> -	const struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
> -	bool dp = false;
>  	u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
> -	u32 clock = crtc_state->port_clock;
>  	bool cntx;
>  	int i;
>  
> -	if (intel_crtc_has_dp_encoder(crtc_state))
> -		dp = true;
> -
>  	/* 1. Read current context selection */
>  	cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0);
>  
> @@ -2736,7 +2747,8 @@ static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
>  }
>  
>  static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
> -					 const struct intel_crtc_state *crtc_state,
> +					 const struct intel_cx0pll_state *pll_state,
> +					 bool is_dp, int port_clock,
>  					 bool lane_reversal)
>  {
>  	struct intel_display *display = to_intel_display(encoder);
> @@ -2751,18 +2763,17 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
>  
>  	val |= XELPDP_FORWARD_CLOCK_UNGATE;
>  
> -	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
> -	    is_hdmi_frl(crtc_state->port_clock))
> +	if (!is_dp && is_hdmi_frl(port_clock))
>  		val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
>  	else
>  		val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
>  
>  	/* TODO: HDMI FRL */
>  	/* DP2.0 10G and 20G rates enable MPLLA*/
> -	if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000)
> -		val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
> +	if (port_clock == 1000000 || port_clock == 2000000)
> +		val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
>  	else
> -		val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
> +		val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
>  
>  	intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
>  		     XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
> @@ -2992,8 +3003,9 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
>  	return val;
>  }
>  
> -static void intel_cx0pll_enable(struct intel_encoder *encoder,
> -				const struct intel_crtc_state *crtc_state)
> +static void __intel_cx0pll_enable(struct intel_encoder *encoder,
> +				  const struct intel_cx0pll_state *pll_state,
> +				  bool is_dp, int port_clock, int lane_count)
>  {
>  	struct intel_display *display = to_intel_display(encoder);
>  	enum phy phy = intel_encoder_to_phy(encoder);
> @@ -3007,7 +3019,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
>  	 * 1. Program PORT_CLOCK_CTL REGISTER to configure
>  	 * clock muxes, gating and SSC
>  	 */
> -	intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
> +	intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal);
>  
>  	/* 2. Bring PHY out of reset. */
>  	intel_cx0_phy_lane_reset(encoder, lane_reversal);
> @@ -3027,15 +3039,15 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
>  
>  	/* 5. Program PHY internal PLL internal registers. */
>  	if (intel_encoder_is_c10phy(encoder))
> -		intel_c10_pll_program(display, crtc_state, encoder);
> +		intel_c10_pll_program(display, encoder, &pll_state->c10);
>  	else
> -		intel_c20_pll_program(display, crtc_state, encoder);
> +		intel_c20_pll_program(display, encoder, &pll_state->c20, port_clock, is_dp);
>  
>  	/*
>  	 * 6. Program the enabled and disabled owned PHY lane
>  	 * transmitters over message bus
>  	 */
> -	intel_cx0_program_phy_lane(encoder, crtc_state->lane_count, lane_reversal);
> +	intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal);
>  
>  	/*
>  	 * 7. Follow the Display Voltage Frequency Switching - Sequence
> @@ -3046,8 +3058,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
>  	 * 8. Program DDI_CLK_VALFREQ to match intended DDI
>  	 * clock frequency.
>  	 */
> -	intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
> -		       crtc_state->port_clock);
> +	intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock);
>  
>  	/*
>  	 * 9. Set PORT_CLOCK_CTL register PCLK PLL Request
> @@ -3074,6 +3085,14 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
>  	intel_cx0_phy_transaction_end(encoder, wakeref);
>  }
>  
> +static void intel_cx0pll_enable(struct intel_encoder *encoder,
> +				const struct intel_crtc_state *crtc_state)
> +{
> +	__intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll,
> +			      intel_crtc_has_dp_encoder(crtc_state), crtc_state->port_clock, crtc_state->lane_count);
> +
> +}
> +
>  int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
>  {
>  	struct intel_display *display = to_intel_display(encoder);
Kahola, Mika Jan. 30, 2025, 9:26 a.m. UTC | #2
> -----Original Message-----
> From: Jani Nikula <jani.nikula@linux.intel.com>
> Sent: Wednesday, 29 January 2025 16.40
> To: Kahola, Mika <mika.kahola@intel.com>; intel-gfx@lists.freedesktop.org; intel-
> xe@lists.freedesktop.org
> Cc: Deak, Imre <imre.deak@intel.com>; Kahola, Mika <mika.kahola@intel.com>
> Subject: Re: [PATCH 1/2] drm/i915/display: Drop crtc_state from C10/C20 pll
> programming
> 
> On Wed, 29 Jan 2025, Mika Kahola <mika.kahola@intel.com> wrote:
> > For PLL programming for C10 and C20 we don't need to carry crtc_state
> > but instead use only necessary parts of the crtc_state i.e. pll_state.
> 
> This is not a good enough justification alone. Usually we pass crtc_state around
> because we're going to need more stuff from there anyway. In that case,
> someone's going to have to reverse this, or pass a bunch more parameters than
> just "is_dp".
> 
> I see that you're doing this because you actually need this in a context that
> doens't have crtc_state. Then *that* needs to be the rationale.
> 
> Even so, there's a good chance this will bite us later.

We only need from crtc_state the pll_state when enabling/disabling pll's and hence this change. What was not mentioned in the commit message is that this will partially prepares the work where all pll handling is moved over to a better location i.e. intel_dpll_mgr.c file. As MTL+ with PICA chips being only platform(s) outside this file. But this change could be left for later stage and when this refactoring work is ready for review round.

Thanks!
Mika 
> 
> 
> BR,
> Jani.
> 
> 
> >
> > Signed-off-by: Mika Kahola <mika.kahola@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_cx0_phy.c | 109
> > +++++++++++--------
> >  1 file changed, 64 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > index 48b0b9755b2b..bffe3d4bbe8b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > @@ -2021,13 +2021,12 @@ intel_c10pll_tables_get(struct intel_crtc_state
> *crtc_state,
> >  	return NULL;
> >  }
> >
> > -static void intel_cx0pll_update_ssc(struct intel_crtc_state *crtc_state,
> > -				    struct intel_encoder *encoder)
> > +static void intel_cx0pll_update_ssc(struct intel_encoder *encoder,
> > +				    struct intel_cx0pll_state *pll_state, bool
> is_dp)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder);
> > -	struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
> >
> > -	if (intel_crtc_has_dp_encoder(crtc_state)) {
> > +	if (is_dp) {
> >  		if (intel_panel_use_ssc(display)) {
> >  			struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> >  			pll_state->ssc_enabled =
> > @@ -2036,11 +2035,10 @@ static void intel_cx0pll_update_ssc(struct
> intel_crtc_state *crtc_state,
> >  	}
> >  }
> >
> > -static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
> > -				    struct intel_encoder *encoder)
> > +static void intel_c10pll_update_pll(struct intel_encoder *encoder,
> > +				    struct intel_cx0pll_state *pll_state, bool
> is_dp)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder);
> > -	struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
> >  	int i;
> >
> >  	if (pll_state->ssc_enabled)
> > @@ -2051,32 +2049,49 @@ static void intel_c10pll_update_pll(struct
> intel_crtc_state *crtc_state,
> >  		pll_state->c10.pll[i] = 0;
> >  }
> >
> > +static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
> > +					      const struct intel_c10pll_state *
> const *tables, int port_clock, bool is_dp,
> > +					      struct intel_cx0pll_state *pll_state) {
> > +	int i;
> > +
> > +	for (i = 0; tables[i]; i++) {
> > +		if (port_clock == tables[i]->clock) {
> > +			pll_state->c10 = *tables[i];
> > +			intel_cx0pll_update_ssc(encoder, pll_state, is_dp);
> > +			intel_c10pll_update_pll(encoder, pll_state, is_dp);
> > +			pll_state->use_c10 = true;
> > +
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	return -EINVAL;
> > +}
> > +
> >  static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
> >  				   struct intel_encoder *encoder)  {
> >  	const struct intel_c10pll_state * const *tables;
> > -	int i;
> > +	int val;
> >
> >  	tables = intel_c10pll_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->dpll_hw_state.cx0pll.c10 = *tables[i];
> > -			intel_cx0pll_update_ssc(crtc_state, encoder);
> > -			intel_c10pll_update_pll(crtc_state, encoder);
> > -			crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
> > -
> > -			return 0;
> > -		}
> > -	}
> > +	val = intel_c10pll_calc_state_from_table(encoder, tables,
> > +						 crtc_state->port_clock,
> intel_crtc_has_dp_encoder(crtc_state),
> > +						 &crtc_state-
> >dpll_hw_state.cx0pll);
> > +	if (val == 0)
> > +		return 0;
> >
> >  	/* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed
> tables */
> >  	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
> >  		intel_snps_hdmi_pll_compute_c10pll(&crtc_state-
> >dpll_hw_state.cx0pll.c10,
> >  						   crtc_state->port_clock);
> > -		intel_c10pll_update_pll(crtc_state, encoder);
> > +		intel_c10pll_update_pll(encoder,
> > +					&crtc_state->dpll_hw_state.cx0pll,
> > +
> 	intel_crtc_has_dp_encoder(crtc_state));
> >  		crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
> >
> >  		return 0;
> > @@ -2112,10 +2127,9 @@ static void
> > intel_c10pll_readout_hw_state(struct intel_encoder *encoder,  }
> >
> >  static void intel_c10_pll_program(struct intel_display *display,
> > -				  const struct intel_crtc_state *crtc_state,
> > -				  struct intel_encoder *encoder)
> > +				  struct intel_encoder *encoder,
> > +				  const struct intel_c10pll_state *pll_state)
> >  {
> > -	const struct intel_c10pll_state *pll_state = &crtc_state-
> >dpll_hw_state.cx0pll.c10;
> >  	int i;
> >
> >  	intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES,
> PHY_C10_VDR_CONTROL(1),
> > @@ -2334,7 +2348,9 @@ static int intel_c20pll_calc_state(struct
> intel_crtc_state *crtc_state,
> >  	for (i = 0; tables[i]; i++) {
> >  		if (crtc_state->port_clock == tables[i]->clock) {
> >  			crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i];
> > -			intel_cx0pll_update_ssc(crtc_state, encoder);
> > +			intel_cx0pll_update_ssc(encoder,
> > +						&crtc_state-
> >dpll_hw_state.cx0pll,
> > +
> 	intel_crtc_has_dp_encoder(crtc_state));
> >  			crtc_state->dpll_hw_state.cx0pll.use_c10 = false;
> >  			return 0;
> >  		}
> > @@ -2600,19 +2616,14 @@ static int intel_get_c20_custom_width(u32
> > clock, bool dp)  }
> >
> >  static void intel_c20_pll_program(struct intel_display *display,
> > -				  const struct intel_crtc_state *crtc_state,
> > -				  struct intel_encoder *encoder)
> > +				  struct intel_encoder *encoder,
> > +				  const struct intel_c20pll_state *pll_state,
> > +				  int clock, bool dp)
> >  {
> > -	const struct intel_c20pll_state *pll_state = &crtc_state-
> >dpll_hw_state.cx0pll.c20;
> > -	bool dp = false;
> >  	u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
> > -	u32 clock = crtc_state->port_clock;
> >  	bool cntx;
> >  	int i;
> >
> > -	if (intel_crtc_has_dp_encoder(crtc_state))
> > -		dp = true;
> > -
> >  	/* 1. Read current context selection */
> >  	cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0,
> > PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0);
> >
> > @@ -2736,7 +2747,8 @@ static int intel_c10pll_calc_port_clock(struct
> > intel_encoder *encoder,  }
> >
> >  static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
> > -					 const struct intel_crtc_state
> *crtc_state,
> > +					 const struct intel_cx0pll_state
> *pll_state,
> > +					 bool is_dp, int port_clock,
> >  					 bool lane_reversal)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder); @@
> > -2751,18 +2763,17 @@ static void intel_program_port_clock_ctl(struct
> > intel_encoder *encoder,
> >
> >  	val |= XELPDP_FORWARD_CLOCK_UNGATE;
> >
> > -	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
> > -	    is_hdmi_frl(crtc_state->port_clock))
> > +	if (!is_dp && is_hdmi_frl(port_clock))
> >  		val |=
> XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
> >  	else
> >  		val |=
> XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
> >
> >  	/* TODO: HDMI FRL */
> >  	/* DP2.0 10G and 20G rates enable MPLLA*/
> > -	if (crtc_state->port_clock == 1000000 || crtc_state->port_clock ==
> 2000000)
> > -		val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ?
> XELPDP_SSC_ENABLE_PLLA : 0;
> > +	if (port_clock == 1000000 || port_clock == 2000000)
> > +		val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
> >  	else
> > -		val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ?
> XELPDP_SSC_ENABLE_PLLB : 0;
> > +		val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
> >
> >  	intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder-
> >port),
> >  		     XELPDP_LANE1_PHY_CLOCK_SELECT |
> XELPDP_FORWARD_CLOCK_UNGATE |
> > @@ -2992,8 +3003,9 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
> >  	return val;
> >  }
> >
> > -static void intel_cx0pll_enable(struct intel_encoder *encoder,
> > -				const struct intel_crtc_state *crtc_state)
> > +static void __intel_cx0pll_enable(struct intel_encoder *encoder,
> > +				  const struct intel_cx0pll_state *pll_state,
> > +				  bool is_dp, int port_clock, int lane_count)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder);
> >  	enum phy phy = intel_encoder_to_phy(encoder); @@ -3007,7 +3019,7
> @@
> > static void intel_cx0pll_enable(struct intel_encoder *encoder,
> >  	 * 1. Program PORT_CLOCK_CTL REGISTER to configure
> >  	 * clock muxes, gating and SSC
> >  	 */
> > -	intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
> > +	intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock,
> > +lane_reversal);
> >
> >  	/* 2. Bring PHY out of reset. */
> >  	intel_cx0_phy_lane_reset(encoder, lane_reversal); @@ -3027,15
> > +3039,15 @@ static void intel_cx0pll_enable(struct intel_encoder
> > *encoder,
> >
> >  	/* 5. Program PHY internal PLL internal registers. */
> >  	if (intel_encoder_is_c10phy(encoder))
> > -		intel_c10_pll_program(display, crtc_state, encoder);
> > +		intel_c10_pll_program(display, encoder, &pll_state->c10);
> >  	else
> > -		intel_c20_pll_program(display, crtc_state, encoder);
> > +		intel_c20_pll_program(display, encoder, &pll_state->c20,
> > +port_clock, is_dp);
> >
> >  	/*
> >  	 * 6. Program the enabled and disabled owned PHY lane
> >  	 * transmitters over message bus
> >  	 */
> > -	intel_cx0_program_phy_lane(encoder, crtc_state->lane_count,
> lane_reversal);
> > +	intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal);
> >
> >  	/*
> >  	 * 7. Follow the Display Voltage Frequency Switching - Sequence @@
> > -3046,8 +3058,7 @@ static void intel_cx0pll_enable(struct intel_encoder
> *encoder,
> >  	 * 8. Program DDI_CLK_VALFREQ to match intended DDI
> >  	 * clock frequency.
> >  	 */
> > -	intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
> > -		       crtc_state->port_clock);
> > +	intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock);
> >
> >  	/*
> >  	 * 9. Set PORT_CLOCK_CTL register PCLK PLL Request @@ -3074,6
> > +3085,14 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
> >  	intel_cx0_phy_transaction_end(encoder, wakeref);  }
> >
> > +static void intel_cx0pll_enable(struct intel_encoder *encoder,
> > +				const struct intel_crtc_state *crtc_state) {
> > +	__intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll,
> > +			      intel_crtc_has_dp_encoder(crtc_state),
> > +crtc_state->port_clock, crtc_state->lane_count);
> > +
> > +}
> > +
> >  int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)  {
> >  	struct intel_display *display = to_intel_display(encoder);
> 
> --
> Jani Nikula, Intel
Imre Deak Jan. 30, 2025, 1:26 p.m. UTC | #3
On Wed, Jan 29, 2025 at 04:40:01PM +0200, Jani Nikula wrote:
> On Wed, 29 Jan 2025, Mika Kahola <mika.kahola@intel.com> wrote:
> > For PLL programming for C10 and C20 we don't need to
> > carry crtc_state but instead use only necessary parts
> > of the crtc_state i.e. pll_state.
> 
> This is not a good enough justification alone. Usually we pass
> crtc_state around because we're going to need more stuff from there
> anyway. In that case, someone's going to have to reverse this, or pass a
> bunch more parameters than just "is_dp".
> 
> I see that you're doing this because you actually need this in a context
> that doens't have crtc_state. Then *that* needs to be the rationale.
> 
> Even so, there's a good chance this will bite us later.

The problem with the alternative to create a temporary CRTC state and
pass that around is that this state would not be fully initialized. If
passing more parameters to the PLL functions (besides is_dp, port_clock,
lane_count) would be impractical due to the long parameter list, the
parameters could be passed instead via a cx0_pll_params structure.

> BR,
> Jani.
> 
> 
> >
> > Signed-off-by: Mika Kahola <mika.kahola@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_cx0_phy.c | 109 +++++++++++--------
> >  1 file changed, 64 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > index 48b0b9755b2b..bffe3d4bbe8b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > @@ -2021,13 +2021,12 @@ intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
> >  	return NULL;
> >  }
> >  
> > -static void intel_cx0pll_update_ssc(struct intel_crtc_state *crtc_state,
> > -				    struct intel_encoder *encoder)
> > +static void intel_cx0pll_update_ssc(struct intel_encoder *encoder,
> > +				    struct intel_cx0pll_state *pll_state, bool is_dp)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder);
> > -	struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
> >  
> > -	if (intel_crtc_has_dp_encoder(crtc_state)) {
> > +	if (is_dp) {
> >  		if (intel_panel_use_ssc(display)) {
> >  			struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> >  			pll_state->ssc_enabled =
> > @@ -2036,11 +2035,10 @@ static void intel_cx0pll_update_ssc(struct intel_crtc_state *crtc_state,
> >  	}
> >  }
> >  
> > -static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
> > -				    struct intel_encoder *encoder)
> > +static void intel_c10pll_update_pll(struct intel_encoder *encoder,
> > +				    struct intel_cx0pll_state *pll_state, bool is_dp)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder);
> > -	struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
> >  	int i;
> >  
> >  	if (pll_state->ssc_enabled)
> > @@ -2051,32 +2049,49 @@ static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
> >  		pll_state->c10.pll[i] = 0;
> >  }
> >  
> > +static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
> > +					      const struct intel_c10pll_state * const *tables, int port_clock, bool is_dp,
> > +					      struct intel_cx0pll_state *pll_state)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; tables[i]; i++) {
> > +		if (port_clock == tables[i]->clock) {
> > +			pll_state->c10 = *tables[i];
> > +			intel_cx0pll_update_ssc(encoder, pll_state, is_dp);
> > +			intel_c10pll_update_pll(encoder, pll_state, is_dp);
> > +			pll_state->use_c10 = true;
> > +
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	return -EINVAL;
> > +}
> > +
> >  static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
> >  				   struct intel_encoder *encoder)
> >  {
> >  	const struct intel_c10pll_state * const *tables;
> > -	int i;
> > +	int val;
> >  
> >  	tables = intel_c10pll_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->dpll_hw_state.cx0pll.c10 = *tables[i];
> > -			intel_cx0pll_update_ssc(crtc_state, encoder);
> > -			intel_c10pll_update_pll(crtc_state, encoder);
> > -			crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
> > -
> > -			return 0;
> > -		}
> > -	}
> > +	val = intel_c10pll_calc_state_from_table(encoder, tables,
> > +						 crtc_state->port_clock, intel_crtc_has_dp_encoder(crtc_state),
> > +						 &crtc_state->dpll_hw_state.cx0pll);
> > +	if (val == 0)
> > +		return 0;
> >  
> >  	/* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */
> >  	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
> >  		intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10,
> >  						   crtc_state->port_clock);
> > -		intel_c10pll_update_pll(crtc_state, encoder);
> > +		intel_c10pll_update_pll(encoder,
> > +					&crtc_state->dpll_hw_state.cx0pll,
> > +					intel_crtc_has_dp_encoder(crtc_state));
> >  		crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
> >  
> >  		return 0;
> > @@ -2112,10 +2127,9 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
> >  }
> >  
> >  static void intel_c10_pll_program(struct intel_display *display,
> > -				  const struct intel_crtc_state *crtc_state,
> > -				  struct intel_encoder *encoder)
> > +				  struct intel_encoder *encoder,
> > +				  const struct intel_c10pll_state *pll_state)
> >  {
> > -	const struct intel_c10pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c10;
> >  	int i;
> >  
> >  	intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
> > @@ -2334,7 +2348,9 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
> >  	for (i = 0; tables[i]; i++) {
> >  		if (crtc_state->port_clock == tables[i]->clock) {
> >  			crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i];
> > -			intel_cx0pll_update_ssc(crtc_state, encoder);
> > +			intel_cx0pll_update_ssc(encoder,
> > +						&crtc_state->dpll_hw_state.cx0pll,
> > +						intel_crtc_has_dp_encoder(crtc_state));
> >  			crtc_state->dpll_hw_state.cx0pll.use_c10 = false;
> >  			return 0;
> >  		}
> > @@ -2600,19 +2616,14 @@ static int intel_get_c20_custom_width(u32 clock, bool dp)
> >  }
> >  
> >  static void intel_c20_pll_program(struct intel_display *display,
> > -				  const struct intel_crtc_state *crtc_state,
> > -				  struct intel_encoder *encoder)
> > +				  struct intel_encoder *encoder,
> > +				  const struct intel_c20pll_state *pll_state,
> > +				  int clock, bool dp)
> >  {
> > -	const struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
> > -	bool dp = false;
> >  	u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
> > -	u32 clock = crtc_state->port_clock;
> >  	bool cntx;
> >  	int i;
> >  
> > -	if (intel_crtc_has_dp_encoder(crtc_state))
> > -		dp = true;
> > -
> >  	/* 1. Read current context selection */
> >  	cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0);
> >  
> > @@ -2736,7 +2747,8 @@ static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
> >  }
> >  
> >  static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
> > -					 const struct intel_crtc_state *crtc_state,
> > +					 const struct intel_cx0pll_state *pll_state,
> > +					 bool is_dp, int port_clock,
> >  					 bool lane_reversal)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder);
> > @@ -2751,18 +2763,17 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
> >  
> >  	val |= XELPDP_FORWARD_CLOCK_UNGATE;
> >  
> > -	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
> > -	    is_hdmi_frl(crtc_state->port_clock))
> > +	if (!is_dp && is_hdmi_frl(port_clock))
> >  		val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
> >  	else
> >  		val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
> >  
> >  	/* TODO: HDMI FRL */
> >  	/* DP2.0 10G and 20G rates enable MPLLA*/
> > -	if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000)
> > -		val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
> > +	if (port_clock == 1000000 || port_clock == 2000000)
> > +		val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
> >  	else
> > -		val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
> > +		val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
> >  
> >  	intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
> >  		     XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
> > @@ -2992,8 +3003,9 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
> >  	return val;
> >  }
> >  
> > -static void intel_cx0pll_enable(struct intel_encoder *encoder,
> > -				const struct intel_crtc_state *crtc_state)
> > +static void __intel_cx0pll_enable(struct intel_encoder *encoder,
> > +				  const struct intel_cx0pll_state *pll_state,
> > +				  bool is_dp, int port_clock, int lane_count)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder);
> >  	enum phy phy = intel_encoder_to_phy(encoder);
> > @@ -3007,7 +3019,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
> >  	 * 1. Program PORT_CLOCK_CTL REGISTER to configure
> >  	 * clock muxes, gating and SSC
> >  	 */
> > -	intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
> > +	intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal);
> >  
> >  	/* 2. Bring PHY out of reset. */
> >  	intel_cx0_phy_lane_reset(encoder, lane_reversal);
> > @@ -3027,15 +3039,15 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
> >  
> >  	/* 5. Program PHY internal PLL internal registers. */
> >  	if (intel_encoder_is_c10phy(encoder))
> > -		intel_c10_pll_program(display, crtc_state, encoder);
> > +		intel_c10_pll_program(display, encoder, &pll_state->c10);
> >  	else
> > -		intel_c20_pll_program(display, crtc_state, encoder);
> > +		intel_c20_pll_program(display, encoder, &pll_state->c20, port_clock, is_dp);
> >  
> >  	/*
> >  	 * 6. Program the enabled and disabled owned PHY lane
> >  	 * transmitters over message bus
> >  	 */
> > -	intel_cx0_program_phy_lane(encoder, crtc_state->lane_count, lane_reversal);
> > +	intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal);
> >  
> >  	/*
> >  	 * 7. Follow the Display Voltage Frequency Switching - Sequence
> > @@ -3046,8 +3058,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
> >  	 * 8. Program DDI_CLK_VALFREQ to match intended DDI
> >  	 * clock frequency.
> >  	 */
> > -	intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
> > -		       crtc_state->port_clock);
> > +	intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock);
> >  
> >  	/*
> >  	 * 9. Set PORT_CLOCK_CTL register PCLK PLL Request
> > @@ -3074,6 +3085,14 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
> >  	intel_cx0_phy_transaction_end(encoder, wakeref);
> >  }
> >  
> > +static void intel_cx0pll_enable(struct intel_encoder *encoder,
> > +				const struct intel_crtc_state *crtc_state)
> > +{
> > +	__intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll,
> > +			      intel_crtc_has_dp_encoder(crtc_state), crtc_state->port_clock, crtc_state->lane_count);
> > +
> > +}
> > +
> >  int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
> >  {
> >  	struct intel_display *display = to_intel_display(encoder);
> 
> -- 
> Jani Nikula, Intel
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 48b0b9755b2b..bffe3d4bbe8b 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2021,13 +2021,12 @@  intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
 	return NULL;
 }
 
-static void intel_cx0pll_update_ssc(struct intel_crtc_state *crtc_state,
-				    struct intel_encoder *encoder)
+static void intel_cx0pll_update_ssc(struct intel_encoder *encoder,
+				    struct intel_cx0pll_state *pll_state, bool is_dp)
 {
 	struct intel_display *display = to_intel_display(encoder);
-	struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
 
-	if (intel_crtc_has_dp_encoder(crtc_state)) {
+	if (is_dp) {
 		if (intel_panel_use_ssc(display)) {
 			struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 			pll_state->ssc_enabled =
@@ -2036,11 +2035,10 @@  static void intel_cx0pll_update_ssc(struct intel_crtc_state *crtc_state,
 	}
 }
 
-static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
-				    struct intel_encoder *encoder)
+static void intel_c10pll_update_pll(struct intel_encoder *encoder,
+				    struct intel_cx0pll_state *pll_state, bool is_dp)
 {
 	struct intel_display *display = to_intel_display(encoder);
-	struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
 	int i;
 
 	if (pll_state->ssc_enabled)
@@ -2051,32 +2049,49 @@  static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
 		pll_state->c10.pll[i] = 0;
 }
 
+static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
+					      const struct intel_c10pll_state * const *tables, int port_clock, bool is_dp,
+					      struct intel_cx0pll_state *pll_state)
+{
+	int i;
+
+	for (i = 0; tables[i]; i++) {
+		if (port_clock == tables[i]->clock) {
+			pll_state->c10 = *tables[i];
+			intel_cx0pll_update_ssc(encoder, pll_state, is_dp);
+			intel_c10pll_update_pll(encoder, pll_state, is_dp);
+			pll_state->use_c10 = true;
+
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
 				   struct intel_encoder *encoder)
 {
 	const struct intel_c10pll_state * const *tables;
-	int i;
+	int val;
 
 	tables = intel_c10pll_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->dpll_hw_state.cx0pll.c10 = *tables[i];
-			intel_cx0pll_update_ssc(crtc_state, encoder);
-			intel_c10pll_update_pll(crtc_state, encoder);
-			crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
-
-			return 0;
-		}
-	}
+	val = intel_c10pll_calc_state_from_table(encoder, tables,
+						 crtc_state->port_clock, intel_crtc_has_dp_encoder(crtc_state),
+						 &crtc_state->dpll_hw_state.cx0pll);
+	if (val == 0)
+		return 0;
 
 	/* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */
 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
 		intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10,
 						   crtc_state->port_clock);
-		intel_c10pll_update_pll(crtc_state, encoder);
+		intel_c10pll_update_pll(encoder,
+					&crtc_state->dpll_hw_state.cx0pll,
+					intel_crtc_has_dp_encoder(crtc_state));
 		crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
 
 		return 0;
@@ -2112,10 +2127,9 @@  static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
 }
 
 static void intel_c10_pll_program(struct intel_display *display,
-				  const struct intel_crtc_state *crtc_state,
-				  struct intel_encoder *encoder)
+				  struct intel_encoder *encoder,
+				  const struct intel_c10pll_state *pll_state)
 {
-	const struct intel_c10pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c10;
 	int i;
 
 	intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
@@ -2334,7 +2348,9 @@  static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
 	for (i = 0; tables[i]; i++) {
 		if (crtc_state->port_clock == tables[i]->clock) {
 			crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i];
-			intel_cx0pll_update_ssc(crtc_state, encoder);
+			intel_cx0pll_update_ssc(encoder,
+						&crtc_state->dpll_hw_state.cx0pll,
+						intel_crtc_has_dp_encoder(crtc_state));
 			crtc_state->dpll_hw_state.cx0pll.use_c10 = false;
 			return 0;
 		}
@@ -2600,19 +2616,14 @@  static int intel_get_c20_custom_width(u32 clock, bool dp)
 }
 
 static void intel_c20_pll_program(struct intel_display *display,
-				  const struct intel_crtc_state *crtc_state,
-				  struct intel_encoder *encoder)
+				  struct intel_encoder *encoder,
+				  const struct intel_c20pll_state *pll_state,
+				  int clock, bool dp)
 {
-	const struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
-	bool dp = false;
 	u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
-	u32 clock = crtc_state->port_clock;
 	bool cntx;
 	int i;
 
-	if (intel_crtc_has_dp_encoder(crtc_state))
-		dp = true;
-
 	/* 1. Read current context selection */
 	cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0);
 
@@ -2736,7 +2747,8 @@  static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
 }
 
 static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
-					 const struct intel_crtc_state *crtc_state,
+					 const struct intel_cx0pll_state *pll_state,
+					 bool is_dp, int port_clock,
 					 bool lane_reversal)
 {
 	struct intel_display *display = to_intel_display(encoder);
@@ -2751,18 +2763,17 @@  static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
 
 	val |= XELPDP_FORWARD_CLOCK_UNGATE;
 
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
-	    is_hdmi_frl(crtc_state->port_clock))
+	if (!is_dp && is_hdmi_frl(port_clock))
 		val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
 	else
 		val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
 
 	/* TODO: HDMI FRL */
 	/* DP2.0 10G and 20G rates enable MPLLA*/
-	if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000)
-		val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
+	if (port_clock == 1000000 || port_clock == 2000000)
+		val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
 	else
-		val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
+		val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
 
 	intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
 		     XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
@@ -2992,8 +3003,9 @@  static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
 	return val;
 }
 
-static void intel_cx0pll_enable(struct intel_encoder *encoder,
-				const struct intel_crtc_state *crtc_state)
+static void __intel_cx0pll_enable(struct intel_encoder *encoder,
+				  const struct intel_cx0pll_state *pll_state,
+				  bool is_dp, int port_clock, int lane_count)
 {
 	struct intel_display *display = to_intel_display(encoder);
 	enum phy phy = intel_encoder_to_phy(encoder);
@@ -3007,7 +3019,7 @@  static void intel_cx0pll_enable(struct intel_encoder *encoder,
 	 * 1. Program PORT_CLOCK_CTL REGISTER to configure
 	 * clock muxes, gating and SSC
 	 */
-	intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
+	intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal);
 
 	/* 2. Bring PHY out of reset. */
 	intel_cx0_phy_lane_reset(encoder, lane_reversal);
@@ -3027,15 +3039,15 @@  static void intel_cx0pll_enable(struct intel_encoder *encoder,
 
 	/* 5. Program PHY internal PLL internal registers. */
 	if (intel_encoder_is_c10phy(encoder))
-		intel_c10_pll_program(display, crtc_state, encoder);
+		intel_c10_pll_program(display, encoder, &pll_state->c10);
 	else
-		intel_c20_pll_program(display, crtc_state, encoder);
+		intel_c20_pll_program(display, encoder, &pll_state->c20, port_clock, is_dp);
 
 	/*
 	 * 6. Program the enabled and disabled owned PHY lane
 	 * transmitters over message bus
 	 */
-	intel_cx0_program_phy_lane(encoder, crtc_state->lane_count, lane_reversal);
+	intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal);
 
 	/*
 	 * 7. Follow the Display Voltage Frequency Switching - Sequence
@@ -3046,8 +3058,7 @@  static void intel_cx0pll_enable(struct intel_encoder *encoder,
 	 * 8. Program DDI_CLK_VALFREQ to match intended DDI
 	 * clock frequency.
 	 */
-	intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
-		       crtc_state->port_clock);
+	intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock);
 
 	/*
 	 * 9. Set PORT_CLOCK_CTL register PCLK PLL Request
@@ -3074,6 +3085,14 @@  static void intel_cx0pll_enable(struct intel_encoder *encoder,
 	intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
+static void intel_cx0pll_enable(struct intel_encoder *encoder,
+				const struct intel_crtc_state *crtc_state)
+{
+	__intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll,
+			      intel_crtc_has_dp_encoder(crtc_state), crtc_state->port_clock, crtc_state->lane_count);
+
+}
+
 int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
 {
 	struct intel_display *display = to_intel_display(encoder);