Intel-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/9] drm/i915/display: DC3CO support
@ 2025-12-09 11:33 Dibin Moolakadan Subrahmanian
  2025-12-09 11:33 ` [PATCH 1/9] drm/i915/display: Remove TGL " Dibin Moolakadan Subrahmanian
                   ` (9 more replies)
  0 siblings, 10 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

Hi all,

This series introduces initial DC3CO DC state support,
replacing the existing PSR2-based TGL DC3CO design
(currently disabled).

The goal of this work is to move DC3CO handling out of PSR2-specific
code paths and into the core atomic display state flow, making the
behaviour consistent across PSR, ALPM and LOBF in line with the new
DC3CO design.

This series is posted as RFC to gather early feedback on the approach
before full integration.

Dibin Moolakadan Subrahmanian (9):
  drm/i915/display: Remove TGL DC3CO support
  drm/i915/display: Replace DC_STATE_EN_DC3CO with
    DC_STATE_EN_UPTO_DC3CO
  drm/i915/display: Add DC3CO enable/disable support
  drm/i915/display: Add DC3CO eligibility logic
  drm/i915/display: Track DC3CO enable source
  drm/i915/display: alpm enable DC3CO support
  drm/i915/display: psr enable DC3CO support
  drm/i915/display: Add intel_dc3co_can_enable() helper
  drm/i915/display: Add DC3CO disable handling for psr2

 drivers/gpu/drm/i915/display/intel_alpm.c     |   4 +
 drivers/gpu/drm/i915/display/intel_display.c  |  95 +++++++++
 drivers/gpu/drm/i915/display/intel_display.h  |   6 +-
 .../gpu/drm/i915/display/intel_display_core.h |   4 +
 .../drm/i915/display/intel_display_power.c    |  10 +-
 .../drm/i915/display/intel_display_power.h    |  10 +
 .../i915/display/intel_display_power_well.c   |  35 ++--
 .../gpu/drm/i915/display/intel_display_regs.h |   2 +-
 drivers/gpu/drm/i915/display/intel_dmc_wl.c   |   2 +-
 drivers/gpu/drm/i915/display/intel_psr.c      | 180 +++++-------------
 drivers/gpu/drm/i915/display/intel_psr_regs.h |   1 +
 11 files changed, 187 insertions(+), 162 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 1/9] drm/i915/display: Remove TGL DC3CO support
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2025-12-09 11:33 ` [PATCH 2/9] drm/i915/display: Replace DC_STATE_EN_DC3CO with DC_STATE_EN_UPTO_DC3CO Dibin Moolakadan Subrahmanian
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

Remove all Tiger Lake DC3CO-related functions, as the feature is no
longer used. The existing structure members are intentionally left in
place and will be cleaned up in subsequent patches.

Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 .../i915/display/intel_display_power_well.c   |  25 ---
 .../drm/i915/display/intel_display_types.h    |   1 -
 drivers/gpu/drm/i915/display/intel_psr.c      | 163 ------------------
 3 files changed, 189 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 db185a859133..2dce622eb5d8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -821,23 +821,6 @@ void gen9_set_dc_state(struct intel_display *display, u32 state)
 	power_domains->dc_state = val & mask;
 }
 
-static void tgl_enable_dc3co(struct intel_display *display)
-{
-	drm_dbg_kms(display->drm, "Enabling DC3CO\n");
-	gen9_set_dc_state(display, DC_STATE_EN_DC3CO);
-}
-
-static void tgl_disable_dc3co(struct intel_display *display)
-{
-	drm_dbg_kms(display->drm, "Disabling DC3CO\n");
-	intel_de_rmw(display, DC_STATE_EN, DC_STATE_DC3CO_STATUS, 0);
-	gen9_set_dc_state(display, DC_STATE_DISABLE);
-	/*
-	 * Delay of 200us DC3CO Exit time B.Spec 49196
-	 */
-	usleep_range(200, 210);
-}
-
 static void assert_can_enable_dc5(struct intel_display *display)
 {
 	enum i915_power_well_id high_pg;
@@ -1016,11 +999,6 @@ void gen9_disable_dc_states(struct intel_display *display)
 	struct intel_cdclk_config cdclk_config = {};
 	u32 old_state = power_domains->dc_state;
 
-	if (power_domains->target_dc_state == DC_STATE_EN_DC3CO) {
-		tgl_disable_dc3co(display);
-		return;
-	}
-
 	if (HAS_DISPLAY(display)) {
 		intel_dmc_wl_get_noreg(display);
 		gen9_set_dc_state(display, DC_STATE_DISABLE);
@@ -1069,9 +1047,6 @@ static void gen9_dc_off_power_well_disable(struct intel_display *display,
 		return;
 
 	switch (power_domains->target_dc_state) {
-	case DC_STATE_EN_DC3CO:
-		tgl_enable_dc3co(display);
-		break;
 	case DC_STATE_EN_UPTO_DC6:
 		skl_enable_dc6(display);
 		break;
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 6ff53cd58052..27f69df7ee9c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1759,7 +1759,6 @@ struct intel_psr {
 	bool panel_replay_enabled;
 	u32 dc3co_exitline;
 	u32 dc3co_exit_delay;
-	struct delayed_work dc3co_work;
 	u8 entry_setup_frames;
 
 	u8 io_wake_lines;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 2a378a5adc59..753359069044 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -85,22 +85,6 @@
  * issues the self-refresh re-enable code is done from a work queue, which
  * must be correctly synchronized/cancelled when shutting down the pipe."
  *
- * DC3CO (DC3 clock off)
- *
- * On top of PSR2, GEN12 adds a intermediate power savings state that turns
- * clock off automatically during PSR2 idle state.
- * The smaller overhead of DC3co entry/exit vs. the overhead of PSR2 deep sleep
- * entry/exit allows the HW to enter a low-power state even when page flipping
- * periodically (for instance a 30fps video playback scenario).
- *
- * Every time a flips occurs PSR2 will get out of deep sleep state(if it was),
- * so DC3CO is enabled and tgl_dc3co_disable_work is schedule to run after 6
- * frames, if no other flip occurs and the function above is executed, DC3CO is
- * disabled and PSR2 is configured to enter deep sleep, resetting again in case
- * of another flip.
- * Front buffer modifications do not trigger DC3CO activation on purpose as it
- * would bring a lot of complexity and most of the moderns systems will only
- * use page flips.
  */
 
 /*
@@ -1173,108 +1157,6 @@ static void psr2_program_idle_frames(struct intel_dp *intel_dp,
 		     EDP_PSR2_IDLE_FRAMES(idle_frames));
 }
 
-static void tgl_psr2_enable_dc3co(struct intel_dp *intel_dp)
-{
-	struct intel_display *display = to_intel_display(intel_dp);
-
-	psr2_program_idle_frames(intel_dp, 0);
-	intel_display_power_set_target_dc_state(display, DC_STATE_EN_DC3CO);
-}
-
-static void tgl_psr2_disable_dc3co(struct intel_dp *intel_dp)
-{
-	struct intel_display *display = to_intel_display(intel_dp);
-
-	intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
-	psr2_program_idle_frames(intel_dp, psr_compute_idle_frames(intel_dp));
-}
-
-static void tgl_dc3co_disable_work(struct work_struct *work)
-{
-	struct intel_dp *intel_dp =
-		container_of(work, typeof(*intel_dp), psr.dc3co_work.work);
-
-	mutex_lock(&intel_dp->psr.lock);
-	/* If delayed work is pending, it is not idle */
-	if (delayed_work_pending(&intel_dp->psr.dc3co_work))
-		goto unlock;
-
-	tgl_psr2_disable_dc3co(intel_dp);
-unlock:
-	mutex_unlock(&intel_dp->psr.lock);
-}
-
-static void tgl_disallow_dc3co_on_psr2_exit(struct intel_dp *intel_dp)
-{
-	if (!intel_dp->psr.dc3co_exitline)
-		return;
-
-	cancel_delayed_work(&intel_dp->psr.dc3co_work);
-	/* Before PSR2 exit disallow dc3co*/
-	tgl_psr2_disable_dc3co(intel_dp);
-}
-
-static bool
-dc3co_is_pipe_port_compatible(struct intel_dp *intel_dp,
-			      struct intel_crtc_state *crtc_state)
-{
-	struct intel_display *display = to_intel_display(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
-	enum port port = dig_port->base.port;
-
-	if (display->platform.alderlake_p || DISPLAY_VER(display) >= 14)
-		return pipe <= PIPE_B && port <= PORT_B;
-	else
-		return pipe == PIPE_A && port == PORT_A;
-}
-
-static void
-tgl_dc3co_exitline_compute_config(struct intel_dp *intel_dp,
-				  struct intel_crtc_state *crtc_state)
-{
-	struct intel_display *display = to_intel_display(intel_dp);
-	const u32 crtc_vdisplay = crtc_state->uapi.adjusted_mode.crtc_vdisplay;
-	struct i915_power_domains *power_domains = &display->power.domains;
-	u32 exit_scanlines;
-
-	/*
-	 * FIXME: Due to the changed sequence of activating/deactivating DC3CO,
-	 * disable DC3CO until the changed dc3co activating/deactivating sequence
-	 * is applied. B.Specs:49196
-	 */
-	return;
-
-	/*
-	 * DMC's DC3CO exit mechanism has an issue with Selective Fecth
-	 * TODO: when the issue is addressed, this restriction should be removed.
-	 */
-	if (crtc_state->enable_psr2_sel_fetch)
-		return;
-
-	if (!(power_domains->allowed_dc_mask & DC_STATE_EN_DC3CO))
-		return;
-
-	if (!dc3co_is_pipe_port_compatible(intel_dp, crtc_state))
-		return;
-
-	/* Wa_16011303918:adl-p */
-	if (display->platform.alderlake_p && IS_DISPLAY_STEP(display, STEP_A0, STEP_B0))
-		return;
-
-	/*
-	 * DC3CO Exit time 200us B.Spec 49196
-	 * PSR2 transcoder Early Exit scanlines = ROUNDUP(200 / line time) + 1
-	 */
-	exit_scanlines =
-		intel_usecs_to_scanlines(&crtc_state->uapi.adjusted_mode, 200) + 1;
-
-	if (drm_WARN_ON(display->drm, exit_scanlines > crtc_vdisplay))
-		return;
-
-	crtc_state->dc3co_exitline = crtc_vdisplay - exit_scanlines;
-}
-
 static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp,
 					      struct intel_crtc_state *crtc_state)
 {
@@ -1613,8 +1495,6 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
 		return false;
 	}
 
-	tgl_dc3co_exitline_compute_config(intel_dp, crtc_state);
-
 	return true;
 }
 
@@ -2063,16 +1943,6 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
 
 	psr_irq_control(intel_dp);
 
-	/*
-	 * TODO: if future platforms supports DC3CO in more than one
-	 * transcoder, EXITLINE will need to be unset when disabling PSR
-	 */
-	if (intel_dp->psr.dc3co_exitline)
-		intel_de_rmw(display,
-			     TRANS_EXITLINE(display, cpu_transcoder),
-			     EXITLINE_MASK,
-			     intel_dp->psr.dc3co_exitline << EXITLINE_SHIFT | EXITLINE_ENABLE);
-
 	if (HAS_PSR_HW_TRACKING(display) && HAS_PSR2_SEL_FETCH(display))
 		intel_de_rmw(display, CHICKEN_PAR1_1, IGNORE_PSR2_HW_TRACKING,
 			     intel_dp->psr.psr2_sel_fetch_enabled ?
@@ -2247,7 +2117,6 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
 		intel_de_rmw(display, TRANS_DP2_CTL(intel_dp->psr.transcoder),
 			     TRANS_DP2_PANEL_REPLAY_ENABLE, 0);
 	} else if (intel_dp->psr.sel_update_enabled) {
-		tgl_disallow_dc3co_on_psr2_exit(intel_dp);
 
 		val = intel_de_rmw(display,
 				   EDP_PSR2_CTL(display, cpu_transcoder),
@@ -2390,7 +2259,6 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 
 	mutex_unlock(&intel_dp->psr.lock);
 	cancel_work_sync(&intel_dp->psr.work);
-	cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
 }
 
 /**
@@ -2421,7 +2289,6 @@ void intel_psr_pause(struct intel_dp *intel_dp)
 	mutex_unlock(&psr->lock);
 
 	cancel_work_sync(&psr->work);
-	cancel_delayed_work_sync(&psr->dc3co_work);
 }
 
 /**
@@ -3518,34 +3385,6 @@ void intel_psr_invalidate(struct intel_display *display,
 		mutex_unlock(&intel_dp->psr.lock);
 	}
 }
-/*
- * When we will be completely rely on PSR2 S/W tracking in future,
- * intel_psr_flush() will invalidate and flush the PSR for ORIGIN_FLIP
- * event also therefore tgl_dc3co_flush_locked() require to be changed
- * accordingly in future.
- */
-static void
-tgl_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
-		       enum fb_op_origin origin)
-{
-	struct intel_display *display = to_intel_display(intel_dp);
-
-	if (!intel_dp->psr.dc3co_exitline || !intel_dp->psr.sel_update_enabled ||
-	    !intel_dp->psr.active)
-		return;
-
-	/*
-	 * At every frontbuffer flush flip event modified delay of delayed work,
-	 * when delayed work schedules that means display has been idle.
-	 */
-	if (!(frontbuffer_bits &
-	    INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
-		return;
-
-	tgl_psr2_enable_dc3co(intel_dp);
-	mod_delayed_work(display->wq.unordered, &intel_dp->psr.dc3co_work,
-			 intel_dp->psr.dc3co_exit_delay);
-}
 
 static void _psr_flush_handle(struct intel_dp *intel_dp)
 {
@@ -3630,7 +3469,6 @@ void intel_psr_flush(struct intel_display *display,
 		if (origin == ORIGIN_FLIP ||
 		    (origin == ORIGIN_CURSOR_UPDATE &&
 		     !intel_dp->psr.psr2_sel_fetch_enabled)) {
-			tgl_dc3co_flush_locked(intel_dp, frontbuffer_bits, origin);
 			goto unlock;
 		}
 
@@ -3689,7 +3527,6 @@ void intel_psr_init(struct intel_dp *intel_dp)
 		intel_dp->psr.link_standby = connector->panel.vbt.psr.full_link;
 
 	INIT_WORK(&intel_dp->psr.work, intel_psr_work);
-	INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, tgl_dc3co_disable_work);
 	mutex_init(&intel_dp->psr.lock);
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 2/9] drm/i915/display: Replace DC_STATE_EN_DC3CO with DC_STATE_EN_UPTO_DC3CO
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
  2025-12-09 11:33 ` [PATCH 1/9] drm/i915/display: Remove TGL " Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2026-01-05 12:45   ` Jani Nikula
  2025-12-09 11:33 ` [PATCH 3/9] drm/i915/display: Add DC3CO enable/disable support Dibin Moolakadan Subrahmanian
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

DC3CO no longer uses a standalone enable bit but part of existing
UPTO_DC* enable bits.

Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display_power.c      | 6 +++---
 drivers/gpu/drm/i915/display/intel_display_power_well.c | 4 ++--
 drivers/gpu/drm/i915/display/intel_display_regs.h       | 2 +-
 drivers/gpu/drm/i915/display/intel_dmc_wl.c             | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 9f323c39d798..0961b194554c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -267,7 +267,7 @@ sanitize_target_dc_state(struct intel_display *display,
 	static const u32 states[] = {
 		DC_STATE_EN_UPTO_DC6,
 		DC_STATE_EN_UPTO_DC5,
-		DC_STATE_EN_DC3CO,
+		DC_STATE_EN_UPTO_DC3CO,
 		DC_STATE_DISABLE,
 	};
 	int i;
@@ -999,10 +999,10 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
 
 	switch (requested_dc) {
 	case 4:
-		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6;
+		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC6;
 		break;
 	case 3:
-		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC5;
+		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC5;
 		break;
 	case 2:
 		mask |= DC_STATE_EN_UPTO_DC6;
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 2dce622eb5d8..6f62a4420f6e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -727,7 +727,7 @@ static u32 gen9_dc_mask(struct intel_display *display)
 	mask = DC_STATE_EN_UPTO_DC5;
 
 	if (DISPLAY_VER(display) >= 12)
-		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6
+		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC6
 					  | DC_STATE_EN_DC9;
 	else if (DISPLAY_VER(display) == 11)
 		mask |= DC_STATE_EN_UPTO_DC6 | DC_STATE_EN_DC9;
@@ -977,7 +977,7 @@ static void bxt_verify_dpio_phy_power_wells(struct intel_display *display)
 static bool gen9_dc_off_power_well_enabled(struct intel_display *display,
 					   struct i915_power_well *power_well)
 {
-	return ((intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_DC3CO) == 0 &&
+	return ((intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_UPTO_DC3CO) == 0 &&
 		(intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
index 9e0d853f4b61..7e620e22718b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
@@ -2819,13 +2819,13 @@ enum skl_power_gate {
 /* GEN9 DC */
 #define DC_STATE_EN			_MMIO(0x45504)
 #define  DC_STATE_DISABLE		0
-#define  DC_STATE_EN_DC3CO		REG_BIT(30)
 #define  DC_STATE_DC3CO_STATUS		REG_BIT(29)
 #define  HOLD_PHY_CLKREQ_PG1_LATCH	REG_BIT(21)
 #define  HOLD_PHY_PG1_LATCH		REG_BIT(20)
 #define  DC_STATE_EN_UPTO_DC5		(1 << 0)
 #define  DC_STATE_EN_DC9		(1 << 3)
 #define  DC_STATE_EN_UPTO_DC6		(2 << 0)
+#define  DC_STATE_EN_UPTO_DC3CO		(3 << 0)
 #define  DC_STATE_EN_UPTO_DC5_DC6_MASK   0x3
 
 #define  DC_STATE_DEBUG                  _MMIO(0x45520)
diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c
index 73a3101514f3..9f403b7820ab 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c
@@ -260,7 +260,7 @@ static bool intel_dmc_wl_check_range(struct intel_display *display,
 	 * the DMC and requires a DC exit for proper access.
 	 */
 	switch (dc_state) {
-	case DC_STATE_EN_DC3CO:
+	case DC_STATE_EN_UPTO_DC3CO:
 		ranges = xe3lpd_dc3co_dmc_ranges;
 		break;
 	case DC_STATE_EN_UPTO_DC5:
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 3/9] drm/i915/display: Add DC3CO enable/disable support
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
  2025-12-09 11:33 ` [PATCH 1/9] drm/i915/display: Remove TGL " Dibin Moolakadan Subrahmanian
  2025-12-09 11:33 ` [PATCH 2/9] drm/i915/display: Replace DC_STATE_EN_DC3CO with DC_STATE_EN_UPTO_DC3CO Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2025-12-09 11:33 ` [PATCH 4/9] drm/i915/display: Add DC3CO eligibility logic Dibin Moolakadan Subrahmanian
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

