> -----Original Message----- > From: Kandpal, Suraj <[email protected]> > Sent: Thursday, 29 January 2026 5.11 > To: Kahola, Mika <[email protected]>; [email protected]; > [email protected] > Cc: Kahola, Mika <[email protected]> > Subject: RE: [PATCH] drm/i915/power_well: Enable workaround for DSS clock > gating issue (22021048059) > > > Subject: [PATCH] drm/i915/power_well: Enable workaround for DSS clock > > gating issue (22021048059) > > You don’t need to mention the WA no in the subject since you describe what > you are doing in the patch
I will drop all mentions of WA number except the one in trailer. Thanks for the review & comments! -Mika- > > > > > Prevent display corruption observed after restart, hotplug, or unplug > > operations on Meteor Lake and newer platforms. The issue is caused by > > DSS clock gating affecting DSC logic when pipe power wells are disabled. > > > > Apply WA 22021048059 by disabling DSS clock gating for the affected > > pipes > > Also no need to mention it here since you have mentioned the WA no. in the > trailer > > Regards, > Suraj Kandpal > > > before turning off their power wells. This avoids DSC corruption on > > external displays. > > > > WA: 22021048059 > > BSpec: 690991, 666241 > > > > Signed-off-by: Mika Kahola <[email protected]> > > --- > > .../i915/display/intel_display_power_well.c | 78 ++++++++++++++++++- > > .../gpu/drm/i915/display/intel_display_regs.h | 7 ++ > > .../gpu/drm/i915/display/intel_display_wa.c | 2 + > > .../gpu/drm/i915/display/intel_display_wa.h | 1 + > > 4 files changed, 86 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c > > b/drivers/gpu/drm/i915/display/intel_display_power_well.c > > index 6f9bc6f9615e..1ef450f26879 100644 > > --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c > > +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c > > @@ -14,10 +14,13 @@ > > #include "intel_crt.h" > > #include "intel_de.h" > > #include "intel_display_irq.h" > > +#include "intel_display_limits.h" > > #include "intel_display_power_well.h" > > #include "intel_display_regs.h" > > #include "intel_display_rpm.h" > > #include "intel_display_types.h" > > +#include "intel_display_utils.h" > > +#include "intel_display_wa.h" > > #include "intel_dkl_phy.h" > > #include "intel_dkl_phy_regs.h" > > #include "intel_dmc.h" > > @@ -194,6 +197,69 @@ int intel_power_well_refcount(struct > > i915_power_well *power_well) > > return power_well->count; > > } > > > > +static void clock_gating_dss_enable_disable(struct intel_display *display, > > + u8 irq_pipe_mask, > > + bool disable) > > +{ > > + struct drm_printer p; > > + enum pipe pipe; > > + > > + switch (irq_pipe_mask) { > > + case BIT(PIPE_A): > > + pipe = PIPE_A; > > + > > + if (disable) > > + intel_de_rmw(display, CLKGATE_DIS_DSSDSC, > > + 0, DSS_PIPE_A_GATING_DISABLED); > > + else > > + intel_de_rmw(display, CLKGATE_DIS_DSSDSC, > > + DSS_PIPE_A_GATING_DISABLED, 0); > > + break; > > + case BIT(PIPE_B): > > + pipe = PIPE_B; > > + > > + if (disable) > > + intel_de_rmw(display, CLKGATE_DIS_DSSDSC, > > + 0, DSS_PIPE_B_GATING_DISABLED); > > + else > > + intel_de_rmw(display, CLKGATE_DIS_DSSDSC, > > + DSS_PIPE_B_GATING_DISABLED, 0); > > + break; > > + case BIT(PIPE_C): > > + pipe = PIPE_C; > > + > > + if (disable) > > + intel_de_rmw(display, CLKGATE_DIS_DSSDSC, > > + 0, DSS_PIPE_C_GATING_DISABLED); > > + else > > + intel_de_rmw(display, CLKGATE_DIS_DSSDSC, > > + DSS_PIPE_C_GATING_DISABLED, 0); > > + break; > > + case BIT(PIPE_D): > > + pipe = PIPE_D; > > + > > + if (disable) > > + intel_de_rmw(display, CLKGATE_DIS_DSSDSC, > > + 0, DSS_PIPE_D_GATING_DISABLED); > > + else > > + intel_de_rmw(display, CLKGATE_DIS_DSSDSC, > > + DSS_PIPE_D_GATING_DISABLED, 0); > > + break; > > + default: > > + MISSING_CASE(irq_pipe_mask); > > + break; > > + } > > + > > + if (!drm_debug_enabled(DRM_UT_KMS)) > > + return; > > + > > + p = drm_dbg_printer(display->drm, DRM_UT_KMS, NULL); > > + > > + drm_printf(&p, "dss clock gating %sd on pipe %c (0x%.8x)\n", > > + str_enable_disable(!disable), pipe_name(pipe), > > + intel_de_read(display, CLKGATE_DIS_DSSDSC)); } > > + > > /* > > * Starting with Haswell, we have a "Power Down Well" that can be turned > > off > > * when not needed anymore. We have 4 registers that can request the > > power well @@ -203,15 +269,23 @@ int intel_power_well_refcount(struct > > i915_power_well *power_well) static void > > hsw_power_well_post_enable(struct intel_display *display, > > u8 irq_pipe_mask) > > { > > - if (irq_pipe_mask) > > + if (irq_pipe_mask) { > > gen8_irq_power_well_post_enable(display, irq_pipe_mask); > > + > > + if (intel_display_wa(display, 22021048059)) > > + clock_gating_dss_enable_disable(display, > > irq_pipe_mask, false); > > + } > > } > > > > static void hsw_power_well_pre_disable(struct intel_display *display, > > u8 irq_pipe_mask) > > { > > - if (irq_pipe_mask) > > + if (irq_pipe_mask) { > > + if (intel_display_wa(display, 22021048059)) > > + clock_gating_dss_enable_disable(display, > > irq_pipe_mask, true); > > + > > gen8_irq_power_well_pre_disable(display, irq_pipe_mask); > > + } > > } > > > > #define ICL_AUX_PW_TO_PHY(pw_idx) \ > > diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h > > b/drivers/gpu/drm/i915/display/intel_display_regs.h > > index 9e0d853f4b61..9740f32ced24 100644 > > --- a/drivers/gpu/drm/i915/display/intel_display_regs.h > > +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h > > @@ -2211,6 +2211,13 @@ > > #define HSW_PWR_WELL_FORCE_ON (1 << 19) > > #define HSW_PWR_WELL_CTL6 _MMIO(0x45414) > > > > +/* clock gating DSS DSC disable register */ > > +#define CLKGATE_DIS_DSSDSC _MMIO(0x46548) > > +#define DSS_PIPE_D_GATING_DISABLED REG_BIT(31) > > +#define DSS_PIPE_C_GATING_DISABLED REG_BIT(29) > > +#define DSS_PIPE_B_GATING_DISABLED REG_BIT(27) > > +#define DSS_PIPE_A_GATING_DISABLED REG_BIT(25) > > + > > /* SKL Fuse Status */ > > enum skl_power_gate { > > SKL_PG0, > > diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c > > b/drivers/gpu/drm/i915/display/intel_display_wa.c > > index 86a6cc45b6ab..f8e14aa34dae 100644 > > --- a/drivers/gpu/drm/i915/display/intel_display_wa.c > > +++ b/drivers/gpu/drm/i915/display/intel_display_wa.c > > @@ -84,6 +84,8 @@ bool __intel_display_wa(struct intel_display > > *display, enum intel_display_wa wa, > > return intel_display_needs_wa_16025573575(display); > > case INTEL_DISPLAY_WA_22014263786: > > return IS_DISPLAY_VERx100(display, 1100, 1400); > > + case INTEL_DISPLAY_WA_22021048059: > > + return DISPLAY_VER(display) >= 14; > > default: > > drm_WARN(display->drm, 1, "Missing Wa number: %s\n", name); > > break; > > diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h > > b/drivers/gpu/drm/i915/display/intel_display_wa.h > > index 40f989f19df1..767420d5f406 100644 > > --- a/drivers/gpu/drm/i915/display/intel_display_wa.h > > +++ b/drivers/gpu/drm/i915/display/intel_display_wa.h > > @@ -34,6 +34,7 @@ enum intel_display_wa { > > INTEL_DISPLAY_WA_16023588340, > > INTEL_DISPLAY_WA_16025573575, > > INTEL_DISPLAY_WA_22014263786, > > + INTEL_DISPLAY_WA_22021048059, > > }; > > > > bool __intel_display_wa(struct intel_display *display, enum > > intel_display_wa wa, const char *name); > > -- > > 2.43.0
