Add verification for lt phy pll dividers during boot. The port clock is calculated from pll dividers and compared against the requested port clock value. If there are a difference exceeding +-2 kHz an drm_warn() is thrown out to indicate possible pll divider mismatch.
Signed-off-by: Mika Kahola <[email protected]> --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + drivers/gpu/drm/i915/display/intel_lt_phy.c | 123 ++++++++++++++---- drivers/gpu/drm/i915/display/intel_lt_phy.h | 1 + 3 files changed, 99 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 001788174f6b..1bb2fd43fade 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4640,6 +4640,7 @@ void intel_dpll_init(struct intel_display *display) * debug option. */ intel_cx0pll_verify_plls(display); + intel_lt_phy_verify_plls(display); } /** diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c b/drivers/gpu/drm/i915/display/intel_lt_phy.c index d00cf3232e7a..d0fd36e3f80e 100644 --- a/drivers/gpu/drm/i915/display/intel_lt_phy.c +++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c @@ -438,24 +438,29 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr20 = { struct intel_lt_phy_pll_params { const char *name; + bool is_hdmi; int clock_rate; - const struct intel_lt_phy_pll_state *pll; + const struct intel_lt_phy_pll_state *state; }; -#define LT_PHY_PLL_PARAMS(__clock_rate, __state) { \ +#define __LT_PHY_PLL_PARAMS(__is_hdmi, __clock_rate, __state) { \ .name = __stringify(__state), \ + .is_hdmi = __is_hdmi, \ .clock_rate = __clock_rate, \ - .pll = &__state, \ + .state = &__state, \ } +#define LT_PHY_PLL_HDMI_PARAMS(__clock_rate, __state) __LT_PHY_PLL_PARAMS(true, __clock_rate, __state) +#define LT_PHY_PLL_DP_PARAMS(__clock_rate, __state) __LT_PHY_PLL_PARAMS(false, __clock_rate, __state) + static const struct intel_lt_phy_pll_params xe3plpd_lt_dp_tables[] = { - LT_PHY_PLL_PARAMS(162000, xe3plpd_lt_dp_rbr), - LT_PHY_PLL_PARAMS(270000, xe3plpd_lt_dp_hbr1), - LT_PHY_PLL_PARAMS(540000, xe3plpd_lt_dp_hbr2), - LT_PHY_PLL_PARAMS(810000, xe3plpd_lt_dp_hbr3), - LT_PHY_PLL_PARAMS(1000000, xe3plpd_lt_dp_uhbr10), - LT_PHY_PLL_PARAMS(1350000, xe3plpd_lt_dp_uhbr13_5), - LT_PHY_PLL_PARAMS(2000000, xe3plpd_lt_dp_uhbr20), + LT_PHY_PLL_DP_PARAMS(162000, xe3plpd_lt_dp_rbr), + LT_PHY_PLL_DP_PARAMS(270000, xe3plpd_lt_dp_hbr1), + LT_PHY_PLL_DP_PARAMS(540000, xe3plpd_lt_dp_hbr2), + LT_PHY_PLL_DP_PARAMS(810000, xe3plpd_lt_dp_hbr3), + LT_PHY_PLL_DP_PARAMS(1000000, xe3plpd_lt_dp_uhbr10), + LT_PHY_PLL_DP_PARAMS(1350000, xe3plpd_lt_dp_uhbr13_5), + LT_PHY_PLL_DP_PARAMS(2000000, xe3plpd_lt_dp_uhbr20), }; static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_2_16 = { @@ -729,15 +734,15 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_6_75 = { }; static const struct intel_lt_phy_pll_params xe3plpd_lt_edp_tables[] = { - LT_PHY_PLL_PARAMS(162000, xe3plpd_lt_dp_rbr), - LT_PHY_PLL_PARAMS(216000, xe3plpd_lt_edp_2_16), - LT_PHY_PLL_PARAMS(243000, xe3plpd_lt_edp_2_43), - LT_PHY_PLL_PARAMS(270000, xe3plpd_lt_dp_hbr1), - LT_PHY_PLL_PARAMS(324000, xe3plpd_lt_edp_3_24), - LT_PHY_PLL_PARAMS(432000, xe3plpd_lt_edp_4_32), - LT_PHY_PLL_PARAMS(540000, xe3plpd_lt_dp_hbr2), - LT_PHY_PLL_PARAMS(675000, xe3plpd_lt_edp_6_75), - LT_PHY_PLL_PARAMS(810000, xe3plpd_lt_dp_hbr3), + LT_PHY_PLL_DP_PARAMS(162000, xe3plpd_lt_dp_rbr), + LT_PHY_PLL_DP_PARAMS(216000, xe3plpd_lt_edp_2_16), + LT_PHY_PLL_DP_PARAMS(243000, xe3plpd_lt_edp_2_43), + LT_PHY_PLL_DP_PARAMS(270000, xe3plpd_lt_dp_hbr1), + LT_PHY_PLL_DP_PARAMS(324000, xe3plpd_lt_edp_3_24), + LT_PHY_PLL_DP_PARAMS(432000, xe3plpd_lt_edp_4_32), + LT_PHY_PLL_DP_PARAMS(540000, xe3plpd_lt_dp_hbr2), + LT_PHY_PLL_DP_PARAMS(675000, xe3plpd_lt_edp_6_75), + LT_PHY_PLL_DP_PARAMS(810000, xe3plpd_lt_dp_hbr3), }; static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_252 = { @@ -1011,11 +1016,11 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_5p94 = { }; static const struct intel_lt_phy_pll_params xe3plpd_lt_hdmi_tables[] = { - LT_PHY_PLL_PARAMS(25200, xe3plpd_lt_hdmi_252), - LT_PHY_PLL_PARAMS(27200, xe3plpd_lt_hdmi_272), - LT_PHY_PLL_PARAMS(74250, xe3plpd_lt_hdmi_742p5), - LT_PHY_PLL_PARAMS(148500, xe3plpd_lt_hdmi_1p485), - LT_PHY_PLL_PARAMS(594000, xe3plpd_lt_hdmi_5p94), + LT_PHY_PLL_HDMI_PARAMS(25200, xe3plpd_lt_hdmi_252), + LT_PHY_PLL_HDMI_PARAMS(27200, xe3plpd_lt_hdmi_272), + LT_PHY_PLL_HDMI_PARAMS(74250, xe3plpd_lt_hdmi_742p5), + LT_PHY_PLL_HDMI_PARAMS(148500, xe3plpd_lt_hdmi_1p485), + LT_PHY_PLL_HDMI_PARAMS(594000, xe3plpd_lt_hdmi_5p94), }; static u8 intel_lt_phy_get_owned_lane_mask(struct intel_encoder *encoder) @@ -1792,8 +1797,8 @@ intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state, return -EINVAL; for (i = 0; tables; i++) { - if (crtc_state->port_clock == tables[i].clock_rate) { - crtc_state->dpll_hw_state.ltpll = *tables[i].pll; + if (intel_cx0pll_clock_matches(crtc_state->port_clock, tables[i].clock_rate)) { + crtc_state->dpll_hw_state.ltpll = *tables[i].state; if (intel_crtc_has_dp_encoder(crtc_state)) { if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) crtc_state->dpll_hw_state.ltpll.config[2] = 1; @@ -2331,3 +2336,69 @@ void intel_xe3plpd_pll_disable(struct intel_encoder *encoder) intel_lt_phy_pll_disable(encoder); } + +static void intel_lt_phy_pll_verify_clock(struct intel_display *display, + int precomputed_clock, + const char *pll_params_name, + const struct intel_lt_phy_pll_state *pll_state, + bool pre_computed_params) +{ + struct drm_printer p; + int clock; + + clock = intel_lt_phy_calc_port_clock(display, pll_state); + + if (intel_cx0pll_clock_matches(clock, precomputed_clock)) + return; + + drm_warn(display->drm, + "%s (%s): clock difference too high: computed %d, pre-computed %d\n", + pll_params_name, + pre_computed_params ? "precomputed" : "computed", + clock, precomputed_clock); + + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + p = drm_dbg_printer(display->drm, DRM_UT_KMS, NULL); + + drm_printf(&p, "PLL state (%s):\n", + pre_computed_params ? "precomputed" : "computed"); + intel_lt_phy_dump_hw_state(display, pll_state); +} + +static void intel_lt_phy_pll_verify_params(struct intel_display *display, + const struct intel_lt_phy_pll_params *pll_params) +{ + struct intel_lt_phy_pll_state pll_state; + + intel_lt_phy_pll_verify_clock(display, pll_params->clock_rate, pll_params->name, pll_params->state, true); + + if (!pll_params->is_hdmi) + return; + + if (intel_lt_phy_calculate_hdmi_state(&pll_state, pll_params->clock_rate) != 0) + return; + + intel_lt_phy_pll_verify_clock(display, pll_params->clock_rate, pll_params->name, &pll_state, false); +} + +static void intel_lt_phy_pll_verify_tables(struct intel_display *display, + const struct intel_lt_phy_pll_params *tables, + int size) +{ + int i; + + for (i = 0; i < size; i++) + intel_lt_phy_pll_verify_params(display, &tables[i]); +} + +void intel_lt_phy_verify_plls(struct intel_display *display) +{ + intel_lt_phy_pll_verify_tables(display, xe3plpd_lt_dp_tables, + ARRAY_SIZE(xe3plpd_lt_dp_tables)); + intel_lt_phy_pll_verify_tables(display, xe3plpd_lt_edp_tables, + ARRAY_SIZE(xe3plpd_lt_edp_tables)); + intel_lt_phy_pll_verify_tables(display, xe3plpd_lt_hdmi_tables, + ARRAY_SIZE(xe3plpd_lt_hdmi_tables)); +} diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.h b/drivers/gpu/drm/i915/display/intel_lt_phy.h index c4999a55473e..56c5a875d93b 100644 --- a/drivers/gpu/drm/i915/display/intel_lt_phy.h +++ b/drivers/gpu/drm/i915/display/intel_lt_phy.h @@ -41,5 +41,6 @@ intel_lt_phy_calculate_hdmi_state(struct intel_lt_phy_pll_state *lt_state, void intel_xe3plpd_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_xe3plpd_pll_disable(struct intel_encoder *encoder); +void intel_lt_phy_verify_plls(struct intel_display *display); #endif /* __INTEL_LT_PHY_H__ */ -- 2.34.1
