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 +-1 kHz an
drm_warn() is thrown out to indicate possible pll divider mismatch.

v2:
- Move the LT_PHY_PLL_PARAMS -> LT_PHY_PLL_DP/HDMI_PARAMS change
  earlier.
- Use tables[i].name != NULL as a terminating condition.
- Use state vs. params term consistently in intel_c10pll_verify_clock()
  and intel_c20pll_verify_clock().

Signed-off-by: Mika Kahola <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c |  2 +
 drivers/gpu/drm/i915/display/intel_lt_phy.c   | 63 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_lt_phy.h   |  1 +
 3 files changed, 66 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c 
b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index 7127bc2a0898..f35a9252f4e1 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -38,6 +38,7 @@
 #include "intel_dpll.h"
 #include "intel_dpll_mgr.h"
 #include "intel_hti.h"
+#include "intel_lt_phy.h"
 #include "intel_mg_phy_regs.h"
 #include "intel_pch_refclk.h"
 #include "intel_step.h"
@@ -4639,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 e33f6f48a6ce..13acfc7c0469 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c
@@ -2343,3 +2343,66 @@ 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_state_name,
+                                         const struct intel_lt_phy_pll_state 
*pll_state,
+                                         bool is_precomputed_state)
+{
+       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,
+                "PLL state %s (%s): clock difference too high: computed %d, 
pre-computed %d\n",
+                pll_state_name,
+                is_precomputed_state ? "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 (%s):\n",
+                  pll_state_name,
+                  is_precomputed_state ? "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 i;
+
+       for (i = 0; tables[i].name; 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);
+       intel_lt_phy_pll_verify_tables(display, xe3plpd_lt_edp_tables);
+       intel_lt_phy_pll_verify_tables(display, 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

Reply via email to