Add explicit handling for DC3CO in the dc_off power well sequencing.
Introduce xe3lpd_enable_dc3co() and wire it into the dc_off power
enable flow. gen9_disable_dc_states() is also updated to disable the
corresponding DMC wakelock when transitioning out of DC3CO.

Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 .../drm/i915/display/intel_display_power_well.c  | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

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 6f62a4420f6e..6d8d9d7b7d0a 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -821,6 +821,13 @@ void gen9_set_dc_state(struct intel_display *display, u32 state)
 	power_domains->dc_state = val & mask;
 }
 
+static void xe3lpd_enable_dc3co(struct intel_display *display)
+{
+	drm_dbg_kms(display->drm, "Enabling DC3CO\n");
+	intel_dmc_wl_enable(display, DC_STATE_EN_UPTO_DC3CO);
+	gen9_set_dc_state(display, DC_STATE_EN_UPTO_DC3CO);
+}
+
 static void assert_can_enable_dc5(struct intel_display *display)
 {
 	enum i915_power_well_id high_pg;
@@ -1009,9 +1016,13 @@ void gen9_disable_dc_states(struct intel_display *display)
 	}
 
 	if (old_state == DC_STATE_EN_UPTO_DC5 ||
-	    old_state == DC_STATE_EN_UPTO_DC6)
+	    old_state == DC_STATE_EN_UPTO_DC6 ||
+	    old_state == DC_STATE_EN_UPTO_DC3CO)
 		intel_dmc_wl_disable(display);
 
+	if (old_state == DC_STATE_EN_UPTO_DC3CO)
+		return;
+
 	intel_cdclk_get_cdclk(display, &cdclk_config);
 	/* Can't read out voltage_level so can't use intel_cdclk_changed() */
 	drm_WARN_ON(display->drm,
@@ -1047,6 +1058,9 @@ static void gen9_dc_off_power_well_disable(struct intel_display *display,
 		return;
 
 	switch (power_domains->target_dc_state) {
+	case DC_STATE_EN_UPTO_DC3CO:
+		xe3lpd_enable_dc3co(display);
+		break;
 	case DC_STATE_EN_UPTO_DC6:
 		skl_enable_dc6(display);
 		break;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 4/9] drm/i915/display: Add DC3CO eligibility logic
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
                   ` (2 preceding siblings ...)
  2025-12-09 11:33 ` [PATCH 3/9] drm/i915/display: Add DC3CO enable/disable support Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2026-01-05 12:55   ` Jani Nikula
  2025-12-09 11:33 ` [PATCH 5/9] drm/i915/display: Track DC3CO enable source Dibin Moolakadan Subrahmanian
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

Introduce dc3co_allow in struct intel_display and determine DC3CO
eligibility during atomic_check(). DC3CO is permitted only when:

  - the active pipe drives eDP,
  - the pipe is single-pipe (no joiner),
  - the pipe/port combination supports DC3CO.

When eligible, intel_atomic_commit_tail() programs the target DC state
as DC_STATE_EN_UPTO_DC3CO; otherwise we fall back to DC6. Update the
PSR vblank enable/disable path to follow the same policy.

Also extend get_allowed_dc_mask() to expose DC3CO support on
DISPLAY_VER >= 35.

Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c  | 75 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_display.h  |  1 +
 .../gpu/drm/i915/display/intel_display_core.h |  3 +
 .../drm/i915/display/intel_display_power.c    |  4 +-
 drivers/gpu/drm/i915/display/intel_psr.c      | 13 ++--
 5 files changed, 87 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 9c6d3ecdb589..205f55a87736 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6295,6 +6295,75 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state)
 	return 0;
 }
 
+bool intel_dc3co_allowed(struct intel_display *display)
+{
+	return display->power.dc3co_allow;
+}
+
+static bool intel_dc3co_port_pipe_compatible(struct intel_dp *intel_dp,
+					     const struct intel_crtc_state *crtc_state)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
+	enum port port = dig_port->base.port;
+	int num_pipes = intel_crtc_num_joined_pipes(crtc_state);
+
+	if (num_pipes != 1)
+		return false;
+
+	if (!(pipe <= PIPE_B && port <= PORT_B))
+		return false;
+
+	return true;
+}
+
+static void intel_dc3co_allow_check(struct intel_atomic_state *state)
+{
+	struct intel_display *display = to_intel_display(state);
+	struct intel_crtc *crtc;
+	struct intel_crtc_state *new_crtc_state;
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp;
+	int i;
+	struct i915_power_domains *power_domains = &display->power.domains;
+	bool any_active = false;
+	bool allow = true;
+
+	display->power.dc3co_allow = 0;
+
+	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
+		return;
+
+	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+		if (!new_crtc_state->hw.active)
+			continue;
+
+		any_active = true;
+
+		for_each_intel_encoder_mask(display->drm, encoder,
+					    new_crtc_state->uapi.encoder_mask) {
+			/* If any active pipe not eDP disable*/
+			if (!intel_encoder_is_dp(encoder) ||
+			    encoder->type != INTEL_OUTPUT_EDP) {
+				allow = false;
+				goto out;
+			}
+			intel_dp = enc_to_intel_dp(encoder);
+			/* Port, joiner, pipe placement checks */
+			if (!intel_dc3co_port_pipe_compatible(intel_dp, new_crtc_state)) {
+				allow = false;
+				goto out;
+			}
+		}
+	}
+
+	if (!any_active)
+		allow = false;
+
+out:
+	display->power.dc3co_allow = allow;
+}
+
 static int intel_atomic_check_config(struct intel_atomic_state *state,
 				     struct intel_link_bw_limits *limits,
 				     enum pipe *failed_pipe)
@@ -6565,6 +6634,8 @@ int intel_atomic_check(struct drm_device *dev,
 	if (ret)
 		goto fail;
 
+	intel_dc3co_allow_check(state);
+
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
 		intel_color_assert_luts(new_crtc_state);
@@ -7601,6 +7672,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 		 */
 		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
 	}
+	if (intel_dc3co_allowed(display))
+		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC3CO);
+	else
+		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
 	/*
 	 * Delay re-enabling DC states by 17 ms to avoid the off->on->off
 	 * toggling overhead at and above 60 FPS.
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index f8e6e4e82722..97987f082560 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -560,5 +560,6 @@ bool assert_port_valid(struct intel_display *display, enum port port);
 
 bool intel_scanout_needs_vtd_wa(struct intel_display *display);
 int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
+bool intel_dc3co_allowed(struct intel_display *display);
 
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index d708d322aa85..fa567c95029c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -538,6 +538,9 @@ struct intel_display {
 
 		/* perform PHY state sanity checks? */
 		bool chv_phy_assert[2];
+
+		/* mark dc3co entry is allowed*/
+		bool dc3co_allow;
 	} power;
 
 	struct {
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 0961b194554c..e99552f18756 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -956,7 +956,9 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
 	if (!HAS_DISPLAY(display))
 		return 0;
 
-	if (DISPLAY_VER(display) >= 20)
+	if (DISPLAY_VER(display) >= 35)
+		max_dc = 3;
+	else if (DISPLAY_VER(display) >= 20)
 		max_dc = 2;
 	else if (display->platform.dg2)
 		max_dc = 1;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 753359069044..9c616f449ad6 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -3903,14 +3903,11 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
 		return;
 	}
 
-	/*
-	 * NOTE: intel_display_power_set_target_dc_state is used
-	 * only by PSR * code for DC3CO handling. DC3CO target
-	 * state is currently disabled in * PSR code. If DC3CO
-	 * is taken into use we need take that into account here
-	 * as well.
-	 */
-	intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
+	if (intel_dc3co_allowed(display))
+		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
+						DC_STATE_EN_UPTO_DC3CO);
+	else
+		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
 						DC_STATE_EN_UPTO_DC6);
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 5/9] drm/i915/display: Track DC3CO enable source
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
                   ` (3 preceding siblings ...)
  2025-12-09 11:33 ` [PATCH 4/9] drm/i915/display: Add DC3CO eligibility logic Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2026-01-05 12:56   ` Jani Nikula
  2025-12-09 11:33 ` [PATCH 6/9] drm/i915/display: alpm enable DC3CO support Dibin Moolakadan Subrahmanian
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

Introduce a bitmask enum intel_dc3co_source to record which display
features (PSR2, ALPM, LOBF) contribute to allowing DC3CO entry.
The source tracking is added here and will be integrated into the DC3CO
allow logic in follow-up commits.
Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c       | 11 +++++++++++
 drivers/gpu/drm/i915/display/intel_display.h       |  4 +++-
 drivers/gpu/drm/i915/display/intel_display_core.h  |  1 +
 drivers/gpu/drm/i915/display/intel_display_power.h | 10 ++++++++++
 4 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 205f55a87736..b14a1c9f80bd 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6300,6 +6300,16 @@ bool intel_dc3co_allowed(struct intel_display *display)
 	return display->power.dc3co_allow;
 }
 
+void intel_dc3co_source_set(struct intel_display *display, enum intel_dc3co_source source)
+{
+	display->power.dc3co_source |= source;
+}
+
+void intel_dc3co_source_unset(struct intel_display *display, enum intel_dc3co_source source)
+{
+	display->power.dc3co_source &= ~source;
+}
+
 static bool intel_dc3co_port_pipe_compatible(struct intel_dp *intel_dp,
 					     const struct intel_crtc_state *crtc_state)
 {
@@ -6330,6 +6340,7 @@ static void intel_dc3co_allow_check(struct intel_atomic_state *state)
 	bool allow = true;
 
 	display->power.dc3co_allow = 0;
+	intel_dc3co_source_unset(display, DC3CO_SOURCE_ALL);
 
 	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
 		return;
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 97987f082560..87bbf1f66209 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -46,6 +46,7 @@ struct intel_link_m_n;
 struct intel_plane;
 struct intel_plane_state;
 struct intel_power_domain_mask;
+enum intel_dc3co_source;
 
 #define pipe_name(p) ((p) + 'A')
 
@@ -561,5 +562,6 @@ bool assert_port_valid(struct intel_display *display, enum port port);
 bool intel_scanout_needs_vtd_wa(struct intel_display *display);
 int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
 bool intel_dc3co_allowed(struct intel_display *display);
-
+void intel_dc3co_source_set(struct intel_display *display, enum intel_dc3co_source source);
+void intel_dc3co_source_unset(struct intel_display *display, enum intel_dc3co_source source);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index fa567c95029c..4ce34c567dbd 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -541,6 +541,7 @@ struct intel_display {
 
 		/* mark dc3co entry is allowed*/
 		bool dc3co_allow;
+		u32 dc3co_source;
 	} power;
 
 	struct {
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
index d616d5d09cbe..dde07f931963 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -131,6 +131,16 @@ struct intel_power_domain_mask {
 	DECLARE_BITMAP(bits, POWER_DOMAIN_NUM);
 };
 
+enum intel_dc3co_source {
+	DC3CO_SOURCE_NONE = 0,
+	DC3CO_SOURCE_PSR2 = BIT(0),
+	DC3CO_SOURCE_ALPM = BIT(1),
+	DC3CO_SOURCE_LOBF = BIT(2),
+	DC3CO_SOURCE_ALL  = DC3CO_SOURCE_PSR2 |
+			    DC3CO_SOURCE_ALPM |
+			    DC3CO_SOURCE_LOBF,
+};
+
 struct i915_power_domains {
 	/*
 	 * Power wells needed for initialization at driver init and suspend
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 6/9] drm/i915/display: alpm enable DC3CO support
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
                   ` (4 preceding siblings ...)
  2025-12-09 11:33 ` [PATCH 5/9] drm/i915/display: Track DC3CO enable source Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2025-12-12  7:37   ` Hogander, Jouni
  2025-12-09 11:33 ` [PATCH 7/9] drm/i915/display: psr " Dibin Moolakadan Subrahmanian
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

if DC3CO allowed set PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL
in ALPM_CTL and update dc3co_source

Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 drivers/gpu/drm/i915/display/intel_alpm.c     | 4 ++++
 drivers/gpu/drm/i915/display/intel_psr_regs.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
index 7ce8c674bb03..28a95f6ddfab 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -347,6 +347,10 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
 
 	alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(crtc_state->alpm_state.check_entry_lines);
 
+	if (intel_dc3co_allowed(display)) {
+		alpm_ctl |= (PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL);
+		intel_dc3co_source_set(display, DC3CO_SOURCE_ALPM);
+	}
 	intel_de_write(display, ALPM_CTL(display, cpu_transcoder), alpm_ctl);
 	mutex_unlock(&intel_dp->alpm.lock);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h
index 8afbf5a38335..16a9e3af198d 100644
--- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
@@ -268,6 +268,7 @@
 
 #define _PR_ALPM_CTL_A	0x60948
 #define PR_ALPM_CTL(dev_priv, tran)	_MMIO_TRANS2(dev_priv, tran, _PR_ALPM_CTL_A)
+#define  PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL			BIT(7)
 #define  PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU	BIT(6)
 #define  PR_ALPM_CTL_RFB_UPDATE_CONTROL				BIT(5)
 #define  PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE	BIT(4)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 7/9] drm/i915/display: psr enable DC3CO support
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
                   ` (5 preceding siblings ...)
  2025-12-09 11:33 ` [PATCH 6/9] drm/i915/display: alpm enable DC3CO support Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2026-01-05 13:02   ` Jani Nikula
  2025-12-09 11:33 ` [PATCH 8/9] drm/i915/display: Add intel_dc3co_can_enable() helper Dibin Moolakadan Subrahmanian
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

if DC3CO allowed and psr2 is enabled, update dc3co_source

Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 drivers/gpu/drm/i915/display/intel_psr.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 9c616f449ad6..d4c5dc6dcc82 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -3007,6 +3007,12 @@ void intel_psr_post_plane_update(struct intel_atomic_state *state,
 		if (crtc_state->crc_enabled && psr->enabled)
 			intel_psr_force_update(intel_dp);
 
+		if (psr->enabled &&
+		    psr->sel_update_enabled &&
+		    intel_dc3co_allowed(display)) {
+			intel_dc3co_source_set(display, DC3CO_SOURCE_PSR2);
+		}
+
 		/*
 		 * Clear possible busy bits in case we have
 		 * invalidate -> flip -> flush sequence.
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 8/9] drm/i915/display: Add intel_dc3co_can_enable() helper
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
                   ` (6 preceding siblings ...)
  2025-12-09 11:33 ` [PATCH 7/9] drm/i915/display: psr " Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2026-01-05 12:56   ` Jani Nikula
  2025-12-09 11:33 ` [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2 Dibin Moolakadan Subrahmanian
  2025-12-09 14:36 ` ✗ i915.CI.BAT: failure for drm/i915/display: DC3CO support Patchwork
  9 siblings, 1 reply; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

Introduce a new helper that validates whether DC3CO can be enabled
based on both allow  and source.

Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 11 ++++++++++-
 drivers/gpu/drm/i915/display/intel_display.h |  1 +
 drivers/gpu/drm/i915/display/intel_psr.c     |  2 +-
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index b14a1c9f80bd..9f9ba58371ab 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6295,6 +6295,15 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state)
 	return 0;
 }
 
+bool intel_dc3co_can_enable(struct intel_display *display)
+{
+	/*
+	 * ToDo - Check CMTG enabled
+	 * ToDo - Check flipq enabled
+	 */
+	return (display->power.dc3co_allow && display->power.dc3co_source);
+}
+
 bool intel_dc3co_allowed(struct intel_display *display)
 {
 	return display->power.dc3co_allow;
@@ -7683,7 +7692,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 		 */
 		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
 	}
-	if (intel_dc3co_allowed(display))
+	if (intel_dc3co_can_enable(display))
 		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC3CO);
 	else
 		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 87bbf1f66209..f704cce4f1d8 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -564,4 +564,5 @@ int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
 bool intel_dc3co_allowed(struct intel_display *display);
 void intel_dc3co_source_set(struct intel_display *display, enum intel_dc3co_source source);
 void intel_dc3co_source_unset(struct intel_display *display, enum intel_dc3co_source source);
+bool intel_dc3co_can_enable(struct intel_display *display);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index d4c5dc6dcc82..18bf45455ea2 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -3909,7 +3909,7 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
 		return;
 	}
 
-	if (intel_dc3co_allowed(display))
+	if (intel_dc3co_can_enable(display))
 		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
 						DC_STATE_EN_UPTO_DC3CO);
 	else
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
                   ` (7 preceding siblings ...)
  2025-12-09 11:33 ` [PATCH 8/9] drm/i915/display: Add intel_dc3co_can_enable() helper Dibin Moolakadan Subrahmanian
@ 2025-12-09 11:33 ` Dibin Moolakadan Subrahmanian
  2025-12-12  7:11   ` Hogander, Jouni
  2026-01-05 13:01   ` Jani Nikula
  2025-12-09 14:36 ` ✗ i915.CI.BAT: failure for drm/i915/display: DC3CO support Patchwork
  9 siblings, 2 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-09 11:33 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

dc6 should be enabled instead of dc3co after  6 idle frames
while in psr2.(re enable part of tgl dc3co handling)

Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  1 +
 drivers/gpu/drm/i915/display/intel_psr.c      | 78 ++++++++++++++++++-
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 27f69df7ee9c..6ff53cd58052 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1759,6 +1759,7 @@ struct intel_psr {
 	bool panel_replay_enabled;
 	u32 dc3co_exitline;
 	u32 dc3co_exit_delay;
+	struct delayed_work dc3co_work;
 	u8 entry_setup_frames;
 
 	u8 io_wake_lines;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 18bf45455ea2..4be709d1d324 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1157,6 +1157,78 @@ static void psr2_program_idle_frames(struct intel_dp *intel_dp,
 		     EDP_PSR2_IDLE_FRAMES(idle_frames));
 }
 
