From 968290fa8a42d9d2d2fd0fcdeb82d7533e83071d Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Mon, 22 Dec 2025 19:18:48 -0300 Subject: [PATCH] drm/i915/cdclk: Implement Wa_13012396614 A new workaround was defined for Xe3_LPD, which requires a tweak on how we handle MDCLK selection. Implement it. Reviewed-by: Dnyaneshwar Bhadane Link: https://patch.msgid.link/20251222-display-wa-13012396614-timing-of-mdclk-source-selection-v1-2-a2f7e9447f7a@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/i915/display/intel_cdclk.c | 31 +++++++++++++++++-- .../gpu/drm/i915/display/intel_display_wa.c | 2 ++ .../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 0aa59d6240958..7443e52859426 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 2b360447e92e9..581d943b9bdc3 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 56b586e38306f..40f989f19df17 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.47.3