A new workaround was defined for Xe3_LPD, which requires a tweak on how
we handle MDCLK selection.  Implement it.

Signed-off-by: Gustavo Sousa <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_cdclk.c      | 31 ++++++++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_display_wa.c |  2 ++
 drivers/gpu/drm/i915/display/intel_display_wa.h |  1 +
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 0aa59d624095..7443e5285942 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -39,6 +39,7 @@
 #include "intel_display_regs.h"
 #include "intel_display_types.h"
 #include "intel_display_utils.h"
+#include "intel_display_wa.h"
 #include "intel_dram.h"
 #include "intel_mchbar_regs.h"
 #include "intel_pci_config.h"
@@ -1858,6 +1859,20 @@ static void bxt_de_pll_enable(struct intel_display 
*display, int vco)
 
 static void icl_cdclk_pll_disable(struct intel_display *display)
 {
+       /*
+        * Wa_13012396614:
+        * Fixes: A sporadic race condition between MDCLK selection and PLL
+        *        enabling.
+        * Workaround:
+        *   Change programming of MDCLK source selection in CDCLK_CTL:
+        *    - When disabling the CDCLK PLL, first set MDCLK source to be 
CD2XCLK.
+        *    - When enabling the CDCLK PLL, update MDCLK source selection only
+        *      after the PLL is enabled (which is already done as part of the
+        *      normal flow of _bxt_set_cdclk()).
+        */
+       if (intel_display_wa(display, 13012396614))
+               intel_de_rmw(display, CDCLK_CTL, MDCLK_SOURCE_SEL_MASK, 
MDCLK_SOURCE_SEL_CD2XCLK);
+
        intel_de_rmw(display, BXT_DE_PLL_ENABLE,
                     BXT_DE_PLL_PLL_ENABLE, 0);
 
@@ -2147,10 +2162,20 @@ static u32 bxt_cdclk_ctl(struct intel_display *display,
            cdclk >= 500000)
                val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
 
-       if (DISPLAY_VER(display) >= 20)
-               val |= xe2lpd_mdclk_source_sel(display);
-       else
+       if (DISPLAY_VER(display) >= 20) {
+               /*
+                * Wa_13012396614 requires selecting CD2XCLK as MDCLK source
+                * prior to disabling the PLL, which is already handled by
+                * icl_cdclk_pll_disable().  Here we are just making sure
+                * we keep the expected value.
+                */
+               if (intel_display_wa(display, 13012396614) && vco == 0)
+                       val |= MDCLK_SOURCE_SEL_CD2XCLK;
+               else
+                       val |= xe2lpd_mdclk_source_sel(display);
+       } else {
                val |= skl_cdclk_decimal(cdclk);
+       }
 
        return val;
 }
diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c 
b/drivers/gpu/drm/i915/display/intel_display_wa.c
index 2b360447e92e..581d943b9bdc 100644
--- a/drivers/gpu/drm/i915/display/intel_display_wa.c
+++ b/drivers/gpu/drm/i915/display/intel_display_wa.c
@@ -62,6 +62,8 @@ static bool intel_display_needs_wa_16025573575(struct 
intel_display *display)
 bool __intel_display_wa(struct intel_display *display, enum intel_display_wa 
wa, const char *name)
 {
        switch (wa) {
+       case INTEL_DISPLAY_WA_13012396614:
+               return DISPLAY_VERx100(display) == 3000;
        case INTEL_DISPLAY_WA_14011503117:
                return DISPLAY_VER(display) == 13;
        case INTEL_DISPLAY_WA_14025769978:
diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h 
b/drivers/gpu/drm/i915/display/intel_display_wa.h
index 56b586e38306..40f989f19df1 100644
--- a/drivers/gpu/drm/i915/display/intel_display_wa.h
+++ b/drivers/gpu/drm/i915/display/intel_display_wa.h
@@ -27,6 +27,7 @@ bool intel_display_needs_wa_16023588340(struct intel_display 
*display);
  * number.
  */
 enum intel_display_wa {
+       INTEL_DISPLAY_WA_13012396614,
        INTEL_DISPLAY_WA_14011503117,
        INTEL_DISPLAY_WA_14025769978,
        INTEL_DISPLAY_WA_15018326506,

-- 
2.52.0

Reply via email to