+static void psr2_dc3co_disable(struct intel_dp *intel_dp)
+{
+	struct intel_display *display = to_intel_display(intel_dp);
+	struct i915_power_domains *power_domains = &display->power.domains;
+
+	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
+		return;
+
+	intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
+	/* Todo restore PSR2 idle frames , ALPM control*/
+}
+
+static void psr2_dc3co_disable_on_exit(struct intel_dp *intel_dp)
+{
+	struct intel_display *display = to_intel_display(intel_dp);
+	struct i915_power_domains *power_domains = &display->power.domains;
+
+	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
+		return;
+
+	cancel_delayed_work(&intel_dp->psr.dc3co_work);
+	intel_dc3co_source_unset(display, DC3CO_SOURCE_PSR2);
+}
+
+static void psr2_dc3co_disable_work(struct work_struct *work)
+{
+	struct intel_dp *intel_dp =
+		container_of(work, typeof(*intel_dp), psr.dc3co_work.work);
+
+	mutex_lock(&intel_dp->psr.lock);
+	/* If delayed work is pending, it is not idle */
+	if (delayed_work_pending(&intel_dp->psr.dc3co_work))
+		goto unlock;
+	/* enable DC6 after idle frames*/
+	psr2_dc3co_disable(intel_dp);
+
+unlock:
+	mutex_unlock(&intel_dp->psr.lock);
+}
+
+/*
+ * When we will be completely rely on PSR2 S/W tracking in future,
+ * intel_psr_flush() will invalidate and flush the PSR for ORIGIN_FLIP
+ * event also therefore psr2_dc3co_flush_locked() require to be changed
+ * accordingly in future.
+ */
+
+static void
+psr2_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
+			enum fb_op_origin origin)
+{
+	struct intel_display *display = to_intel_display(intel_dp);
+	struct i915_power_domains *power_domains = &display->power.domains;
+
+	if (!(power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO))
+		return;
+
+	if (!intel_dp->psr.sel_update_enabled ||
+	    !intel_dp->psr.active)
+		return;
+	/*
+	 * At every frontbuffer flush flip event modified delay of delayed work,
+	 * when delayed work schedules that means display has been idle.
+	 */
+	if (!(frontbuffer_bits &
+	    INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
+		return;
+
+	mod_delayed_work(display->wq.unordered, &intel_dp->psr.dc3co_work,
+			 intel_dp->psr.dc3co_exit_delay);
+}
+
 static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp,
 					      struct intel_crtc_state *crtc_state)
 {
@@ -2117,7 +2189,7 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
 		intel_de_rmw(display, TRANS_DP2_CTL(intel_dp->psr.transcoder),
 			     TRANS_DP2_PANEL_REPLAY_ENABLE, 0);
 	} else if (intel_dp->psr.sel_update_enabled) {
-
+		psr2_dc3co_disable_on_exit(intel_dp);
 		val = intel_de_rmw(display,
 				   EDP_PSR2_CTL(display, cpu_transcoder),
 				   EDP_PSR2_ENABLE, 0);
@@ -2259,6 +2331,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 
 	mutex_unlock(&intel_dp->psr.lock);
 	cancel_work_sync(&intel_dp->psr.work);
+	cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
 }
 
 /**
@@ -2289,6 +2362,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
 	mutex_unlock(&psr->lock);
 
 	cancel_work_sync(&psr->work);
+	cancel_delayed_work_sync(&psr->dc3co_work);
 }
 
 /**
@@ -3475,6 +3549,7 @@ void intel_psr_flush(struct intel_display *display,
 		if (origin == ORIGIN_FLIP ||
 		    (origin == ORIGIN_CURSOR_UPDATE &&
 		     !intel_dp->psr.psr2_sel_fetch_enabled)) {
+			psr2_dc3co_flush_locked(intel_dp, frontbuffer_bits, origin);
 			goto unlock;
 		}
 
@@ -3533,6 +3608,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
 		intel_dp->psr.link_standby = connector->panel.vbt.psr.full_link;
 
 	INIT_WORK(&intel_dp->psr.work, intel_psr_work);
+	INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, psr2_dc3co_disable_work);
 	mutex_init(&intel_dp->psr.lock);
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* ✗ i915.CI.BAT: failure for drm/i915/display: DC3CO support
  2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
                   ` (8 preceding siblings ...)
  2025-12-09 11:33 ` [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2 Dibin Moolakadan Subrahmanian
@ 2025-12-09 14:36 ` Patchwork
  9 siblings, 0 replies; 28+ messages in thread
From: Patchwork @ 2025-12-09 14:36 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 9710 bytes --]

== Series Details ==

Series: drm/i915/display: DC3CO support
URL   : https://patchwork.freedesktop.org/series/158689/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_17647 -> Patchwork_158689v1
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_158689v1 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_158689v1, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/index.html

Participating hosts (8 -> 6)
------------------------------

  Additional (2): fi-glk-j4005 bat-dg2-11 
  Missing    (4): bat-dg2-13 bat-arlh-2 bat-rpls-4 bat-adls-6 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_158689v1:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_module_load@load:
    - fi-ilk-650:         [PASS][1] -> [ABORT][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17647/fi-ilk-650/igt@i915_module_load@load.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/fi-ilk-650/igt@i915_module_load@load.html
    - fi-pnv-d510:        [PASS][3] -> [ABORT][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17647/fi-pnv-d510/igt@i915_module_load@load.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/fi-pnv-d510/igt@i915_module_load@load.html
    - fi-elk-e7500:       [PASS][5] -> [ABORT][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17647/fi-elk-e7500/igt@i915_module_load@load.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/fi-elk-e7500/igt@i915_module_load@load.html

  
Known issues
------------

  Here are the changes found in Patchwork_158689v1 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_huc_copy@huc-copy:
    - fi-glk-j4005:       NOTRUN -> [SKIP][7] ([i915#2190])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/fi-glk-j4005/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@random-engines:
    - fi-glk-j4005:       NOTRUN -> [SKIP][8] ([i915#4613]) +3 other tests skip
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/fi-glk-j4005/igt@gem_lmem_swapping@random-engines.html

  * igt@gem_mmap@basic:
    - bat-dg2-11:         NOTRUN -> [SKIP][9] ([i915#4083])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@gem_mmap@basic.html

  * igt@gem_tiled_blits@basic:
    - bat-dg2-11:         NOTRUN -> [SKIP][10] ([i915#4077]) +2 other tests skip
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@gem_tiled_blits@basic.html

  * igt@gem_tiled_pread_basic:
    - bat-dg2-11:         NOTRUN -> [SKIP][11] ([i915#4079]) +1 other test skip
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@gem_tiled_pread_basic.html

  * igt@i915_pm_rps@basic-api:
    - bat-dg2-11:         NOTRUN -> [SKIP][12] ([i915#11681] / [i915#6621])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@i915_pm_rps@basic-api.html

  * igt@i915_selftest@live:
    - fi-glk-j4005:       NOTRUN -> [ABORT][13] ([i915#15399]) +1 other test abort
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/fi-glk-j4005/igt@i915_selftest@live.html

  * igt@i915_selftest@live@hugepages:
    - bat-dg2-11:         NOTRUN -> [ABORT][14] ([i915#15399]) +1 other test abort
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@i915_selftest@live@hugepages.html

  * igt@i915_selftest@live@workarounds:
    - bat-dg2-11:         NOTRUN -> [DMESG-FAIL][15] ([i915#12061])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@i915_selftest@live@workarounds.html

  * igt@kms_addfb_basic@addfb25-framebuffer-vs-set-tiling:
    - bat-dg2-11:         NOTRUN -> [SKIP][16] ([i915#4212]) +7 other tests skip
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_addfb_basic@addfb25-framebuffer-vs-set-tiling.html

  * igt@kms_addfb_basic@addfb25-y-tiled-small-legacy:
    - bat-dg2-11:         NOTRUN -> [SKIP][17] ([i915#5190])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_addfb_basic@addfb25-y-tiled-small-legacy.html

  * igt@kms_addfb_basic@basic-y-tiled-legacy:
    - bat-dg2-11:         NOTRUN -> [SKIP][18] ([i915#4215] / [i915#5190])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_addfb_basic@basic-y-tiled-legacy.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic:
    - fi-glk-j4005:       NOTRUN -> [SKIP][19] +11 other tests skip
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/fi-glk-j4005/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html
    - bat-dg2-11:         NOTRUN -> [SKIP][20] ([i915#4103] / [i915#4213]) +1 other test skip
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html

  * igt@kms_dsc@dsc-basic:
    - bat-dg2-11:         NOTRUN -> [SKIP][21] ([i915#3555] / [i915#3840])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_dsc@dsc-basic.html

  * igt@kms_force_connector_basic@force-load-detect:
    - bat-dg2-11:         NOTRUN -> [SKIP][22]
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_force_connector_basic@force-load-detect.html

  * igt@kms_pm_backlight@basic-brightness:
    - bat-dg2-11:         NOTRUN -> [SKIP][23] ([i915#5354])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_pm_backlight@basic-brightness.html

  * igt@kms_psr@psr-primary-mmap-gtt:
    - bat-dg2-11:         NOTRUN -> [SKIP][24] ([i915#1072] / [i915#9732]) +3 other tests skip
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_psr@psr-primary-mmap-gtt.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - bat-dg2-11:         NOTRUN -> [SKIP][25] ([i915#3555])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@kms_setmode@basic-clone-single-crtc.html

  * igt@prime_vgem@basic-fence-flip:
    - bat-dg2-11:         NOTRUN -> [SKIP][26] ([i915#3708])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@prime_vgem@basic-fence-flip.html

  * igt@prime_vgem@basic-gtt:
    - bat-dg2-11:         NOTRUN -> [SKIP][27] ([i915#3708] / [i915#4077]) +1 other test skip
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@prime_vgem@basic-gtt.html

  * igt@prime_vgem@basic-read:
    - bat-dg2-11:         NOTRUN -> [SKIP][28] ([i915#3291] / [i915#3708]) +2 other tests skip
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-dg2-11/igt@prime_vgem@basic-read.html

  
#### Warnings ####

  * igt@i915_selftest@live:
    - bat-atsm-1:         [INCOMPLETE][29] ([i915#12061] / [i915#15157]) -> [INCOMPLETE][30] ([i915#15157])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17647/bat-atsm-1/igt@i915_selftest@live.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/bat-atsm-1/igt@i915_selftest@live.html

  
  [i915#1072]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1072
  [i915#11681]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11681
  [i915#12061]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061
  [i915#15157]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15157
  [i915#15399]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15399
  [i915#2190]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2190
  [i915#3291]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3291
  [i915#3555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3555
  [i915#3708]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3708
  [i915#3840]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3840
  [i915#4077]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4077
  [i915#4079]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4083
  [i915#4103]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4213
  [i915#4215]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4215
  [i915#4613]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4613
  [i915#5190]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5190
  [i915#5354]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5354
  [i915#6621]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6621
  [i915#9732]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9732


Build changes
-------------

  * Linux: CI_DRM_17647 -> Patchwork_158689v1

  CI-20190529: 20190529
  CI_DRM_17647: 48deab361d3b570e2210875fdc8ffb29627d054f @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_8659: 8659
  Patchwork_158689v1: 48deab361d3b570e2210875fdc8ffb29627d054f @ git://anongit.freedesktop.org/gfx-ci/linux

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_158689v1/index.html

[-- Attachment #2: Type: text/html, Size: 11501 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2
  2025-12-09 11:33 ` [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2 Dibin Moolakadan Subrahmanian
@ 2025-12-12  7:11   ` Hogander, Jouni
  2025-12-16  8:24     ` Dibin Moolakadan Subrahmanian
  2026-01-05 13:01   ` Jani Nikula
  1 sibling, 1 reply; 28+ messages in thread
From: Hogander, Jouni @ 2025-12-12  7:11 UTC (permalink / raw)
  To: intel-xe@lists.freedesktop.org, Dibin Moolakadan Subrahmanian,
	intel-gfx@lists.freedesktop.org
  Cc: Shankar, Uma, Manna, Animesh, Deak, Imre

On Tue, 2025-12-09 at 17:03 +0530, Dibin Moolakadan Subrahmanian wrote:
> dc6 should be enabled instead of dc3co after  6 idle frames
> while in psr2.(re enable part of tgl dc3co handling)

This is for PSR and pretty much following existing (disabled) TGL DC3CO
control. What is your idea how selection between DC6 and DC3CO will be
done in case of LOBF?

BR,

Jouni Högander

> 
> Signed-off-by: Dibin Moolakadan Subrahmanian
> <dibin.moolakadan.subrahmanian@intel.com>
> ---
>  .../drm/i915/display/intel_display_types.h    |  1 +
>  drivers/gpu/drm/i915/display/intel_psr.c      | 78
> ++++++++++++++++++-
>  2 files changed, 78 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 27f69df7ee9c..6ff53cd58052 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1759,6 +1759,7 @@ struct intel_psr {
>  	bool panel_replay_enabled;
>  	u32 dc3co_exitline;
>  	u32 dc3co_exit_delay;
> +	struct delayed_work dc3co_work;
>  	u8 entry_setup_frames;
>  
>  	u8 io_wake_lines;
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
> b/drivers/gpu/drm/i915/display/intel_psr.c
> index 18bf45455ea2..4be709d1d324 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -1157,6 +1157,78 @@ static void psr2_program_idle_frames(struct
> intel_dp *intel_dp,
>  		     EDP_PSR2_IDLE_FRAMES(idle_frames));
>  }
>  
> +static void psr2_dc3co_disable(struct intel_dp *intel_dp)
> +{
> +	struct intel_display *display = to_intel_display(intel_dp);
> +	struct i915_power_domains *power_domains = &display-
> >power.domains;
> +
> +	if ((power_domains->allowed_dc_mask &
> DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
> +		return;
> +
> +	intel_display_power_set_target_dc_state(display,
> DC_STATE_EN_UPTO_DC6);
> +	/* Todo restore PSR2 idle frames , ALPM control*/
> +}
> +
> +static void psr2_dc3co_disable_on_exit(struct intel_dp *intel_dp)
> +{
> +	struct intel_display *display = to_intel_display(intel_dp);
> +	struct i915_power_domains *power_domains = &display-
> >power.domains;
> +
> +	if ((power_domains->allowed_dc_mask &
> DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
> +		return;
> +
> +	cancel_delayed_work(&intel_dp->psr.dc3co_work);
> +	intel_dc3co_source_unset(display, DC3CO_SOURCE_PSR2);
> +}
> +
> +static void psr2_dc3co_disable_work(struct work_struct *work)
> +{
> +	struct intel_dp *intel_dp =
> +		container_of(work, typeof(*intel_dp),
> psr.dc3co_work.work);
> +
> +	mutex_lock(&intel_dp->psr.lock);
> +	/* If delayed work is pending, it is not idle */
> +	if (delayed_work_pending(&intel_dp->psr.dc3co_work))
> +		goto unlock;
> +	/* enable DC6 after idle frames*/
> +	psr2_dc3co_disable(intel_dp);
> +
> +unlock:
> +	mutex_unlock(&intel_dp->psr.lock);
> +}
> +
> +/*
> + * When we will be completely rely on PSR2 S/W tracking in future,
> + * intel_psr_flush() will invalidate and flush the PSR for
> ORIGIN_FLIP
> + * event also therefore psr2_dc3co_flush_locked() require to be
> changed
> + * accordingly in future.
> + */
> +
> +static void
> +psr2_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int
> frontbuffer_bits,
> +			enum fb_op_origin origin)
> +{
> +	struct intel_display *display = to_intel_display(intel_dp);
> +	struct i915_power_domains *power_domains = &display-
> >power.domains;
> +
> +	if (!(power_domains->allowed_dc_mask &
> DC_STATE_EN_UPTO_DC3CO))
> +		return;
> +
> +	if (!intel_dp->psr.sel_update_enabled ||
> +	    !intel_dp->psr.active)
> +		return;
> +	/*
> +	 * At every frontbuffer flush flip event modified delay of
> delayed work,
> +	 * when delayed work schedules that means display has been
> idle.
> +	 */
> +	if (!(frontbuffer_bits &
> +	    INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
> +		return;
> +
> +	mod_delayed_work(display->wq.unordered, &intel_dp-
> >psr.dc3co_work,
> +			 intel_dp->psr.dc3co_exit_delay);
> +}
> +
>  static bool intel_psr2_sel_fetch_config_valid(struct intel_dp
> *intel_dp,
>  					      struct
> intel_crtc_state *crtc_state)
>  {
> @@ -2117,7 +2189,7 @@ static void intel_psr_exit(struct intel_dp
> *intel_dp)
>  		intel_de_rmw(display, TRANS_DP2_CTL(intel_dp-
> >psr.transcoder),
>  			     TRANS_DP2_PANEL_REPLAY_ENABLE, 0);
>  	} else if (intel_dp->psr.sel_update_enabled) {
> -
> +		psr2_dc3co_disable_on_exit(intel_dp);
>  		val = intel_de_rmw(display,
>  				   EDP_PSR2_CTL(display,
> cpu_transcoder),
>  				   EDP_PSR2_ENABLE, 0);
> @@ -2259,6 +2331,7 @@ void intel_psr_disable(struct intel_dp
> *intel_dp,
>  
>  	mutex_unlock(&intel_dp->psr.lock);
>  	cancel_work_sync(&intel_dp->psr.work);
> +	cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
>  }
>  
>  /**
> @@ -2289,6 +2362,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
>  	mutex_unlock(&psr->lock);
>  
>  	cancel_work_sync(&psr->work);
> +	cancel_delayed_work_sync(&psr->dc3co_work);
>  }
>  
>  /**
> @@ -3475,6 +3549,7 @@ void intel_psr_flush(struct intel_display
> *display,
>  		if (origin == ORIGIN_FLIP ||
>  		    (origin == ORIGIN_CURSOR_UPDATE &&
>  		     !intel_dp->psr.psr2_sel_fetch_enabled)) {
> +			psr2_dc3co_flush_locked(intel_dp,
> frontbuffer_bits, origin);
>  			goto unlock;
>  		}
>  
> @@ -3533,6 +3608,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
>  		intel_dp->psr.link_standby = connector-
> >panel.vbt.psr.full_link;
>  
>  	INIT_WORK(&intel_dp->psr.work, intel_psr_work);
> +	INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work,
> psr2_dc3co_disable_work);
>  	mutex_init(&intel_dp->psr.lock);
>  }
>  


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 6/9] drm/i915/display: alpm enable DC3CO support
  2025-12-09 11:33 ` [PATCH 6/9] drm/i915/display: alpm enable DC3CO support Dibin Moolakadan Subrahmanian
@ 2025-12-12  7:37   ` Hogander, Jouni
  2025-12-16  6:08     ` Dibin Moolakadan Subrahmanian
  0 siblings, 1 reply; 28+ messages in thread
From: Hogander, Jouni @ 2025-12-12  7:37 UTC (permalink / raw)
  To: intel-xe@lists.freedesktop.org, Dibin Moolakadan Subrahmanian,
	intel-gfx@lists.freedesktop.org
  Cc: Shankar, Uma, Manna, Animesh, Deak, Imre

On Tue, 2025-12-09 at 17:03 +0530, Dibin Moolakadan Subrahmanian wrote:
> if DC3CO allowed set PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL
> in ALPM_CTL and update dc3co_source
> 
> Signed-off-by: Dibin Moolakadan Subrahmanian
> <dibin.moolakadan.subrahmanian@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_alpm.c     | 4 ++++
>  drivers/gpu/drm/i915/display/intel_psr_regs.h | 1 +
>  2 files changed, 5 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c
> b/drivers/gpu/drm/i915/display/intel_alpm.c
> index 7ce8c674bb03..28a95f6ddfab 100644
> --- a/drivers/gpu/drm/i915/display/intel_alpm.c
> +++ b/drivers/gpu/drm/i915/display/intel_alpm.c
> @@ -347,6 +347,10 @@ static void lnl_alpm_configure(struct intel_dp
> *intel_dp,
>  
>  	alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(crtc_state-
> >alpm_state.check_entry_lines);
>  
> +	if (intel_dc3co_allowed(display)) {
> +		alpm_ctl |= (PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL);
> +		intel_dc3co_source_set(display, DC3CO_SOURCE_ALPM);

This source concept is generally confusing. More specifically
DC3CO_SOURCE_ALPM I don't understand:

PSR and LOBF are methods to allow switching link off. ALPM is a method
to switch the link off. DC3CO and DC6 are Display power saving states
which are possible as the link is switched off.

BR,

Jouni Högander

> +	}
>  	intel_de_write(display, ALPM_CTL(display, cpu_transcoder),
> alpm_ctl);
>  	mutex_unlock(&intel_dp->alpm.lock);
>  }
> diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h
> b/drivers/gpu/drm/i915/display/intel_psr_regs.h
> index 8afbf5a38335..16a9e3af198d 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
> @@ -268,6 +268,7 @@
>  
>  #define _PR_ALPM_CTL_A	0x60948
>  #define PR_ALPM_CTL(dev_priv, tran)	_MMIO_TRANS2(dev_priv, tran,
> _PR_ALPM_CTL_A)
> +#define 
> PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL			BIT(7)
>  #define 
> PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU	BIT(6)
>  #define 
> PR_ALPM_CTL_RFB_UPDATE_CONTROL				BIT(5)
>  #define 
> PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE	BIT(4)


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 6/9] drm/i915/display: alpm enable DC3CO support
  2025-12-12  7:37   ` Hogander, Jouni
@ 2025-12-16  6:08     ` Dibin Moolakadan Subrahmanian
  0 siblings, 0 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-16  6:08 UTC (permalink / raw)
  To: Hogander, Jouni, intel-xe@lists.freedesktop.org,
	intel-gfx@lists.freedesktop.org
  Cc: Shankar, Uma, Manna, Animesh, Deak, Imre

[-- Attachment #1: Type: text/plain, Size: 2415 bytes --]


On 12-12-2025 13:07, Hogander, Jouni wrote:
> On Tue, 2025-12-09 at 17:03 +0530, Dibin Moolakadan Subrahmanian wrote:
>> if DC3CO allowed set PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL
>> in ALPM_CTL and update dc3co_source
>>
>> Signed-off-by: Dibin Moolakadan Subrahmanian
>> <dibin.moolakadan.subrahmanian@intel.com>
>> ---
>>   drivers/gpu/drm/i915/display/intel_alpm.c     | 4 ++++
>>   drivers/gpu/drm/i915/display/intel_psr_regs.h | 1 +
>>   2 files changed, 5 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c
>> b/drivers/gpu/drm/i915/display/intel_alpm.c
>> index 7ce8c674bb03..28a95f6ddfab 100644
>> --- a/drivers/gpu/drm/i915/display/intel_alpm.c
>> +++ b/drivers/gpu/drm/i915/display/intel_alpm.c
>> @@ -347,6 +347,10 @@ static void lnl_alpm_configure(struct intel_dp
>> *intel_dp,
>>   
>>   	alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(crtc_state-
>>> alpm_state.check_entry_lines);
>>   
>> +	if (intel_dc3co_allowed(display)) {
>> +		alpm_ctl |= (PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL);
>> +		intel_dc3co_source_set(display, DC3CO_SOURCE_ALPM);
> This source concept is generally confusing. More specifically
> DC3CO_SOURCE_ALPM I don't understand:
>
> PSR and LOBF are methods to allow switching link off. ALPM is a method
> to switch the link off. DC3CO and DC6 are Display power saving states
> which are possible as the link is switched off.

Thank you for comments , I want to track the reason for enabling DC3CO.
I will remove DC3CO_SOURCE_ALPM as you pointed, but want to keep
DC3CO_REASON_PSR2 and DC3CO_REASON_LOBF .

> BR,
>
> Jouni Högander
>
>> +	}
>>   	intel_de_write(display, ALPM_CTL(display, cpu_transcoder),
>> alpm_ctl);
>>   	mutex_unlock(&intel_dp->alpm.lock);
>>   }
>> diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h
>> b/drivers/gpu/drm/i915/display/intel_psr_regs.h
>> index 8afbf5a38335..16a9e3af198d 100644
>> --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
>> +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
>> @@ -268,6 +268,7 @@
>>   
>>   #define _PR_ALPM_CTL_A	0x60948
>>   #define PR_ALPM_CTL(dev_priv, tran)	_MMIO_TRANS2(dev_priv, tran,
>> _PR_ALPM_CTL_A)
>> +#define
>> PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL			BIT(7)
>>   #define
>> PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU	BIT(6)
>>   #define
>> PR_ALPM_CTL_RFB_UPDATE_CONTROL				BIT(5)
>>   #define
>> PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE	BIT(4)

[-- Attachment #2: Type: text/html, Size: 3442 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2
  2025-12-12  7:11   ` Hogander, Jouni
@ 2025-12-16  8:24     ` Dibin Moolakadan Subrahmanian
  2025-12-16  8:30       ` Hogander, Jouni
  0 siblings, 1 reply; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-16  8:24 UTC (permalink / raw)
  To: Hogander, Jouni, intel-xe@lists.freedesktop.org,
	intel-gfx@lists.freedesktop.org
  Cc: Shankar, Uma, Manna, Animesh, Deak, Imre

[-- Attachment #1: Type: text/plain, Size: 6147 bytes --]


On 12-12-2025 12:41, Hogander, Jouni wrote:
> On Tue, 2025-12-09 at 17:03 +0530, Dibin Moolakadan Subrahmanian wrote:
>> dc6 should be enabled instead of dc3co after  6 idle frames
>> while in psr2.(re enable part of tgl dc3co handling)
> This is for PSR and pretty much following existing (disabled) TGL DC3CO
> control. What is your idea how selection between DC6 and DC3CO will be
> done in case of LOBF?

For both LOBF and PSR dc3co will be enabled from intel_atomic_commit_tail() it self.
This patch selects DC6 after 6 idle frames for PSR.

> BR,
>
> Jouni Högander
>
>> Signed-off-by: Dibin Moolakadan Subrahmanian
>> <dibin.moolakadan.subrahmanian@intel.com>
>> ---
>>   .../drm/i915/display/intel_display_types.h    |  1 +
>>   drivers/gpu/drm/i915/display/intel_psr.c      | 78
>> ++++++++++++++++++-
>>   2 files changed, 78 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
>> b/drivers/gpu/drm/i915/display/intel_display_types.h
>> index 27f69df7ee9c..6ff53cd58052 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
>> @@ -1759,6 +1759,7 @@ struct intel_psr {
>>   	bool panel_replay_enabled;
>>   	u32 dc3co_exitline;
>>   	u32 dc3co_exit_delay;
>> +	struct delayed_work dc3co_work;
>>   	u8 entry_setup_frames;
>>   
>>   	u8 io_wake_lines;
>> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
>> b/drivers/gpu/drm/i915/display/intel_psr.c
>> index 18bf45455ea2..4be709d1d324 100644
>> --- a/drivers/gpu/drm/i915/display/intel_psr.c
>> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
>> @@ -1157,6 +1157,78 @@ static void psr2_program_idle_frames(struct
>> intel_dp *intel_dp,
>>   		     EDP_PSR2_IDLE_FRAMES(idle_frames));
>>   }
>>   
>> +static void psr2_dc3co_disable(struct intel_dp *intel_dp)
>> +{
>> +	struct intel_display *display = to_intel_display(intel_dp);
>> +	struct i915_power_domains *power_domains = &display-
>>> power.domains;
>> +
>> +	if ((power_domains->allowed_dc_mask &
>> DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
>> +		return;
>> +
>> +	intel_display_power_set_target_dc_state(display,
>> DC_STATE_EN_UPTO_DC6);
>> +	/* Todo restore PSR2 idle frames , ALPM control*/
>> +}
>> +
>> +static void psr2_dc3co_disable_on_exit(struct intel_dp *intel_dp)
>> +{
>> +	struct intel_display *display = to_intel_display(intel_dp);
>> +	struct i915_power_domains *power_domains = &display-
>>> power.domains;
>> +
>> +	if ((power_domains->allowed_dc_mask &
>> DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
>> +		return;
>> +
>> +	cancel_delayed_work(&intel_dp->psr.dc3co_work);
>> +	intel_dc3co_source_unset(display, DC3CO_SOURCE_PSR2);
>> +}
>> +
>> +static void psr2_dc3co_disable_work(struct work_struct *work)
>> +{
>> +	struct intel_dp *intel_dp =
>> +		container_of(work, typeof(*intel_dp),
>> psr.dc3co_work.work);
>> +
>> +	mutex_lock(&intel_dp->psr.lock);
>> +	/* If delayed work is pending, it is not idle */
>> +	if (delayed_work_pending(&intel_dp->psr.dc3co_work))
>> +		goto unlock;
>> +	/* enable DC6 after idle frames*/
>> +	psr2_dc3co_disable(intel_dp);
>> +
>> +unlock:
>> +	mutex_unlock(&intel_dp->psr.lock);
>> +}
>> +
>> +/*
>> + * When we will be completely rely on PSR2 S/W tracking in future,
>> + * intel_psr_flush() will invalidate and flush the PSR for
>> ORIGIN_FLIP
>> + * event also therefore psr2_dc3co_flush_locked() require to be
>> changed
>> + * accordingly in future.
>> + */
>> +
>> +static void
>> +psr2_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int
>> frontbuffer_bits,
>> +			enum fb_op_origin origin)
>> +{
>> +	struct intel_display *display = to_intel_display(intel_dp);
>> +	struct i915_power_domains *power_domains = &display-
>>> power.domains;
>> +
>> +	if (!(power_domains->allowed_dc_mask &
>> DC_STATE_EN_UPTO_DC3CO))
>> +		return;
>> +
>> +	if (!intel_dp->psr.sel_update_enabled ||
>> +	    !intel_dp->psr.active)
>> +		return;
>> +	/*
>> +	 * At every frontbuffer flush flip event modified delay of
>> delayed work,
>> +	 * when delayed work schedules that means display has been
>> idle.
>> +	 */
>> +	if (!(frontbuffer_bits &
>> +	    INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
>> +		return;
>> +
>> +	mod_delayed_work(display->wq.unordered, &intel_dp-
>>> psr.dc3co_work,
>> +			 intel_dp->psr.dc3co_exit_delay);
>> +}
>> +
>>   static bool intel_psr2_sel_fetch_config_valid(struct intel_dp
>> *intel_dp,
>>   					      struct
>> intel_crtc_state *crtc_state)
>>   {
>> @@ -2117,7 +2189,7 @@ static void intel_psr_exit(struct intel_dp
>> *intel_dp)
>>   		intel_de_rmw(display, TRANS_DP2_CTL(intel_dp-
>>> psr.transcoder),
>>   			     TRANS_DP2_PANEL_REPLAY_ENABLE, 0);
>>   	} else if (intel_dp->psr.sel_update_enabled) {
>> -
>> +		psr2_dc3co_disable_on_exit(intel_dp);
>>   		val = intel_de_rmw(display,
>>   				   EDP_PSR2_CTL(display,
>> cpu_transcoder),
>>   				   EDP_PSR2_ENABLE, 0);
>> @@ -2259,6 +2331,7 @@ void intel_psr_disable(struct intel_dp
>> *intel_dp,
>>   
>>   	mutex_unlock(&intel_dp->psr.lock);
>>   	cancel_work_sync(&intel_dp->psr.work);
>> +	cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
>>   }
>>   
>>   /**
>> @@ -2289,6 +2362,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
>>   	mutex_unlock(&psr->lock);
>>   
>>   	cancel_work_sync(&psr->work);
>> +	cancel_delayed_work_sync(&psr->dc3co_work);
>>   }
>>   
>>   /**
>> @@ -3475,6 +3549,7 @@ void intel_psr_flush(struct intel_display
>> *display,
>>   		if (origin == ORIGIN_FLIP ||
>>   		    (origin == ORIGIN_CURSOR_UPDATE &&
>>   		     !intel_dp->psr.psr2_sel_fetch_enabled)) {
>> +			psr2_dc3co_flush_locked(intel_dp,
>> frontbuffer_bits, origin);
>>   			goto unlock;
>>   		}
>>   
>> @@ -3533,6 +3608,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
>>   		intel_dp->psr.link_standby = connector-
>>> panel.vbt.psr.full_link;
>>   
>>   	INIT_WORK(&intel_dp->psr.work, intel_psr_work);
>> +	INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work,
>> psr2_dc3co_disable_work);
>>   	mutex_init(&intel_dp->psr.lock);
>>   }
>>   

[-- Attachment #2: Type: text/html, Size: 7965 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2
  2025-12-16  8:24     ` Dibin Moolakadan Subrahmanian
@ 2025-12-16  8:30       ` Hogander, Jouni
  2025-12-17  7:50         ` Dibin Moolakadan Subrahmanian
  0 siblings, 1 reply; 28+ messages in thread
From: Hogander, Jouni @ 2025-12-16  8:30 UTC (permalink / raw)
  To: intel-xe@lists.freedesktop.org, Dibin Moolakadan Subrahmanian,
	intel-gfx@lists.freedesktop.org
  Cc: Shankar, Uma, Manna, Animesh, Deak, Imre

[-- Attachment #1: Type: text/plain, Size: 6954 bytes --]

On Tue, 2025-12-16 at 13:54 +0530, Dibin Moolakadan Subrahmanian wrote:


On 12-12-2025 12:41, Hogander, Jouni wrote:


On Tue, 2025-12-09 at 17:03 +0530, Dibin Moolakadan Subrahmanian wrote:


dc6 should be enabled instead of dc3co after  6 idle frames

while in psr2.(re enable part of tgl dc3co handling)

This is for PSR and pretty much following existing (disabled) TGL DC3CO

control. What is your idea how selection between DC6 and DC3CO will be

done in case of LOBF?

For both LOBF and PSR dc3co will be enabled from intel_atomic_commit_tail() it self.

This patch selects DC6 after 6 idle frames for PSR.

But how you are planning to do the same for LOBF? I think they should have common control.

BR,
Jouni Högander



BR,


Jouni Högander



Signed-off-by: Dibin Moolakadan Subrahmanian

<dibin.moolakadan.subrahmanian@intel.com><mailto:dibin.moolakadan.subrahmanian@intel.com>

---

 .../drm/i915/display/intel_display_types.h    |  1 +

 drivers/gpu/drm/i915/display/intel_psr.c      | 78

++++++++++++++++++-

 2 files changed, 78 insertions(+), 1 deletion(-)


diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h

b/drivers/gpu/drm/i915/display/intel_display_types.h

index 27f69df7ee9c..6ff53cd58052 100644

--- a/drivers/gpu/drm/i915/display/intel_display_types.h

+++ b/drivers/gpu/drm/i915/display/intel_display_types.h

@@ -1759,6 +1759,7 @@ struct intel_psr {

        bool panel_replay_enabled;

        u32 dc3co_exitline;

        u32 dc3co_exit_delay;

+       struct delayed_work dc3co_work;

        u8 entry_setup_frames;



        u8 io_wake_lines;

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c

b/drivers/gpu/drm/i915/display/intel_psr.c

index 18bf45455ea2..4be709d1d324 100644

--- a/drivers/gpu/drm/i915/display/intel_psr.c

+++ b/drivers/gpu/drm/i915/display/intel_psr.c

@@ -1157,6 +1157,78 @@ static void psr2_program_idle_frames(struct

intel_dp *intel_dp,

                     EDP_PSR2_IDLE_FRAMES(idle_frames));

 }



+static void psr2_dc3co_disable(struct intel_dp *intel_dp)

+{

+       struct intel_display *display = to_intel_display(intel_dp);

+       struct i915_power_domains *power_domains = &display-


power.domains;

+

+       if ((power_domains->allowed_dc_mask &

DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)

+               return;

+

+       intel_display_power_set_target_dc_state(display,

DC_STATE_EN_UPTO_DC6);

+       /* Todo restore PSR2 idle frames , ALPM control*/

+}

+

+static void psr2_dc3co_disable_on_exit(struct intel_dp *intel_dp)

+{

+       struct intel_display *display = to_intel_display(intel_dp);

+       struct i915_power_domains *power_domains = &display-


power.domains;

+

+       if ((power_domains->allowed_dc_mask &

DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)

+               return;

+

+       cancel_delayed_work(&intel_dp->psr.dc3co_work);

+       intel_dc3co_source_unset(display, DC3CO_SOURCE_PSR2);

+}

+

+static void psr2_dc3co_disable_work(struct work_struct *work)

+{

+       struct intel_dp *intel_dp =

+               container_of(work, typeof(*intel_dp),

psr.dc3co_work.work);

+

+       mutex_lock(&intel_dp->psr.lock);

+       /* If delayed work is pending, it is not idle */

+       if (delayed_work_pending(&intel_dp->psr.dc3co_work))

+               goto unlock;

+       /* enable DC6 after idle frames*/

+       psr2_dc3co_disable(intel_dp);

+

+unlock:

+       mutex_unlock(&intel_dp->psr.lock);

+}

+

+/*

+ * When we will be completely rely on PSR2 S/W tracking in future,

+ * intel_psr_flush() will invalidate and flush the PSR for

ORIGIN_FLIP

+ * event also therefore psr2_dc3co_flush_locked() require to be

changed

+ * accordingly in future.

+ */

+

+static void

+psr2_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int

frontbuffer_bits,

+                       enum fb_op_origin origin)

+{

+       struct intel_display *display = to_intel_display(intel_dp);

+       struct i915_power_domains *power_domains = &display-


power.domains;

+

+       if (!(power_domains->allowed_dc_mask &

DC_STATE_EN_UPTO_DC3CO))

+               return;

+

+       if (!intel_dp->psr.sel_update_enabled ||

+           !intel_dp->psr.active)

+               return;

+       /*

+        * At every frontbuffer flush flip event modified delay of

delayed work,

+        * when delayed work schedules that means display has been

idle.

+        */

+       if (!(frontbuffer_bits &

+           INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))

+               return;

+

+       mod_delayed_work(display->wq.unordered, &intel_dp-


psr.dc3co_work,

+                        intel_dp->psr.dc3co_exit_delay);

+}

+

 static bool intel_psr2_sel_fetch_config_valid(struct intel_dp

*intel_dp,

                                              struct

intel_crtc_state *crtc_state)

 {

@@ -2117,7 +2189,7 @@ static void intel_psr_exit(struct intel_dp

*intel_dp)

                intel_de_rmw(display, TRANS_DP2_CTL(intel_dp-


psr.transcoder),

                             TRANS_DP2_PANEL_REPLAY_ENABLE, 0);

        } else if (intel_dp->psr.sel_update_enabled) {

-

+               psr2_dc3co_disable_on_exit(intel_dp);

                val = intel_de_rmw(display,

                                   EDP_PSR2_CTL(display,

cpu_transcoder),

                                   EDP_PSR2_ENABLE, 0);

@@ -2259,6 +2331,7 @@ void intel_psr_disable(struct intel_dp

*intel_dp,



        mutex_unlock(&intel_dp->psr.lock);

        cancel_work_sync(&intel_dp->psr.work);

+       cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);

 }



 /**

@@ -2289,6 +2362,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)

        mutex_unlock(&psr->lock);



        cancel_work_sync(&psr->work);

+       cancel_delayed_work_sync(&psr->dc3co_work);

 }



 /**

@@ -3475,6 +3549,7 @@ void intel_psr_flush(struct intel_display

*display,

                if (origin == ORIGIN_FLIP ||

                    (origin == ORIGIN_CURSOR_UPDATE &&

                     !intel_dp->psr.psr2_sel_fetch_enabled)) {

+                       psr2_dc3co_flush_locked(intel_dp,

frontbuffer_bits, origin);

                        goto unlock;

                }



@@ -3533,6 +3608,7 @@ void intel_psr_init(struct intel_dp *intel_dp)

                intel_dp->psr.link_standby = connector-


panel.vbt.psr.full_link;



        INIT_WORK(&intel_dp->psr.work, intel_psr_work);

+       INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work,

psr2_dc3co_disable_work);

        mutex_init(&intel_dp->psr.lock);

 }




[-- Attachment #2: Type: text/html, Size: 11241 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2
  2025-12-16  8:30       ` Hogander, Jouni
@ 2025-12-17  7:50         ` Dibin Moolakadan Subrahmanian
  0 siblings, 0 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2025-12-17  7:50 UTC (permalink / raw)
  To: Hogander, Jouni, intel-xe@lists.freedesktop.org,
	intel-gfx@lists.freedesktop.org
  Cc: Shankar, Uma, Manna, Animesh, Deak, Imre

[-- Attachment #1: Type: text/plain, Size: 7004 bytes --]


On 16-12-2025 14:00, Hogander, Jouni wrote:
> On Tue, 2025-12-16 at 13:54 +0530, Dibin Moolakadan Subrahmanian wrote:
> >
> >
> > On 12-12-2025 12:41, Hogander, Jouni wrote:
> >
> >> On Tue, 2025-12-09 at 17:03 +0530, Dibin Moolakadan Subrahmanian wrote:
> >>
> >>> dc6 should be enabled instead of dc3co after  6 idle frames
> >>> while in psr2.(re enable part of tgl dc3co handling)
> >> This is for PSR and pretty much following existing (disabled) TGL DC3CO
> >> control. What is your idea how selection between DC6 and DC3CO will be
> >> done in case of LOBF?
> > For both LOBF and PSR dc3co will be enabled from intel_atomic_commit_tail() it self.
> > This patch selects DC6 after 6 idle frames for PSR.
>
> But how you are planning to do the same for LOBF? I think they should have
> common control.

Planning not to enable DC6 for LOBF, only DC3CO will be enabled in LOBF.

> BR,
> Jouni Högander
>
> >
> >> BR,
> >>
> >> Jouni Högander
> >>
> >>
> >>> Signed-off-by: Dibin Moolakadan Subrahmanian
> >>> <dibin.moolakadan.subrahmanian@intel.com>
> >>> ---
> >>>   .../drm/i915/display/intel_display_types.h    |  1 +
> >>>   drivers/gpu/drm/i915/display/intel_psr.c      | 78
> >>> ++++++++++++++++++-
> >>>   2 files changed, 78 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> >>> b/drivers/gpu/drm/i915/display/intel_display_types.h
> >>> index 27f69df7ee9c..6ff53cd58052 100644
> >>> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> >>> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> >>> @@ -1759,6 +1759,7 @@ struct intel_psr {
> >>>   	bool panel_replay_enabled;
> >>>   	u32 dc3co_exitline;
> >>>   	u32 dc3co_exit_delay;
> >>> +	struct delayed_work dc3co_work;
> >>>   	u8 entry_setup_frames;
> >>>   
> >>>   	u8 io_wake_lines;
> >>> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
> >>> b/drivers/gpu/drm/i915/display/intel_psr.c
> >>> index 18bf45455ea2..4be709d1d324 100644
> >>> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> >>> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> >>> @@ -1157,6 +1157,78 @@ static void psr2_program_idle_frames(struct
> >>> intel_dp *intel_dp,
> >>>   		     EDP_PSR2_IDLE_FRAMES(idle_frames));
> >>>   }
> >>>   
> >>> +static void psr2_dc3co_disable(struct intel_dp *intel_dp)
> >>> +{
> >>> +	struct intel_display *display = to_intel_display(intel_dp);
> >>> +	struct i915_power_domains *power_domains = &display-
> >>>
> >>>> power.domains;
> >>> +
> >>> +	if ((power_domains->allowed_dc_mask &
> >>> DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
> >>> +		return;
> >>> +
> >>> +	intel_display_power_set_target_dc_state(display,
> >>> DC_STATE_EN_UPTO_DC6);
> >>> +	/* Todo restore PSR2 idle frames , ALPM control*/
> >>> +}
> >>> +
> >>> +static void psr2_dc3co_disable_on_exit(struct intel_dp *intel_dp)
> >>> +{
> >>> +	struct intel_display *display = to_intel_display(intel_dp);
> >>> +	struct i915_power_domains *power_domains = &display-
> >>>
> >>>> power.domains;
> >>> +
> >>> +	if ((power_domains->allowed_dc_mask &
> >>> DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
> >>> +		return;
> >>> +
> >>> +	cancel_delayed_work(&intel_dp->psr.dc3co_work);
> >>> +	intel_dc3co_source_unset(display, DC3CO_SOURCE_PSR2);
> >>> +}
> >>> +
> >>> +static void psr2_dc3co_disable_work(struct work_struct *work)
> >>> +{
> >>> +	struct intel_dp *intel_dp =
> >>> +		container_of(work, typeof(*intel_dp),
> >>> psr.dc3co_work.work);
> >>> +
> >>> +	mutex_lock(&intel_dp->psr.lock);
> >>> +	/* If delayed work is pending, it is not idle */
> >>> +	if (delayed_work_pending(&intel_dp->psr.dc3co_work))
> >>> +		goto unlock;
> >>> +	/* enable DC6 after idle frames*/
> >>> +	psr2_dc3co_disable(intel_dp);
> >>> +
> >>> +unlock:
> >>> +	mutex_unlock(&intel_dp->psr.lock);
> >>> +}
> >>> +
> >>> +/*
> >>> + * When we will be completely rely on PSR2 S/W tracking in future,
> >>> + * intel_psr_flush() will invalidate and flush the PSR for
> >>> ORIGIN_FLIP
> >>> + * event also therefore psr2_dc3co_flush_locked() require to be
> >>> changed
> >>> + * accordingly in future.
> >>> + */
> >>> +
> >>> +static void
> >>> +psr2_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int
> >>> frontbuffer_bits,
> >>> +			enum fb_op_origin origin)
> >>> +{
> >>> +	struct intel_display *display = to_intel_display(intel_dp);
> >>> +	struct i915_power_domains *power_domains = &display-
> >>>
> >>>> power.domains;
> >>> +
> >>> +	if (!(power_domains->allowed_dc_mask &
> >>> DC_STATE_EN_UPTO_DC3CO))
> >>> +		return;
> >>> +
> >>> +	if (!intel_dp->psr.sel_update_enabled ||
> >>> +	    !intel_dp->psr.active)
> >>> +		return;
> >>> +	/*
> >>> +	 * At every frontbuffer flush flip event modified delay of
> >>> delayed work,
> >>> +	 * when delayed work schedules that means display has been
> >>> idle.
> >>> +	 */
> >>> +	if (!(frontbuffer_bits &
> >>> +	    INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
> >>> +		return;
> >>> +
> >>> +	mod_delayed_work(display->wq.unordered, &intel_dp-
> >>>
> >>>> psr.dc3co_work,
> >>> +			 intel_dp->psr.dc3co_exit_delay);
> >>> +}
> >>> +
> >>>   static bool intel_psr2_sel_fetch_config_valid(struct intel_dp
> >>> *intel_dp,
> >>>   					      struct
> >>> intel_crtc_state *crtc_state)
> >>>   {
> >>> @@ -2117,7 +2189,7 @@ static void intel_psr_exit(struct intel_dp
> >>> *intel_dp)
> >>>   		intel_de_rmw(display, TRANS_DP2_CTL(intel_dp-
> >>>
> >>>> psr.transcoder),
> >>>   			     TRANS_DP2_PANEL_REPLAY_ENABLE, 0);
> >>>   	} else if (intel_dp->psr.sel_update_enabled) {
> >>> -
> >>> +		psr2_dc3co_disable_on_exit(intel_dp);
> >>>   		val = intel_de_rmw(display,
> >>>   				   EDP_PSR2_CTL(display,
> >>> cpu_transcoder),
> >>>   				   EDP_PSR2_ENABLE, 0);
> >>> @@ -2259,6 +2331,7 @@ void intel_psr_disable(struct intel_dp
> >>> *intel_dp,
> >>>   
> >>>   	mutex_unlock(&intel_dp->psr.lock);
> >>>   	cancel_work_sync(&intel_dp->psr.work);
> >>> +	cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
> >>>   }
> >>>   
> >>>   /**
> >>> @@ -2289,6 +2362,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
> >>>   	mutex_unlock(&psr->lock);
> >>>   
> >>>   	cancel_work_sync(&psr->work);
> >>> +	cancel_delayed_work_sync(&psr->dc3co_work);
> >>>   }
> >>>   
> >>>   /**
> >>> @@ -3475,6 +3549,7 @@ void intel_psr_flush(struct intel_display
> >>> *display,
> >>>   		if (origin == ORIGIN_FLIP ||
> >>>   		    (origin == ORIGIN_CURSOR_UPDATE &&
> >>>   		     !intel_dp->psr.psr2_sel_fetch_enabled)) {
> >>> +			psr2_dc3co_flush_locked(intel_dp,
> >>> frontbuffer_bits, origin);
> >>>   			goto unlock;
> >>>   		}
> >>>   
> >>> @@ -3533,6 +3608,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
> >>>   		intel_dp->psr.link_standby = connector-
> >>>
> >>>> panel.vbt.psr.full_link;
> >>>   
> >>>   	INIT_WORK(&intel_dp->psr.work, intel_psr_work);
> >>> +	INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work,
> >>> psr2_dc3co_disable_work);
> >>>   	mutex_init(&intel_dp->psr.lock);
> >>>   }
> >>>   
>

[-- Attachment #2: Type: text/html, Size: 9119 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] drm/i915/display: Replace DC_STATE_EN_DC3CO with DC_STATE_EN_UPTO_DC3CO
  2025-12-09 11:33 ` [PATCH 2/9] drm/i915/display: Replace DC_STATE_EN_DC3CO with DC_STATE_EN_UPTO_DC3CO Dibin Moolakadan Subrahmanian
@ 2026-01-05 12:45   ` Jani Nikula
  2026-01-06 10:40     ` Dibin Moolakadan Subrahmanian
  0 siblings, 1 reply; 28+ messages in thread
From: Jani Nikula @ 2026-01-05 12:45 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com> wrote:
> DC3CO no longer uses a standalone enable bit but part of existing
> UPTO_DC* enable bits.

"no longer" for register contents absolutely requires references to the
platforms.

>
> Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display_power.c      | 6 +++---
>  drivers/gpu/drm/i915/display/intel_display_power_well.c | 4 ++--
>  drivers/gpu/drm/i915/display/intel_display_regs.h       | 2 +-
>  drivers/gpu/drm/i915/display/intel_dmc_wl.c             | 2 +-
>  4 files changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index 9f323c39d798..0961b194554c 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -267,7 +267,7 @@ sanitize_target_dc_state(struct intel_display *display,
>  	static const u32 states[] = {
>  		DC_STATE_EN_UPTO_DC6,
>  		DC_STATE_EN_UPTO_DC5,
> -		DC_STATE_EN_DC3CO,
> +		DC_STATE_EN_UPTO_DC3CO,
>  		DC_STATE_DISABLE,
>  	};
>  	int i;
> @@ -999,10 +999,10 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
>  
>  	switch (requested_dc) {
>  	case 4:
> -		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6;
> +		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC6;
>  		break;
>  	case 3:
> -		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC5;
> +		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC5;
>  		break;
>  	case 2:
>  		mask |= DC_STATE_EN_UPTO_DC6;
> 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 2dce622eb5d8..6f62a4420f6e 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
> @@ -727,7 +727,7 @@ static u32 gen9_dc_mask(struct intel_display *display)
>  	mask = DC_STATE_EN_UPTO_DC5;
>  
>  	if (DISPLAY_VER(display) >= 12)
> -		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6
> +		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC6
>  					  | DC_STATE_EN_DC9;
>  	else if (DISPLAY_VER(display) == 11)
>  		mask |= DC_STATE_EN_UPTO_DC6 | DC_STATE_EN_DC9;
> @@ -977,7 +977,7 @@ static void bxt_verify_dpio_phy_power_wells(struct intel_display *display)
>  static bool gen9_dc_off_power_well_enabled(struct intel_display *display,
>  					   struct i915_power_well *power_well)
>  {
> -	return ((intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_DC3CO) == 0 &&
> +	return ((intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_UPTO_DC3CO) == 0 &&
>  		(intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
> index 9e0d853f4b61..7e620e22718b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> @@ -2819,13 +2819,13 @@ enum skl_power_gate {
>  /* GEN9 DC */
>  #define DC_STATE_EN			_MMIO(0x45504)
>  #define  DC_STATE_DISABLE		0
> -#define  DC_STATE_EN_DC3CO		REG_BIT(30)
>  #define  DC_STATE_DC3CO_STATUS		REG_BIT(29)
>  #define  HOLD_PHY_CLKREQ_PG1_LATCH	REG_BIT(21)
>  #define  HOLD_PHY_PG1_LATCH		REG_BIT(20)
>  #define  DC_STATE_EN_UPTO_DC5		(1 << 0)
>  #define  DC_STATE_EN_DC9		(1 << 3)
>  #define  DC_STATE_EN_UPTO_DC6		(2 << 0)
> +#define  DC_STATE_EN_UPTO_DC3CO		(3 << 0)

This could use a conversion to REG_FIELD_MASK and REG_FIELD_PREP.

>  #define  DC_STATE_EN_UPTO_DC5_DC6_MASK   0x3
>  
>  #define  DC_STATE_DEBUG                  _MMIO(0x45520)
> diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c
> index 73a3101514f3..9f403b7820ab 100644
> --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c
> +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c
> @@ -260,7 +260,7 @@ static bool intel_dmc_wl_check_range(struct intel_display *display,
>  	 * the DMC and requires a DC exit for proper access.
>  	 */
>  	switch (dc_state) {
> -	case DC_STATE_EN_DC3CO:
> +	case DC_STATE_EN_UPTO_DC3CO:
>  		ranges = xe3lpd_dc3co_dmc_ranges;
>  		break;
>  	case DC_STATE_EN_UPTO_DC5:

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 4/9] drm/i915/display: Add DC3CO eligibility logic
  2025-12-09 11:33 ` [PATCH 4/9] drm/i915/display: Add DC3CO eligibility logic Dibin Moolakadan Subrahmanian
@ 2026-01-05 12:55   ` Jani Nikula
  2026-01-06 12:58     ` Dibin Moolakadan Subrahmanian
  0 siblings, 1 reply; 28+ messages in thread
From: Jani Nikula @ 2026-01-05 12:55 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com> wrote:
> Introduce dc3co_allow in struct intel_display and determine DC3CO
> eligibility during atomic_check(). DC3CO is permitted only when:
>
>   - the active pipe drives eDP,
>   - the pipe is single-pipe (no joiner),
>   - the pipe/port combination supports DC3CO.
>
> When eligible, intel_atomic_commit_tail() programs the target DC state
> as DC_STATE_EN_UPTO_DC3CO; otherwise we fall back to DC6. Update the
> PSR vblank enable/disable path to follow the same policy.
>
> Also extend get_allowed_dc_mask() to expose DC3CO support on
> DISPLAY_VER >= 35.
>
> Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  | 75 +++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_display.h  |  1 +
>  .../gpu/drm/i915/display/intel_display_core.h |  3 +
>  .../drm/i915/display/intel_display_power.c    |  4 +-
>  drivers/gpu/drm/i915/display/intel_psr.c      | 13 ++--
>  5 files changed, 87 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 9c6d3ecdb589..205f55a87736 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -6295,6 +6295,75 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state)
>  	return 0;
>  }
>  
> +bool intel_dc3co_allowed(struct intel_display *display)
> +{
> +	return display->power.dc3co_allow;

Very few files should touch display->power, and this is not one of them.

'git grep "display->power" -- drivers/gpu/drm/i915/display'

When is it okay to call this function and expect to get sane results?

> +}
> +
> +static bool intel_dc3co_port_pipe_compatible(struct intel_dp *intel_dp,
> +					     const struct intel_crtc_state *crtc_state)
> +{
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
> +	enum port port = dig_port->base.port;
> +	int num_pipes = intel_crtc_num_joined_pipes(crtc_state);
> +
> +	if (num_pipes != 1)
> +		return false;
> +
> +	if (!(pipe <= PIPE_B && port <= PORT_B))
> +		return false;
> +
> +	return true;

That's a really complicated way to say

	return num_pipes == 1 && pipe <= PIPEB && port <= PORT_B;

> +}
> +
> +static void intel_dc3co_allow_check(struct intel_atomic_state *state)

What does "check" mean here? Or in *any* function?

Check sounds like something that's a pure function that doesn't change
anything... but this does.

> +{
> +	struct intel_display *display = to_intel_display(state);
> +	struct intel_crtc *crtc;
> +	struct intel_crtc_state *new_crtc_state;
> +	struct intel_encoder *encoder;
> +	struct intel_dp *intel_dp;
> +	int i;
> +	struct i915_power_domains *power_domains = &display->power.domains;
> +	bool any_active = false;
> +	bool allow = true;
> +
> +	display->power.dc3co_allow = 0;

That's now cached state with no stated rules on when it's valid and when
it's not.

> +
> +	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
> +		return;
> +
> +	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
> +		if (!new_crtc_state->hw.active)
> +			continue;
> +
> +		any_active = true;
> +
> +		for_each_intel_encoder_mask(display->drm, encoder,
> +					    new_crtc_state->uapi.encoder_mask) {
> +			/* If any active pipe not eDP disable*/

What?

> +			if (!intel_encoder_is_dp(encoder) ||
> +			    encoder->type != INTEL_OUTPUT_EDP) {
> +				allow = false;
> +				goto out;
> +			}
> +			intel_dp = enc_to_intel_dp(encoder);
> +			/* Port, joiner, pipe placement checks */

Is that a helpful comment?

> +			if (!intel_dc3co_port_pipe_compatible(intel_dp, new_crtc_state)) {
> +				allow = false;
> +				goto out;
> +			}
> +		}
> +	}
> +
> +	if (!any_active)
> +		allow = false;
> +
> +out:
> +	display->power.dc3co_allow = allow;
> +}
> +

intel_display.[ch] is not the dumping ground for random new code. The
goal is to *reduce* the size of it, not increase.

>  static int intel_atomic_check_config(struct intel_atomic_state *state,
>  				     struct intel_link_bw_limits *limits,
>  				     enum pipe *failed_pipe)
> @@ -6565,6 +6634,8 @@ int intel_atomic_check(struct drm_device *dev,
>  	if (ret)
>  		goto fail;
>  
> +	intel_dc3co_allow_check(state);
> +
>  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>  					    new_crtc_state, i) {
>  		intel_color_assert_luts(new_crtc_state);
> @@ -7601,6 +7672,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>  		 */
>  		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
>  	}
> +	if (intel_dc3co_allowed(display))
> +		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC3CO);
> +	else
> +		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
>  	/*
>  	 * Delay re-enabling DC states by 17 ms to avoid the off->on->off
>  	 * toggling overhead at and above 60 FPS.
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index f8e6e4e82722..97987f082560 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -560,5 +560,6 @@ bool assert_port_valid(struct intel_display *display, enum port port);
>  
>  bool intel_scanout_needs_vtd_wa(struct intel_display *display);
>  int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
> +bool intel_dc3co_allowed(struct intel_display *display);
>  
>  #endif
> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
> index d708d322aa85..fa567c95029c 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> @@ -538,6 +538,9 @@ struct intel_display {
>  
>  		/* perform PHY state sanity checks? */
>  		bool chv_phy_assert[2];
> +
> +		/* mark dc3co entry is allowed*/

		                              ^- space missing

> +		bool dc3co_allow;

Still unclear when this is valid.

>  	} power;
>  
>  	struct {
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index 0961b194554c..e99552f18756 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -956,7 +956,9 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
>  	if (!HAS_DISPLAY(display))
>  		return 0;
>  
> -	if (DISPLAY_VER(display) >= 20)
> +	if (DISPLAY_VER(display) >= 35)
> +		max_dc = 3;
> +	else if (DISPLAY_VER(display) >= 20)
>  		max_dc = 2;
>  	else if (display->platform.dg2)
>  		max_dc = 1;
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
> index 753359069044..9c616f449ad6 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -3903,14 +3903,11 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
>  		return;
>  	}
>  
> -	/*
> -	 * NOTE: intel_display_power_set_target_dc_state is used
> -	 * only by PSR * code for DC3CO handling. DC3CO target
> -	 * state is currently disabled in * PSR code. If DC3CO
> -	 * is taken into use we need take that into account here
> -	 * as well.
> -	 */
> -	intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
> +	if (intel_dc3co_allowed(display))
> +		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
> +						DC_STATE_EN_UPTO_DC3CO);
> +	else
> +		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
>  						DC_STATE_EN_UPTO_DC6);
>  }

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 5/9] drm/i915/display: Track DC3CO enable source
  2025-12-09 11:33 ` [PATCH 5/9] drm/i915/display: Track DC3CO enable source Dibin Moolakadan Subrahmanian
@ 2026-01-05 12:56   ` Jani Nikula
  0 siblings, 0 replies; 28+ messages in thread
From: Jani Nikula @ 2026-01-05 12:56 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com> wrote:
> Introduce a bitmask enum intel_dc3co_source to record which display
> features (PSR2, ALPM, LOBF) contribute to allowing DC3CO entry.
> The source tracking is added here and will be integrated into the DC3CO
> allow logic in follow-up commits.
> Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c       | 11 +++++++++++
>  drivers/gpu/drm/i915/display/intel_display.h       |  4 +++-
>  drivers/gpu/drm/i915/display/intel_display_core.h  |  1 +
>  drivers/gpu/drm/i915/display/intel_display_power.h | 10 ++++++++++
>  4 files changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 205f55a87736..b14a1c9f80bd 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -6300,6 +6300,16 @@ bool intel_dc3co_allowed(struct intel_display *display)
>  	return display->power.dc3co_allow;
>  }
>  
> +void intel_dc3co_source_set(struct intel_display *display, enum intel_dc3co_source source)
> +{
> +	display->power.dc3co_source |= source;
> +}
> +
> +void intel_dc3co_source_unset(struct intel_display *display, enum intel_dc3co_source source)
> +{
> +	display->power.dc3co_source &= ~source;
> +}
> +

These don't belong in intel_display.[ch].

>  static bool intel_dc3co_port_pipe_compatible(struct intel_dp *intel_dp,
>  					     const struct intel_crtc_state *crtc_state)
>  {
> @@ -6330,6 +6340,7 @@ static void intel_dc3co_allow_check(struct intel_atomic_state *state)
>  	bool allow = true;
>  
>  	display->power.dc3co_allow = 0;
> +	intel_dc3co_source_unset(display, DC3CO_SOURCE_ALL);
>  
>  	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
>  		return;
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index 97987f082560..87bbf1f66209 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -46,6 +46,7 @@ struct intel_link_m_n;
>  struct intel_plane;
>  struct intel_plane_state;
>  struct intel_power_domain_mask;
> +enum intel_dc3co_source;
>  
>  #define pipe_name(p) ((p) + 'A')
>  
> @@ -561,5 +562,6 @@ bool assert_port_valid(struct intel_display *display, enum port port);
>  bool intel_scanout_needs_vtd_wa(struct intel_display *display);
>  int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
>  bool intel_dc3co_allowed(struct intel_display *display);
> -
> +void intel_dc3co_source_set(struct intel_display *display, enum intel_dc3co_source source);
> +void intel_dc3co_source_unset(struct intel_display *display, enum intel_dc3co_source source);
>  #endif
> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
> index fa567c95029c..4ce34c567dbd 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> @@ -541,6 +541,7 @@ struct intel_display {
>  
>  		/* mark dc3co entry is allowed*/
>  		bool dc3co_allow;
> +		u32 dc3co_source;
>  	} power;
>  
>  	struct {
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
> index d616d5d09cbe..dde07f931963 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.h
> @@ -131,6 +131,16 @@ struct intel_power_domain_mask {
>  	DECLARE_BITMAP(bits, POWER_DOMAIN_NUM);
>  };
>  
> +enum intel_dc3co_source {
> +	DC3CO_SOURCE_NONE = 0,
> +	DC3CO_SOURCE_PSR2 = BIT(0),
> +	DC3CO_SOURCE_ALPM = BIT(1),
> +	DC3CO_SOURCE_LOBF = BIT(2),
> +	DC3CO_SOURCE_ALL  = DC3CO_SOURCE_PSR2 |
> +			    DC3CO_SOURCE_ALPM |
> +			    DC3CO_SOURCE_LOBF,
> +};
> +
>  struct i915_power_domains {
>  	/*
>  	 * Power wells needed for initialization at driver init and suspend

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 8/9] drm/i915/display: Add intel_dc3co_can_enable() helper
  2025-12-09 11:33 ` [PATCH 8/9] drm/i915/display: Add intel_dc3co_can_enable() helper Dibin Moolakadan Subrahmanian
@ 2026-01-05 12:56   ` Jani Nikula
  0 siblings, 0 replies; 28+ messages in thread
From: Jani Nikula @ 2026-01-05 12:56 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com> wrote:
> Introduce a new helper that validates whether DC3CO can be enabled
> based on both allow  and source.
>
> Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c | 11 ++++++++++-
>  drivers/gpu/drm/i915/display/intel_display.h |  1 +
>  drivers/gpu/drm/i915/display/intel_psr.c     |  2 +-
>  3 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index b14a1c9f80bd..9f9ba58371ab 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -6295,6 +6295,15 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state)
>  	return 0;
>  }
>  
> +bool intel_dc3co_can_enable(struct intel_display *display)
> +{
> +	/*
> +	 * ToDo - Check CMTG enabled
> +	 * ToDo - Check flipq enabled
> +	 */
> +	return (display->power.dc3co_allow && display->power.dc3co_source);
> +}
> +

This doesn't belong in intel_display.[ch].

>  bool intel_dc3co_allowed(struct intel_display *display)
>  {
>  	return display->power.dc3co_allow;
> @@ -7683,7 +7692,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>  		 */
>  		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
>  	}
> -	if (intel_dc3co_allowed(display))
> +	if (intel_dc3co_can_enable(display))
>  		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC3CO);
>  	else
>  		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index 87bbf1f66209..f704cce4f1d8 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -564,4 +564,5 @@ int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
>  bool intel_dc3co_allowed(struct intel_display *display);
>  void intel_dc3co_source_set(struct intel_display *display, enum intel_dc3co_source source);
>  void intel_dc3co_source_unset(struct intel_display *display, enum intel_dc3co_source source);
> +bool intel_dc3co_can_enable(struct intel_display *display);
>  #endif
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
> index d4c5dc6dcc82..18bf45455ea2 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -3909,7 +3909,7 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
>  		return;
>  	}
>  
> -	if (intel_dc3co_allowed(display))
> +	if (intel_dc3co_can_enable(display))
>  		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
>  						DC_STATE_EN_UPTO_DC3CO);
>  	else

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2
  2025-12-09 11:33 ` [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2 Dibin Moolakadan Subrahmanian
  2025-12-12  7:11   ` Hogander, Jouni
@ 2026-01-05 13:01   ` Jani Nikula
  2026-01-06 13:28     ` Dibin Moolakadan Subrahmanian
  1 sibling, 1 reply; 28+ messages in thread
From: Jani Nikula @ 2026-01-05 13:01 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com> wrote:
> dc6 should be enabled instead of dc3co after  6 idle frames
> while in psr2.(re enable part of tgl dc3co handling)

Please write proper commit messages. I don't understand what this patch
is supposed to do based on this.

> Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
> ---
>  .../drm/i915/display/intel_display_types.h    |  1 +
>  drivers/gpu/drm/i915/display/intel_psr.c      | 78 ++++++++++++++++++-
>  2 files changed, 78 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 27f69df7ee9c..6ff53cd58052 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1759,6 +1759,7 @@ struct intel_psr {
>  	bool panel_replay_enabled;
>  	u32 dc3co_exitline;
>  	u32 dc3co_exit_delay;
> +	struct delayed_work dc3co_work;
>  	u8 entry_setup_frames;
>  
>  	u8 io_wake_lines;
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
> index 18bf45455ea2..4be709d1d324 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -1157,6 +1157,78 @@ static void psr2_program_idle_frames(struct intel_dp *intel_dp,
>  		     EDP_PSR2_IDLE_FRAMES(idle_frames));
>  }
>  
> +static void psr2_dc3co_disable(struct intel_dp *intel_dp)
> +{
> +	struct intel_display *display = to_intel_display(intel_dp);
> +	struct i915_power_domains *power_domains = &display->power.domains;

There's currently one place in intel_psr.c that checks
power_domains->allowed_dc_mask, and I think even that is too much.

display->power belongs to intel_display_power*.c, and nobody else.

I think you probably need a helper function to ask for this stuff from
power modules.

> +
> +	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
> +		return;
> +
> +	intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
> +	/* Todo restore PSR2 idle frames , ALPM control*/

	/* TODO: restore PSR2 idle frames, ALPM control */

> +}
> +
> +static void psr2_dc3co_disable_on_exit(struct intel_dp *intel_dp)
> +{
> +	struct intel_display *display = to_intel_display(intel_dp);
> +	struct i915_power_domains *power_domains = &display->power.domains;
> +
> +	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
> +		return;
> +
> +	cancel_delayed_work(&intel_dp->psr.dc3co_work);
> +	intel_dc3co_source_unset(display, DC3CO_SOURCE_PSR2);
> +}
> +
> +static void psr2_dc3co_disable_work(struct work_struct *work)
> +{
> +	struct intel_dp *intel_dp =
> +		container_of(work, typeof(*intel_dp), psr.dc3co_work.work);
> +
> +	mutex_lock(&intel_dp->psr.lock);
> +	/* If delayed work is pending, it is not idle */
> +	if (delayed_work_pending(&intel_dp->psr.dc3co_work))
> +		goto unlock;
> +	/* enable DC6 after idle frames*/
> +	psr2_dc3co_disable(intel_dp);
> +
> +unlock:
> +	mutex_unlock(&intel_dp->psr.lock);
> +}
> +
> +/*
> + * When we will be completely rely on PSR2 S/W tracking in future,
> + * intel_psr_flush() will invalidate and flush the PSR for ORIGIN_FLIP
> + * event also therefore psr2_dc3co_flush_locked() require to be changed
> + * accordingly in future.
> + */
> +
> +static void
> +psr2_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
> +			enum fb_op_origin origin)
> +{
> +	struct intel_display *display = to_intel_display(intel_dp);
> +	struct i915_power_domains *power_domains = &display->power.domains;
> +
> +	if (!(power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO))
> +		return;
> +
> +	if (!intel_dp->psr.sel_update_enabled ||
> +	    !intel_dp->psr.active)
> +		return;
> +	/*
> +	 * At every frontbuffer flush flip event modified delay of delayed work,
> +	 * when delayed work schedules that means display has been idle.
> +	 */
> +	if (!(frontbuffer_bits &
> +	    INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
> +		return;
> +
> +	mod_delayed_work(display->wq.unordered, &intel_dp->psr.dc3co_work,
> +			 intel_dp->psr.dc3co_exit_delay);
> +}
> +
>  static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp,
>  					      struct intel_crtc_state *crtc_state)
>  {
> @@ -2117,7 +2189,7 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
>  		intel_de_rmw(display, TRANS_DP2_CTL(intel_dp->psr.transcoder),
>  			     TRANS_DP2_PANEL_REPLAY_ENABLE, 0);
>  	} else if (intel_dp->psr.sel_update_enabled) {
> -
> +		psr2_dc3co_disable_on_exit(intel_dp);
>  		val = intel_de_rmw(display,
>  				   EDP_PSR2_CTL(display, cpu_transcoder),
>  				   EDP_PSR2_ENABLE, 0);
> @@ -2259,6 +2331,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
>  
>  	mutex_unlock(&intel_dp->psr.lock);
>  	cancel_work_sync(&intel_dp->psr.work);
> +	cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
>  }
>  
>  /**
> @@ -2289,6 +2362,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
>  	mutex_unlock(&psr->lock);
>  
>  	cancel_work_sync(&psr->work);
> +	cancel_delayed_work_sync(&psr->dc3co_work);
>  }
>  
>  /**
> @@ -3475,6 +3549,7 @@ void intel_psr_flush(struct intel_display *display,
>  		if (origin == ORIGIN_FLIP ||
>  		    (origin == ORIGIN_CURSOR_UPDATE &&
>  		     !intel_dp->psr.psr2_sel_fetch_enabled)) {
> +			psr2_dc3co_flush_locked(intel_dp, frontbuffer_bits, origin);
>  			goto unlock;
>  		}
>  
> @@ -3533,6 +3608,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
>  		intel_dp->psr.link_standby = connector->panel.vbt.psr.full_link;
>  
>  	INIT_WORK(&intel_dp->psr.work, intel_psr_work);
> +	INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, psr2_dc3co_disable_work);
>  	mutex_init(&intel_dp->psr.lock);
>  }

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 7/9] drm/i915/display: psr enable DC3CO support
  2025-12-09 11:33 ` [PATCH 7/9] drm/i915/display: psr " Dibin Moolakadan Subrahmanian
@ 2026-01-05 13:02   ` Jani Nikula
  2026-01-06 13:10     ` Dibin Moolakadan Subrahmanian
  0 siblings, 1 reply; 28+ messages in thread
From: Jani Nikula @ 2026-01-05 13:02 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com> wrote:
> if DC3CO allowed and psr2 is enabled, update dc3co_source

Yeah, I can read the code, but what does it mean? Why?

>
> Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_psr.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
> index 9c616f449ad6..d4c5dc6dcc82 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -3007,6 +3007,12 @@ void intel_psr_post_plane_update(struct intel_atomic_state *state,
>  		if (crtc_state->crc_enabled && psr->enabled)
>  			intel_psr_force_update(intel_dp);
>  
> +		if (psr->enabled &&
> +		    psr->sel_update_enabled &&
> +		    intel_dc3co_allowed(display)) {
> +			intel_dc3co_source_set(display, DC3CO_SOURCE_PSR2);
> +		}
> +
>  		/*
>  		 * Clear possible busy bits in case we have
>  		 * invalidate -> flip -> flush sequence.

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/9] drm/i915/display: Replace DC_STATE_EN_DC3CO with DC_STATE_EN_UPTO_DC3CO
  2026-01-05 12:45   ` Jani Nikula
@ 2026-01-06 10:40     ` Dibin Moolakadan Subrahmanian
  0 siblings, 0 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2026-01-06 10:40 UTC (permalink / raw)
  To: Jani Nikula, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

[-- Attachment #1: Type: text/plain, Size: 4608 bytes --]


On 05-01-2026 18:15, Jani Nikula wrote:
> On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com> wrote:
>> DC3CO no longer uses a standalone enable bit but part of existing
>> UPTO_DC* enable bits.
> "no longer" for register contents absolutely requires references to the
> platforms.

I will add platform details here.

Regards,
Dibin

>> Signed-off-by: Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com>
>> ---
>>   drivers/gpu/drm/i915/display/intel_display_power.c      | 6 +++---
>>   drivers/gpu/drm/i915/display/intel_display_power_well.c | 4 ++--
>>   drivers/gpu/drm/i915/display/intel_display_regs.h       | 2 +-
>>   drivers/gpu/drm/i915/display/intel_dmc_wl.c             | 2 +-
>>   4 files changed, 7 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
>> index 9f323c39d798..0961b194554c 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
>> @@ -267,7 +267,7 @@ sanitize_target_dc_state(struct intel_display *display,
>>   	static const u32 states[] = {
>>   		DC_STATE_EN_UPTO_DC6,
>>   		DC_STATE_EN_UPTO_DC5,
>> -		DC_STATE_EN_DC3CO,
>> +		DC_STATE_EN_UPTO_DC3CO,
>>   		DC_STATE_DISABLE,
>>   	};
>>   	int i;
>> @@ -999,10 +999,10 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
>>   
>>   	switch (requested_dc) {
>>   	case 4:
>> -		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6;
>> +		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC6;
>>   		break;
>>   	case 3:
>> -		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC5;
>> +		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC5;
>>   		break;
>>   	case 2:
>>   		mask |= DC_STATE_EN_UPTO_DC6;
>> 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 2dce622eb5d8..6f62a4420f6e 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
>> @@ -727,7 +727,7 @@ static u32 gen9_dc_mask(struct intel_display *display)
>>   	mask = DC_STATE_EN_UPTO_DC5;
>>   
>>   	if (DISPLAY_VER(display) >= 12)
>> -		mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6
>> +		mask |= DC_STATE_EN_UPTO_DC3CO | DC_STATE_EN_UPTO_DC6
>>   					  | DC_STATE_EN_DC9;
>>   	else if (DISPLAY_VER(display) == 11)
>>   		mask |= DC_STATE_EN_UPTO_DC6 | DC_STATE_EN_DC9;
>> @@ -977,7 +977,7 @@ static void bxt_verify_dpio_phy_power_wells(struct intel_display *display)
>>   static bool gen9_dc_off_power_well_enabled(struct intel_display *display,
>>   					   struct i915_power_well *power_well)
>>   {
>> -	return ((intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_DC3CO) == 0 &&
>> +	return ((intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_UPTO_DC3CO) == 0 &&
>>   		(intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
>>   }
>>   
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> index 9e0d853f4b61..7e620e22718b 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> @@ -2819,13 +2819,13 @@ enum skl_power_gate {
>>   /* GEN9 DC */
>>   #define DC_STATE_EN			_MMIO(0x45504)
>>   #define  DC_STATE_DISABLE		0
>> -#define  DC_STATE_EN_DC3CO		REG_BIT(30)
>>   #define  DC_STATE_DC3CO_STATUS		REG_BIT(29)
>>   #define  HOLD_PHY_CLKREQ_PG1_LATCH	REG_BIT(21)
>>   #define  HOLD_PHY_PG1_LATCH		REG_BIT(20)
>>   #define  DC_STATE_EN_UPTO_DC5		(1 << 0)
>>   #define  DC_STATE_EN_DC9		(1 << 3)
>>   #define  DC_STATE_EN_UPTO_DC6		(2 << 0)
>> +#define  DC_STATE_EN_UPTO_DC3CO		(3 << 0)
> This could use a conversion to REG_FIELD_MASK and REG_FIELD_PREP.
>
>>   #define  DC_STATE_EN_UPTO_DC5_DC6_MASK   0x3
>>   
>>   #define  DC_STATE_DEBUG                  _MMIO(0x45520)
>> diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c
>> index 73a3101514f3..9f403b7820ab 100644
>> --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c
>> +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c
>> @@ -260,7 +260,7 @@ static bool intel_dmc_wl_check_range(struct intel_display *display,
>>   	 * the DMC and requires a DC exit for proper access.
>>   	 */
>>   	switch (dc_state) {
>> -	case DC_STATE_EN_DC3CO:
>> +	case DC_STATE_EN_UPTO_DC3CO:
>>   		ranges = xe3lpd_dc3co_dmc_ranges;
>>   		break;
>>   	case DC_STATE_EN_UPTO_DC5:

[-- Attachment #2: Type: text/html, Size: 5523 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 4/9] drm/i915/display: Add DC3CO eligibility logic
  2026-01-05 12:55   ` Jani Nikula
@ 2026-01-06 12:58     ` Dibin Moolakadan Subrahmanian
  2026-01-07  9:14       ` Jani Nikula
  0 siblings, 1 reply; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2026-01-06 12:58 UTC (permalink / raw)
  To: Jani Nikula, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

[-- Attachment #1: Type: text/plain, Size: 8999 bytes --]


On 05-01-2026 18:25, Jani Nikula wrote:
> On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com> wrote:
>> Introduce dc3co_allow in struct intel_display and determine DC3CO
>> eligibility during atomic_check(). DC3CO is permitted only when:
>>
>>    - the active pipe drives eDP,
>>    - the pipe is single-pipe (no joiner),
>>    - the pipe/port combination supports DC3CO.
>>
>> When eligible, intel_atomic_commit_tail() programs the target DC state
>> as DC_STATE_EN_UPTO_DC3CO; otherwise we fall back to DC6. Update the
>> PSR vblank enable/disable path to follow the same policy.
>>
>> Also extend get_allowed_dc_mask() to expose DC3CO support on
>> DISPLAY_VER >= 35.
>>
>> Signed-off-by: Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com>
>> ---
>>   drivers/gpu/drm/i915/display/intel_display.c  | 75 +++++++++++++++++++
>>   drivers/gpu/drm/i915/display/intel_display.h  |  1 +
>>   .../gpu/drm/i915/display/intel_display_core.h |  3 +
>>   .../drm/i915/display/intel_display_power.c    |  4 +-
>>   drivers/gpu/drm/i915/display/intel_psr.c      | 13 ++--
>>   5 files changed, 87 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>> index 9c6d3ecdb589..205f55a87736 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -6295,6 +6295,75 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state)
>>   	return 0;
>>   }
>>   
>> +bool intel_dc3co_allowed(struct intel_display *display)
>> +{
>> +	return display->power.dc3co_allow;
> Very few files should touch display->power, and this is not one of them.
>
> 'git grep "display->power" -- drivers/gpu/drm/i915/display'

Yes, git grep shows few files , I will try to move all dc3co functions to
drivers/gpu/drm/i915/display/intel_display_power.c.

>
> When is it okay to call this function and expect to get sane results?

display->power.dc3co_allow is only updated in intel_dc3co_allow_check() which is called from
intel_atomic_commit_tail().intel_dc3co_allowed() only intended to be called from intel_post_plane_update()
path(ALPM/PSR), which executes as part of intel_atomic_commit_tail().

>
>> +}
>> +
>> +static bool intel_dc3co_port_pipe_compatible(struct intel_dp *intel_dp,
>> +					     const struct intel_crtc_state *crtc_state)
>> +{
>> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
>> +	enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
>> +	enum port port = dig_port->base.port;
>> +	int num_pipes = intel_crtc_num_joined_pipes(crtc_state);
>> +
>> +	if (num_pipes != 1)
>> +		return false;
>> +
>> +	if (!(pipe <= PIPE_B && port <= PORT_B))
>> +		return false;
>> +
>> +	return true;
> That's a really complicated way to say
>
> 	return num_pipes == 1 && pipe <= PIPEB && port <= PORT_B;

I will update this.

>
>> +}
>> +
>> +static void intel_dc3co_allow_check(struct intel_atomic_state *state)
> What does "check" mean here? Or in *any* function?
>
> Check sounds like something that's a pure function that doesn't change
> anything... but this does.

I will split this function to two , one for check and one for initialization

>> +{
>> +	struct intel_display *display = to_intel_display(state);
>> +	struct intel_crtc *crtc;
>> +	struct intel_crtc_state *new_crtc_state;
>> +	struct intel_encoder *encoder;
>> +	struct intel_dp *intel_dp;
>> +	int i;
>> +	struct i915_power_domains *power_domains = &display->power.domains;
>> +	bool any_active = false;
>> +	bool allow = true;
>> +
>> +	display->power.dc3co_allow = 0;
> That's now cached state with no stated rules on when it's valid and when
> it's not.
>
>> +
>> +	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
>> +		return;
>> +
>> +	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
>> +		if (!new_crtc_state->hw.active)
>> +			continue;
>> +
>> +		any_active = true;
>> +
>> +		for_each_intel_encoder_mask(display->drm, encoder,
>> +					    new_crtc_state->uapi.encoder_mask) {
>> +			/* If any active pipe not eDP disable*/
> What?

I will correct comment /* Disallow DC3CO if any active pipe is not eDP */

>
>> +			if (!intel_encoder_is_dp(encoder) ||
>> +			    encoder->type != INTEL_OUTPUT_EDP) {
>> +				allow = false;
>> +				goto out;
>> +			}
>> +			intel_dp = enc_to_intel_dp(encoder);
>> +			/* Port, joiner, pipe placement checks */
> Is that a helpful comment?
>
>> +			if (!intel_dc3co_port_pipe_compatible(intel_dp, new_crtc_state)) {
>> +				allow = false;
>> +				goto out;
>> +			}
>> +		}
>> +	}
>> +
>> +	if (!any_active)
>> +		allow = false;
>> +
>> +out:
>> +	display->power.dc3co_allow = allow;
>> +}
>> +
> intel_display.[ch] is not the dumping ground for random new code. The
> goal is to *reduce* the size of it, not increase.

This function needs encoder,port and pipe information, which is why I added
it in intel_display.c.However,I agree it is updating dc3co_allow . I will check if
it can be moved to intel_display_power.c.

>
>>   static int intel_atomic_check_config(struct intel_atomic_state *state,
>>   				     struct intel_link_bw_limits *limits,
>>   				     enum pipe *failed_pipe)
>> @@ -6565,6 +6634,8 @@ int intel_atomic_check(struct drm_device *dev,
>>   	if (ret)
>>   		goto fail;
>>   
>> +	intel_dc3co_allow_check(state);
>> +
>>   	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>>   					    new_crtc_state, i) {
>>   		intel_color_assert_luts(new_crtc_state);
>> @@ -7601,6 +7672,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>>   		 */
>>   		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
>>   	}
>> +	if (intel_dc3co_allowed(display))
>> +		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC3CO);
>> +	else
>> +		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
>>   	/*
>>   	 * Delay re-enabling DC states by 17 ms to avoid the off->on->off
>>   	 * toggling overhead at and above 60 FPS.
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
>> index f8e6e4e82722..97987f082560 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display.h
>> @@ -560,5 +560,6 @@ bool assert_port_valid(struct intel_display *display, enum port port);
>>   
>>   bool intel_scanout_needs_vtd_wa(struct intel_display *display);
>>   int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
>> +bool intel_dc3co_allowed(struct intel_display *display);
>>   
>>   #endif
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
>> index d708d322aa85..fa567c95029c 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
>> @@ -538,6 +538,9 @@ struct intel_display {
>>   
>>   		/* perform PHY state sanity checks? */
>>   		bool chv_phy_assert[2];
>> +
>> +		/* mark dc3co entry is allowed*/
> 		                              ^- space missing
will add space.
>
>> +		bool dc3co_allow;
> Still unclear when this is valid.
>
>>   	} power;
>>   
>>   	struct {
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
>> index 0961b194554c..e99552f18756 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
>> @@ -956,7 +956,9 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
>>   	if (!HAS_DISPLAY(display))
>>   		return 0;
>>   
>> -	if (DISPLAY_VER(display) >= 20)
>> +	if (DISPLAY_VER(display) >= 35)
>> +		max_dc = 3;
>> +	else if (DISPLAY_VER(display) >= 20)
>>   		max_dc = 2;
>>   	else if (display->platform.dg2)
>>   		max_dc = 1;
>> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
>> index 753359069044..9c616f449ad6 100644
>> --- a/drivers/gpu/drm/i915/display/intel_psr.c
>> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
>> @@ -3903,14 +3903,11 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
>>   		return;
>>   	}
>>   
>> -	/*
>> -	 * NOTE: intel_display_power_set_target_dc_state is used
>> -	 * only by PSR * code for DC3CO handling. DC3CO target
>> -	 * state is currently disabled in * PSR code. If DC3CO
>> -	 * is taken into use we need take that into account here
>> -	 * as well.
>> -	 */
>> -	intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
>> +	if (intel_dc3co_allowed(display))
>> +		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
>> +						DC_STATE_EN_UPTO_DC3CO);
>> +	else
>> +		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
>>   						DC_STATE_EN_UPTO_DC6);
>>   }

[-- Attachment #2: Type: text/html, Size: 11895 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 7/9] drm/i915/display: psr enable DC3CO support
  2026-01-05 13:02   ` Jani Nikula
@ 2026-01-06 13:10     ` Dibin Moolakadan Subrahmanian
  0 siblings, 0 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2026-01-06 13:10 UTC (permalink / raw)
  To: Jani Nikula, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

[-- Attachment #1: Type: text/plain, Size: 1379 bytes --]

On 05-01-2026 18:32, Jani Nikula wrote:
> On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com> wrote:
>> if DC3CO allowed and psr2 is enabled, update dc3co_source
> Yeah, I can read the code, but what does it mean? Why?

I will add more details.
The intent is to record PSR2 as the source enabling DC3CO.
DC3CO can be entered when either PSR2 or LOBF is enabled, and
dc3co_source is used to track which feature triggered it.

>> Signed-off-by: Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com>
>> ---
>>   drivers/gpu/drm/i915/display/intel_psr.c | 6 ++++++
>>   1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
>> index 9c616f449ad6..d4c5dc6dcc82 100644
>> --- a/drivers/gpu/drm/i915/display/intel_psr.c
>> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
>> @@ -3007,6 +3007,12 @@ void intel_psr_post_plane_update(struct intel_atomic_state *state,
>>   		if (crtc_state->crc_enabled && psr->enabled)
>>   			intel_psr_force_update(intel_dp);
>>   
>> +		if (psr->enabled &&
>> +		    psr->sel_update_enabled &&
>> +		    intel_dc3co_allowed(display)) {
>> +			intel_dc3co_source_set(display, DC3CO_SOURCE_PSR2);
>> +		}
>> +
>>   		/*
>>   		 * Clear possible busy bits in case we have
>>   		 * invalidate -> flip -> flush sequence.

[-- Attachment #2: Type: text/html, Size: 2364 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2
  2026-01-05 13:01   ` Jani Nikula
@ 2026-01-06 13:28     ` Dibin Moolakadan Subrahmanian
  0 siblings, 0 replies; 28+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2026-01-06 13:28 UTC (permalink / raw)
  To: Jani Nikula, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

[-- Attachment #1: Type: text/plain, Size: 6570 bytes --]


On 05-01-2026 18:31, Jani Nikula wrote:
> On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com> wrote:
>> dc6 should be enabled instead of dc3co after  6 idle frames
>> while in psr2.(re enable part of tgl dc3co handling)
> Please write proper commit messages. I don't understand what this patch
> is supposed to do based on this.

I will add more details to commit message .
On TGL, original code disabled DC3CO after 6 consecutive idle frames and
re-enabled DC6. That logic was removed for the new DC3CO design. This patch
restores the behavior in PSR2, switching from DC3CO to DC6 after 6 idle
frames to maintain correct power management.

>
>> Signed-off-by: Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com>
>> ---
>>   .../drm/i915/display/intel_display_types.h    |  1 +
>>   drivers/gpu/drm/i915/display/intel_psr.c      | 78 ++++++++++++++++++-
>>   2 files changed, 78 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
>> index 27f69df7ee9c..6ff53cd58052 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
>> @@ -1759,6 +1759,7 @@ struct intel_psr {
>>   	bool panel_replay_enabled;
>>   	u32 dc3co_exitline;
>>   	u32 dc3co_exit_delay;
>> +	struct delayed_work dc3co_work;
>>   	u8 entry_setup_frames;
>>   
>>   	u8 io_wake_lines;
>> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
>> index 18bf45455ea2..4be709d1d324 100644
>> --- a/drivers/gpu/drm/i915/display/intel_psr.c
>> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
>> @@ -1157,6 +1157,78 @@ static void psr2_program_idle_frames(struct intel_dp *intel_dp,
>>   		     EDP_PSR2_IDLE_FRAMES(idle_frames));
>>   }
>>   
>> +static void psr2_dc3co_disable(struct intel_dp *intel_dp)
>> +{
>> +	struct intel_display *display = to_intel_display(intel_dp);
>> +	struct i915_power_domains *power_domains = &display->power.domains;
> There's currently one place in intel_psr.c that checks
> power_domains->allowed_dc_mask, and I think even that is too much.
>
> display->power belongs to intel_display_power*.c, and nobody else.
>
> I think you probably need a helper function to ask for this stuff from
> power modules.

Thanks for pointing this out.
I will add a helper function in intel_display_power.c to query this
instead of accessing display->power directly.

>> +
>> +	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
>> +		return;
>> +
>> +	intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
>> +	/* Todo restore PSR2 idle frames , ALPM control*/
> 	/* TODO: restore PSR2 idle frames, ALPM control */
>
>> +}
>> +
>> +static void psr2_dc3co_disable_on_exit(struct intel_dp *intel_dp)
>> +{
>> +	struct intel_display *display = to_intel_display(intel_dp);
>> +	struct i915_power_domains *power_domains = &display->power.domains;
>> +
>> +	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
>> +		return;
>> +
>> +	cancel_delayed_work(&intel_dp->psr.dc3co_work);
>> +	intel_dc3co_source_unset(display, DC3CO_SOURCE_PSR2);
>> +}
>> +
>> +static void psr2_dc3co_disable_work(struct work_struct *work)
>> +{
>> +	struct intel_dp *intel_dp =
>> +		container_of(work, typeof(*intel_dp), psr.dc3co_work.work);
>> +
>> +	mutex_lock(&intel_dp->psr.lock);
>> +	/* If delayed work is pending, it is not idle */
>> +	if (delayed_work_pending(&intel_dp->psr.dc3co_work))
>> +		goto unlock;
>> +	/* enable DC6 after idle frames*/
>> +	psr2_dc3co_disable(intel_dp);
>> +
>> +unlock:
>> +	mutex_unlock(&intel_dp->psr.lock);
>> +}
>> +
>> +/*
>> + * When we will be completely rely on PSR2 S/W tracking in future,
>> + * intel_psr_flush() will invalidate and flush the PSR for ORIGIN_FLIP
>> + * event also therefore psr2_dc3co_flush_locked() require to be changed
>> + * accordingly in future.
>> + */
>> +
>> +static void
>> +psr2_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
>> +			enum fb_op_origin origin)
>> +{
>> +	struct intel_display *display = to_intel_display(intel_dp);
>> +	struct i915_power_domains *power_domains = &display->power.domains;
>> +
>> +	if (!(power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO))
>> +		return;
>> +
>> +	if (!intel_dp->psr.sel_update_enabled ||
>> +	    !intel_dp->psr.active)
>> +		return;
>> +	/*
>> +	 * At every frontbuffer flush flip event modified delay of delayed work,
>> +	 * when delayed work schedules that means display has been idle.
>> +	 */
>> +	if (!(frontbuffer_bits &
>> +	    INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
>> +		return;
>> +
>> +	mod_delayed_work(display->wq.unordered, &intel_dp->psr.dc3co_work,
>> +			 intel_dp->psr.dc3co_exit_delay);
>> +}
>> +
>>   static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp,
>>   					      struct intel_crtc_state *crtc_state)
>>   {
>> @@ -2117,7 +2189,7 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
>>   		intel_de_rmw(display, TRANS_DP2_CTL(intel_dp->psr.transcoder),
>>   			     TRANS_DP2_PANEL_REPLAY_ENABLE, 0);
>>   	} else if (intel_dp->psr.sel_update_enabled) {
>> -
>> +		psr2_dc3co_disable_on_exit(intel_dp);
>>   		val = intel_de_rmw(display,
>>   				   EDP_PSR2_CTL(display, cpu_transcoder),
>>   				   EDP_PSR2_ENABLE, 0);
>> @@ -2259,6 +2331,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
>>   
>>   	mutex_unlock(&intel_dp->psr.lock);
>>   	cancel_work_sync(&intel_dp->psr.work);
>> +	cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
>>   }
>>   
>>   /**
>> @@ -2289,6 +2362,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
>>   	mutex_unlock(&psr->lock);
>>   
>>   	cancel_work_sync(&psr->work);
>> +	cancel_delayed_work_sync(&psr->dc3co_work);
>>   }
>>   
>>   /**
>> @@ -3475,6 +3549,7 @@ void intel_psr_flush(struct intel_display *display,
>>   		if (origin == ORIGIN_FLIP ||
>>   		    (origin == ORIGIN_CURSOR_UPDATE &&
>>   		     !intel_dp->psr.psr2_sel_fetch_enabled)) {
>> +			psr2_dc3co_flush_locked(intel_dp, frontbuffer_bits, origin);
>>   			goto unlock;
>>   		}
>>   
>> @@ -3533,6 +3608,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
>>   		intel_dp->psr.link_standby = connector->panel.vbt.psr.full_link;
>>   
>>   	INIT_WORK(&intel_dp->psr.work, intel_psr_work);
>> +	INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, psr2_dc3co_disable_work);
>>   	mutex_init(&intel_dp->psr.lock);
>>   }

[-- Attachment #2: Type: text/html, Size: 7765 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 4/9] drm/i915/display: Add DC3CO eligibility logic
  2026-01-06 12:58     ` Dibin Moolakadan Subrahmanian
@ 2026-01-07  9:14       ` Jani Nikula
  0 siblings, 0 replies; 28+ messages in thread
From: Jani Nikula @ 2026-01-07  9:14 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian, intel-gfx, intel-xe
  Cc: animesh.manna, uma.shankar, imre.deak, jouni.hogander

On Tue, 06 Jan 2026, Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com> wrote:
> On 05-01-2026 18:25, Jani Nikula wrote:
>> On Tue, 09 Dec 2025, Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com> wrote:
>>> Introduce dc3co_allow in struct intel_display and determine DC3CO
>>> eligibility during atomic_check(). DC3CO is permitted only when:
>>>
>>>    - the active pipe drives eDP,
>>>    - the pipe is single-pipe (no joiner),
>>>    - the pipe/port combination supports DC3CO.
>>>
>>> When eligible, intel_atomic_commit_tail() programs the target DC state
>>> as DC_STATE_EN_UPTO_DC3CO; otherwise we fall back to DC6. Update the
>>> PSR vblank enable/disable path to follow the same policy.
>>>
>>> Also extend get_allowed_dc_mask() to expose DC3CO support on
>>> DISPLAY_VER >= 35.
>>>
>>> Signed-off-by: Dibin Moolakadan Subrahmanian<dibin.moolakadan.subrahmanian@intel.com>
>>> ---
>>>   drivers/gpu/drm/i915/display/intel_display.c  | 75 +++++++++++++++++++
>>>   drivers/gpu/drm/i915/display/intel_display.h  |  1 +
>>>   .../gpu/drm/i915/display/intel_display_core.h |  3 +
>>>   .../drm/i915/display/intel_display_power.c    |  4 +-
>>>   drivers/gpu/drm/i915/display/intel_psr.c      | 13 ++--
>>>   5 files changed, 87 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>>> index 9c6d3ecdb589..205f55a87736 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>>> @@ -6295,6 +6295,75 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state)
>>>   	return 0;
>>>   }
>>>   
>>> +bool intel_dc3co_allowed(struct intel_display *display)
>>> +{
>>> +	return display->power.dc3co_allow;
>> Very few files should touch display->power, and this is not one of them.
>>
>> 'git grep "display->power" -- drivers/gpu/drm/i915/display'
>
> Yes, git grep shows few files , I will try to move all dc3co functions to
> drivers/gpu/drm/i915/display/intel_display_power.c.
>
>>
>> When is it okay to call this function and expect to get sane results?
>
> display->power.dc3co_allow is only updated in intel_dc3co_allow_check() which is called from
> intel_atomic_commit_tail().intel_dc3co_allowed() only intended to be called from intel_post_plane_update()
> path(ALPM/PSR), which executes as part of intel_atomic_commit_tail().

The point being, you have a complicated set of rules, and who's going to
know them and how when reading the code?

BR,
Jani.

>
>>
>>> +}
>>> +
>>> +static bool intel_dc3co_port_pipe_compatible(struct intel_dp *intel_dp,
>>> +					     const struct intel_crtc_state *crtc_state)
>>> +{
>>> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
>>> +	enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
>>> +	enum port port = dig_port->base.port;
>>> +	int num_pipes = intel_crtc_num_joined_pipes(crtc_state);
>>> +
>>> +	if (num_pipes != 1)
>>> +		return false;
>>> +
>>> +	if (!(pipe <= PIPE_B && port <= PORT_B))
>>> +		return false;
>>> +
>>> +	return true;
>> That's a really complicated way to say
>>
>> 	return num_pipes == 1 && pipe <= PIPEB && port <= PORT_B;
>
> I will update this.
>
>>
>>> +}
>>> +
>>> +static void intel_dc3co_allow_check(struct intel_atomic_state *state)
>> What does "check" mean here? Or in *any* function?
>>
>> Check sounds like something that's a pure function that doesn't change
>> anything... but this does.
>
> I will split this function to two , one for check and one for initialization
>
>>> +{
>>> +	struct intel_display *display = to_intel_display(state);
>>> +	struct intel_crtc *crtc;
>>> +	struct intel_crtc_state *new_crtc_state;
>>> +	struct intel_encoder *encoder;
>>> +	struct intel_dp *intel_dp;
>>> +	int i;
>>> +	struct i915_power_domains *power_domains = &display->power.domains;
>>> +	bool any_active = false;
>>> +	bool allow = true;
>>> +
>>> +	display->power.dc3co_allow = 0;
>> That's now cached state with no stated rules on when it's valid and when
>> it's not.
>>
>>> +
>>> +	if ((power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) != DC_STATE_EN_UPTO_DC3CO)
>>> +		return;
>>> +
>>> +	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
>>> +		if (!new_crtc_state->hw.active)
>>> +			continue;
>>> +
>>> +		any_active = true;
>>> +
>>> +		for_each_intel_encoder_mask(display->drm, encoder,
>>> +					    new_crtc_state->uapi.encoder_mask) {
>>> +			/* If any active pipe not eDP disable*/
>> What?
>
> I will correct comment /* Disallow DC3CO if any active pipe is not eDP */
>
>>
>>> +			if (!intel_encoder_is_dp(encoder) ||
>>> +			    encoder->type != INTEL_OUTPUT_EDP) {
>>> +				allow = false;
>>> +				goto out;
>>> +			}
>>> +			intel_dp = enc_to_intel_dp(encoder);
>>> +			/* Port, joiner, pipe placement checks */
>> Is that a helpful comment?
>>
>>> +			if (!intel_dc3co_port_pipe_compatible(intel_dp, new_crtc_state)) {
>>> +				allow = false;
>>> +				goto out;
>>> +			}
>>> +		}
>>> +	}
>>> +
>>> +	if (!any_active)
>>> +		allow = false;
>>> +
>>> +out:
>>> +	display->power.dc3co_allow = allow;
>>> +}
>>> +
>> intel_display.[ch] is not the dumping ground for random new code. The
>> goal is to *reduce* the size of it, not increase.
>
> This function needs encoder,port and pipe information, which is why I added
> it in intel_display.c.However,I agree it is updating dc3co_allow . I will check if
> it can be moved to intel_display_power.c.
>
>>
>>>   static int intel_atomic_check_config(struct intel_atomic_state *state,
>>>   				     struct intel_link_bw_limits *limits,
>>>   				     enum pipe *failed_pipe)
>>> @@ -6565,6 +6634,8 @@ int intel_atomic_check(struct drm_device *dev,
>>>   	if (ret)
>>>   		goto fail;
>>>   
>>> +	intel_dc3co_allow_check(state);
>>> +
>>>   	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>>>   					    new_crtc_state, i) {
>>>   		intel_color_assert_luts(new_crtc_state);
>>> @@ -7601,6 +7672,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>>>   		 */
>>>   		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
>>>   	}
>>> +	if (intel_dc3co_allowed(display))
>>> +		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC3CO);
>>> +	else
>>> +		intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
>>>   	/*
>>>   	 * Delay re-enabling DC states by 17 ms to avoid the off->on->off
>>>   	 * toggling overhead at and above 60 FPS.
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
>>> index f8e6e4e82722..97987f082560 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_display.h
>>> @@ -560,5 +560,6 @@ bool assert_port_valid(struct intel_display *display, enum port port);
>>>   
>>>   bool intel_scanout_needs_vtd_wa(struct intel_display *display);
>>>   int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
>>> +bool intel_dc3co_allowed(struct intel_display *display);
>>>   
>>>   #endif
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
>>> index d708d322aa85..fa567c95029c 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
>>> @@ -538,6 +538,9 @@ struct intel_display {
>>>   
>>>   		/* perform PHY state sanity checks? */
>>>   		bool chv_phy_assert[2];
>>> +
>>> +		/* mark dc3co entry is allowed*/
>> 		                              ^- space missing
> will add space.
>>
>>> +		bool dc3co_allow;
>> Still unclear when this is valid.
>>
>>>   	} power;
>>>   
>>>   	struct {
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
>>> index 0961b194554c..e99552f18756 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
>>> @@ -956,7 +956,9 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
>>>   	if (!HAS_DISPLAY(display))
>>>   		return 0;
>>>   
>>> -	if (DISPLAY_VER(display) >= 20)
>>> +	if (DISPLAY_VER(display) >= 35)
>>> +		max_dc = 3;
>>> +	else if (DISPLAY_VER(display) >= 20)
>>>   		max_dc = 2;
>>>   	else if (display->platform.dg2)
>>>   		max_dc = 1;
>>> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
>>> index 753359069044..9c616f449ad6 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_psr.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
>>> @@ -3903,14 +3903,11 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
>>>   		return;
>>>   	}
>>>   
>>> -	/*
>>> -	 * NOTE: intel_display_power_set_target_dc_state is used
>>> -	 * only by PSR * code for DC3CO handling. DC3CO target
>>> -	 * state is currently disabled in * PSR code. If DC3CO
>>> -	 * is taken into use we need take that into account here
>>> -	 * as well.
>>> -	 */
>>> -	intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
>>> +	if (intel_dc3co_allowed(display))
>>> +		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
>>> +						DC_STATE_EN_UPTO_DC3CO);
>>> +	else
>>> +		intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
>>>   						DC_STATE_EN_UPTO_DC6);
>>>   }

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2026-01-07  9:14 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-09 11:33 [RFC PATCH 0/9] drm/i915/display: DC3CO support Dibin Moolakadan Subrahmanian
2025-12-09 11:33 ` [PATCH 1/9] drm/i915/display: Remove TGL " Dibin Moolakadan Subrahmanian
2025-12-09 11:33 ` [PATCH 2/9] drm/i915/display: Replace DC_STATE_EN_DC3CO with DC_STATE_EN_UPTO_DC3CO Dibin Moolakadan Subrahmanian
2026-01-05 12:45   ` Jani Nikula
2026-01-06 10:40     ` Dibin Moolakadan Subrahmanian
2025-12-09 11:33 ` [PATCH 3/9] drm/i915/display: Add DC3CO enable/disable support Dibin Moolakadan Subrahmanian
2025-12-09 11:33 ` [PATCH 4/9] drm/i915/display: Add DC3CO eligibility logic Dibin Moolakadan Subrahmanian
2026-01-05 12:55   ` Jani Nikula
2026-01-06 12:58     ` Dibin Moolakadan Subrahmanian
2026-01-07  9:14       ` Jani Nikula
2025-12-09 11:33 ` [PATCH 5/9] drm/i915/display: Track DC3CO enable source Dibin Moolakadan Subrahmanian
2026-01-05 12:56   ` Jani Nikula
2025-12-09 11:33 ` [PATCH 6/9] drm/i915/display: alpm enable DC3CO support Dibin Moolakadan Subrahmanian
2025-12-12  7:37   ` Hogander, Jouni
2025-12-16  6:08     ` Dibin Moolakadan Subrahmanian
2025-12-09 11:33 ` [PATCH 7/9] drm/i915/display: psr " Dibin Moolakadan Subrahmanian
2026-01-05 13:02   ` Jani Nikula
2026-01-06 13:10     ` Dibin Moolakadan Subrahmanian
2025-12-09 11:33 ` [PATCH 8/9] drm/i915/display: Add intel_dc3co_can_enable() helper Dibin Moolakadan Subrahmanian
2026-01-05 12:56   ` Jani Nikula
2025-12-09 11:33 ` [PATCH 9/9] drm/i915/display: Add DC3CO disable handling for psr2 Dibin Moolakadan Subrahmanian
2025-12-12  7:11   ` Hogander, Jouni
2025-12-16  8:24     ` Dibin Moolakadan Subrahmanian
2025-12-16  8:30       ` Hogander, Jouni
2025-12-17  7:50         ` Dibin Moolakadan Subrahmanian
2026-01-05 13:01   ` Jani Nikula
2026-01-06 13:28     ` Dibin Moolakadan Subrahmanian
2025-12-09 14:36 ` ✗ i915.CI.BAT: failure for drm/i915/display: DC3CO support Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox