drm/i915/display: Mask RO bits in gen9_write_dc_state()

The DC_STATE_EN register has read-only status bits that are set by
hardware on some platforms. These bits may cause the read-back
verification loop in gen9_write_dc_state() to spuriously retry.

Mask the RO bits from the read-back comparison to prevent
unnecessary retries.

Changes in v2:
- Rename patch from
  "drm/i915/display: Use rmw in gen9_write_dc_state() to preserve non-DC
bits"
  to
  "drm/i915/display: Mask RO bits in gen9_write_dc_state()"
- Mask only RO bits rather than masking all non DC state bits
  in DC_STATE_EN.  As the register has also some clear-on-write flags,
  like 'Display DC*CO State Status DSI'(Imre Deak)

Changes in v3:
- Limit ro mask to read-back comparison.

Changes in v4:
- Add bit definitions (Jani Nikula)

BSpec: 49437,69115
Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
Link: https://patch.msgid.link/20260605155359.4116572-1-dibin.moolakadan.subrahmanian@intel.com
This commit is contained in:
Dibin Moolakadan Subrahmanian
2026-06-17 18:19:23 +05:30
committed by Animesh Manna
parent fe12dfaef7
commit 94c0b93dc2
2 changed files with 24 additions and 4 deletions
@@ -726,12 +726,28 @@ static void assert_can_disable_dc9(struct intel_display *display)
*/
}
static u32 dc_state_ro_mask(struct intel_display *display)
{
if (DISPLAY_VER(display) >= 20)
return DC_STATE_EN_CSR_MASK_CMTG_1 | DC_STATE_EN_CSR_MASK_CMTG_0;
else if (DISPLAY_VER(display) >= 13 && !display->platform.dg2)
return DC_STATE_EN_CSR_MASK_CMTG_0;
return 0;
}
static void gen9_write_dc_state(struct intel_display *display,
u32 state)
{
int rewrites = 0;
int rereads = 0;
u32 v;
/*
* Mask out RO status bits from read-back comparison.
* HW may set these bits independently, so exclude them
* to prevent the verify loop from retrying due to RO bits mismatch.
*/
u32 ro_mask = dc_state_ro_mask(display);
intel_de_write(display, DC_STATE_EN, state);
@@ -743,7 +759,7 @@ static void gen9_write_dc_state(struct intel_display *display,
do {
v = intel_de_read(display, DC_STATE_EN);
if (v != state) {
if ((v & ~ro_mask) != (state & ~ro_mask)) {
intel_de_write(display, DC_STATE_EN, state);
rewrites++;
rereads = 0;
@@ -753,10 +769,10 @@ static void gen9_write_dc_state(struct intel_display *display,
} while (rewrites < 100);
if (v != state)
if ((v & ~ro_mask) != (state & ~ro_mask))
drm_err(display->drm,
"Writing dc state to 0x%x failed, now 0x%x\n",
state, v);
"Writing dc state to 0x%x failed, now 0x%x (ro_mask=0x%x)\n",
state, v, ro_mask);
/* Most of the times we need one retry, avoid spam */
if (rewrites > 1)
@@ -3081,6 +3081,10 @@ enum skl_power_gate {
#define DC_STATE_EN_UPTO_DC5 REG_FIELD_PREP(DC_STATE_EN_UPTO_DC3CO_DC5_DC6_MASK, 1)
#define DC_STATE_EN_UPTO_DC6 REG_FIELD_PREP(DC_STATE_EN_UPTO_DC3CO_DC5_DC6_MASK, 2)
#define DC_STATE_EN_UPTO_DC3CO REG_FIELD_PREP(DC_STATE_EN_UPTO_DC3CO_DC5_DC6_MASK, 3)
/* display version 20+ */
#define DC_STATE_EN_CSR_MASK_CMTG_1 REG_BIT(11)
/* display version 13+, except dg2 */
#define DC_STATE_EN_CSR_MASK_CMTG_0 REG_BIT(10)
#define DC_STATE_DEBUG _MMIO(0x45520)
#define DC_STATE_DEBUG_MASK_CORES (1 << 0)