On Wed, 01 Oct 2025, Mika Kahola <[email protected]> wrote:
> From: Imre Deak <[email protected]>
>
> The Cx0 PLL enable programming needs to know if the PLL is in DP or HDMI
> mode. The PLL manager framework doesn't pass the CRTC state to the PLL's
> enable hook, so prepare here for the conversion to use the PLL manager
> for Cx0 PHY PLLs by determining the DP/HDMI mode from the PLL state.
>
> For C10 PHYs use the fact that the HDMI divider value in the PLL
> registers are set if and only if the PLL is in HDMI mode.
>
> For C20 PHYs use the DP mode flag programmed to the VDR SERDES register,
> which is set if and only if the PLL is in DP mode.
>
> Assert that the above PLL/VDR SERDES register values match the DP/HDMI
> mode being configured already during state computation.
>
> This also allows dropping the is_dp param from the
> __intel_cx0pll_enable() function, since it can retrieve this now from
> the PLL state.
>
> Signed-off-by: Imre Deak <[email protected]>
> ---
> drivers/gpu/drm/i915/display/intel_cx0_phy.c | 43 ++++++++++++++++----
> 1 file changed, 36 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> index 93e37b7ac3d9..f2fd766343d5 100644
> --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> @@ -2090,6 +2090,24 @@ static void intel_c10pll_update_pll(struct
> intel_encoder *encoder,
> pll_state->c10.pll[i] = 0;
> }
>
> +static bool c10pll_state_is_dp(const struct intel_c10pll_state *pll_state)
> +{
> + return !REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]);
> +}
> +
> +static bool c20pll_state_is_dp(const struct intel_c20pll_state *pll_state)
> +{
> + return pll_state->vdr.serdes_rate & PHY_C20_IS_DP;
Wouldn't need this if software state was the logical state instead of
hardware state that you need to mask. It could be just
pll_state->vdr.is_dp, and no function needed.
> +}
> +
> +static bool cx0pll_state_is_dp(const struct intel_cx0pll_state *pll_state)
> +{
> + if (pll_state->use_c10)
> + return c10pll_state_is_dp(&pll_state->c10);
> +
> + return c20pll_state_is_dp(&pll_state->c20);
> +}
> +
> /*
> * TODO: Convert the following align with intel_c20pll_find_table() and
> * intel_c20pll_calc_state_from_table().
> @@ -2099,6 +2117,7 @@ static int intel_c10pll_calc_state_from_table(struct
> intel_encoder *encoder,
> bool is_dp, int port_clock, int
> lane_count,
> struct intel_cx0pll_state
> *pll_state)
> {
> + struct intel_display *display = to_intel_display(encoder);
> int i;
>
> for (i = 0; tables[i]; i++) {
> @@ -2110,6 +2129,8 @@ static int intel_c10pll_calc_state_from_table(struct
> intel_encoder *encoder,
> pll_state->use_c10 = true;
> pll_state->lane_count = lane_count;
>
> + drm_WARN_ON(display->drm, is_dp !=
> c10pll_state_is_dp(&pll_state->c10));
> +
> return 0;
> }
> }
> @@ -2120,6 +2141,8 @@ static int intel_c10pll_calc_state_from_table(struct
> intel_encoder *encoder,
> static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
> struct intel_encoder *encoder)
> {
> + struct intel_display *display = to_intel_display(encoder);
> + bool is_dp = intel_crtc_has_dp_encoder(crtc_state);
> const struct intel_c10pll_state * const *tables;
> int err;
>
> @@ -2127,8 +2150,7 @@ static int intel_c10pll_calc_state(struct
> intel_crtc_state *crtc_state,
> if (!tables)
> return -EINVAL;
>
> - err = intel_c10pll_calc_state_from_table(encoder, tables,
> -
> intel_crtc_has_dp_encoder(crtc_state),
> + err = intel_c10pll_calc_state_from_table(encoder, tables, is_dp,
> crtc_state->port_clock,
> crtc_state->lane_count,
>
> &crtc_state->dpll_hw_state.cx0pll);
>
> @@ -2143,6 +2165,9 @@ static int intel_c10pll_calc_state(struct
> intel_crtc_state *crtc_state,
> crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
> crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count;
>
> + drm_WARN_ON(display->drm,
> + is_dp !=
> c10pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c10));
> +
> return 0;
> }
>
> @@ -2643,6 +2668,7 @@ static int intel_c20pll_calc_state_from_table(struct
> intel_crtc_state *crtc_stat
> static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
> struct intel_encoder *encoder)
> {
> + struct intel_display *display = to_intel_display(encoder);
> bool is_dp = intel_crtc_has_dp_encoder(crtc_state);
> int err = -ENOENT;
>
> @@ -2663,6 +2689,9 @@ static int intel_c20pll_calc_state(struct
> intel_crtc_state *crtc_state,
> intel_c20_calc_vdr_params(&crtc_state->dpll_hw_state.cx0pll.c20.vdr,
> is_dp, crtc_state->port_clock);
>
> + drm_WARN_ON(display->drm,
> + is_dp !=
> c20pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c20));
> +
> return 0;
> }
>
> @@ -2929,10 +2958,11 @@ static void intel_c20_pll_program(struct
> intel_display *display,
>
> static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
> const struct intel_cx0pll_state
> *pll_state,
> - bool is_dp, int port_clock,
> + int port_clock,
> bool lane_reversal)
> {
> struct intel_display *display = to_intel_display(encoder);
> + bool is_dp = cx0pll_state_is_dp(pll_state);
> u32 val = 0;
>
> intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, encoder->port),
> @@ -3178,7 +3208,7 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
>
> static void __intel_cx0pll_enable(struct intel_encoder *encoder,
> const struct intel_cx0pll_state *pll_state,
> - bool is_dp, int port_clock)
> + int port_clock)
> {
> struct intel_display *display = to_intel_display(encoder);
> enum phy phy = intel_encoder_to_phy(encoder);
> @@ -3192,7 +3222,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, pll_state, is_dp, port_clock,
> lane_reversal);
> + intel_program_port_clock_ctl(encoder, pll_state, port_clock,
> lane_reversal);
>
> /* 2. Bring PHY out of reset. */
> intel_cx0_phy_lane_reset(encoder, lane_reversal);
> @@ -3262,7 +3292,6 @@ 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);
> }
>
> @@ -3818,7 +3847,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display
> *display)
> "[ENCODER:%d:%s] Applying power saving workaround
> on disabled PLL\n",
> encoder->base.base.id, encoder->base.name);
>
> - __intel_cx0pll_enable(encoder, &pll_state, true, port_clock);
> + __intel_cx0pll_enable(encoder, &pll_state, port_clock);
> intel_cx0pll_disable(encoder);
> }
> }
--
Jani Nikula, Intel