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
