From: Jani Nikula <jani.nikula@linux.intel.com>
To: Dibin Moolakadan Subrahmanian
<dibin.moolakadan.subrahmanian@intel.com>,
intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org
Cc: animesh.manna@intel.com, uma.shankar@intel.com
Subject: Re: [PATCH v4 07/13] drm/i915/display: Add DC3CO eligibility computation
Date: Wed, 27 May 2026 15:24:08 +0300 [thread overview]
Message-ID: <2d54511166d5e97b5476dc0422d7f583a2543cf6@intel.com> (raw)
In-Reply-To: <20260526191826.3786009-8-dibin.moolakadan.subrahmanian@intel.com>
On Wed, 27 May 2026, Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com> wrote:
> Compute DC3CO eligibility during atomic_check based on
> pipe/port constraints and runtime triggers and store
> result in display->power.dc3co.
Atomic check should not change persistent state. It's almost always a
mistake. (I guess sometimes can't be avoided.)
> When DC3CO is allowed, request DC_STATE_EN_UPTO_DC3CO and
> reduce the DC entry delay. Otherwise, retain the existing
> delay and set default DC_STATE_EN_UPTO_DC6.
>
> Changes in v2:
> - Move dc3co state from intel_atomic_state to display->power (Uma Shankar)
> - Use #define bitmasks instead of enum for DC3CO triggers (Jani Nikula)
>
> Changes in v3:
> - Fix trigger always returning zero in intel_dc3co_compute_state().
>
> Changes in v4:
> - Call intel_display_power_set_target_dc_state() only when DC3CO is
> supported.
> - For Panel replay DC3CO trigger, add check for as_sdp_supported flag
> - Add 1:1 mapping check to intel_dc3co_port_pipe_compatible for
> display version 35.(Uma Shankar,Animesh Manna)
> - Add guard for intel_dc3co_compute_state()
>
> BSpec: 75253
> Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 102 +++++++++++++++++-
> .../gpu/drm/i915/display/intel_display_core.h | 3 +-
> .../drm/i915/display/intel_display_power.c | 30 ++++++
> .../drm/i915/display/intel_display_power.h | 22 ++++
> 4 files changed, 151 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 757a78c75bbf..375ffb329022 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -5874,6 +5874,74 @@ static bool intel_pipes_need_modeset(struct intel_atomic_state *state,
> return false;
> }
>
> +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);
> +
> + /* Need to follow 1:1 mapping because of CMTG restriction*/
> + if (DISPLAY_VER(to_intel_display(crtc_state)) == 35)
> + return num_pipes == 1 &&
> + ((pipe == PIPE_A && port == PORT_A) ||
> + (pipe == PIPE_B && port == PORT_B));
> + else
> + return num_pipes == 1 && pipe <= PIPE_B && port <= PORT_B;
> +}
> +
> +static void intel_dc3co_compute_state(struct intel_atomic_state *state)
> +{
> + struct intel_display *display = to_intel_display(state);
> + struct intel_crtc *crtc;
> + struct intel_crtc_state *crtc_state;
> + struct intel_encoder *encoder;
> + struct intel_dp *intel_dp;
> + u8 active_pipes = 0;
> + enum pipe pipe;
> + u32 trigger = DC3CO_TRIGGER_NONE;
> +
> + if (!HAS_DC3CO(display))
> + return;
> +
> + for_each_intel_crtc(display->drm, crtc)
> + active_pipes |= crtc->active ? BIT(crtc->pipe) : 0;
> +
> + active_pipes = intel_calc_active_pipes(state, active_pipes);
> +
> + if (hweight8(active_pipes) != 1)
> + goto done;
> +
> + pipe = ffs(active_pipes) - 1;
> + crtc = intel_crtc_for_pipe(display, pipe);
> +
> + crtc_state = to_intel_crtc_state(crtc->base.state);
> +
> + for_each_intel_encoder_mask(display->drm, encoder,
> + crtc_state->uapi.encoder_mask) {
> + if (encoder->type != INTEL_OUTPUT_EDP)
> + goto done;
> +
> + intel_dp = enc_to_intel_dp(encoder);
> +
> + if (!intel_dc3co_port_pipe_compatible(intel_dp, crtc_state))
> + goto done;
> + }
> +
> + if (crtc_state->has_lobf)
> + trigger |= DC3CO_TRIGGER_LOBF;
> + if (crtc_state->has_panel_replay && intel_dp->as_sdp_supported)
> + trigger |= DC3CO_TRIGGER_PANEL_REPLAY;
> + if (crtc_state->has_sel_update)
> + trigger |= DC3CO_TRIGGER_PSR2;
> +
> +done:
> + intel_display_power_dc3co_update(display, !!trigger, trigger);
Are two parameters necessary?
> + drm_dbg_kms(display->drm, "DC3CO allowed=%d trigger=0x%x\n",
> + !!trigger, trigger);
> +}
None of the above stuff belongs in intel_display.c. The file's too big
as it is. Probably intel_display_power.c.
> +
> static int intel_atomic_check_joiner(struct intel_atomic_state *state,
> struct intel_crtc *primary_crtc)
> {
> @@ -6570,6 +6638,9 @@ int intel_atomic_check(struct drm_device *dev,
> "modeset" : "fastset");
> }
>
> + if (intel_display_power_dc3co_supported(display))
> + intel_dc3co_compute_state(state);
> +
Smells like intel_display_power_atomic_check(), maybe, without the if
statement here.
> return 0;
>
> fail:
> @@ -7421,6 +7492,12 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
> struct intel_power_domain_mask put_domains[I915_MAX_PIPES] = {};
> struct ref_tracker *wakeref = NULL;
> int i;
> + u32 target_dc_state;
> + /*
> + * Delay re-enabling DC states by 17 ms to avoid the off->on->off
> + * toggling overhead at and above 60 FPS.
> + */
> + int power_async_delay = 17;
>
> for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
> intel_atomic_dsb_prepare(state, crtc);
> @@ -7627,11 +7704,26 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
> */
> intel_uncore_arm_unclaimed_mmio_detection(uncore);
> }
> - /*
> - * Delay re-enabling DC states by 17 ms to avoid the off->on->off
> - * toggling overhead at and above 60 FPS.
> - */
> - intel_display_power_put_async_delay(display, POWER_DOMAIN_DC_OFF, wakeref, 17);
> +
> + if (intel_display_power_dc3co_supported(display)) {
> + if (intel_display_power_dc3co_allowed(display)) {
> + /*
> + * Use minimal re-enable delay to allow DC3CO entry on
> + * the next idle frame, unlike the 17ms guard needed to
> + * prevent DC5/DC6 toggling overhead at 60+ FPS.
> + */
> + power_async_delay = 1;
> + target_dc_state = DC_STATE_EN_UPTO_DC3CO;
> + } else {
> + target_dc_state = DC_STATE_EN_UPTO_DC6;
> + }
> +
> + intel_display_power_set_target_dc_state(display, target_dc_state);
> + }
> +
This is also way too detailed for intel_atomic_commit_tail(). This is
the highest level of modeset functions. See the code around here,
there's nothing as detailed.
> + intel_display_power_put_async_delay(display,
> + POWER_DOMAIN_DC_OFF, wakeref, power_async_delay);
Maybe need to consider intel_display_power_put_commit_tail() or
something along those lines to hide all of the delay stuff there.
> +
> intel_display_rpm_put(display, state->wakeref);
>
> /*
> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
> index 3dc5ac75a98b..e24accf473d7 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> @@ -537,7 +537,8 @@ struct intel_display {
>
> struct {
> struct i915_power_domains domains;
> -
> + /* DC3CO eligibility state */
> + struct intel_dc3co_state dc3co;
> /* Shadow for DISPLAY_PHY_CONTROL which can't be safely read */
> u32 chv_phy_control;
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index 4b91747b38f1..b0f40e4233c8 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -366,6 +366,35 @@ bool intel_display_power_dc3co_supported(struct intel_display *display)
> return (power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC3CO) == DC_STATE_EN_UPTO_DC3CO;
> }
>
> +void intel_display_power_dc3co_update(struct intel_display *display,
> + bool allowed, u32 trigger)
> +{
> + struct intel_dc3co_state *dc3co = &display->power.dc3co;
> +
> + if (!HAS_DC3CO(display))
> + return;
> +
> + mutex_lock(&dc3co->lock);
> + dc3co->allowed = allowed;
Can this always be derived from dc3co->trigger?
> + dc3co->trigger = trigger;
> + mutex_unlock(&dc3co->lock);
> +}
> +
> +bool intel_display_power_dc3co_allowed(struct intel_display *display)
> +{
> + struct intel_dc3co_state *dc3co = &display->power.dc3co;
> + bool allowed;
> +
> + if (!HAS_DC3CO(display))
> + return false;
> +
> + mutex_lock(&dc3co->lock);
> + allowed = dc3co->allowed;
> + mutex_unlock(&dc3co->lock);
> +
> + return allowed;
> +}
> +
> static void __async_put_domains_mask(struct i915_power_domains *power_domains,
> struct intel_power_domain_mask *mask)
> {
> @@ -1045,6 +1074,7 @@ int intel_power_domains_init(struct intel_display *display)
> sanitize_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
>
> mutex_init(&power_domains->lock);
> + mutex_init(&display->power.dc3co.lock);
>
> INIT_DELAYED_WORK(&power_domains->async_put_work,
> intel_display_power_put_async_work);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
> index 05880e9da89f..0b1a06f88ae5 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.h
> @@ -131,6 +131,25 @@ struct intel_power_domain_mask {
> DECLARE_BITMAP(bits, POWER_DOMAIN_NUM);
> };
>
> +/*
> + * DC3CO enabling triggers (bitmask).
> + * DC3CO may be enabled when at least one of these triggers is active.
> + * Additional constraints may still apply.
> + */
> +#define DC3CO_TRIGGER_NONE (0)
> +#define DC3CO_TRIGGER_PSR2 BIT(0)
> +#define DC3CO_TRIGGER_LOBF BIT(1)
> +#define DC3CO_TRIGGER_PANEL_REPLAY BIT(2)
> +#define DC3CO_TRIGGER_ALL (DC3CO_TRIGGER_PSR2 | \
> + DC3CO_TRIGGER_LOBF | \
> + DC3CO_TRIGGER_PANEL_REPLAY)
> +
> +struct intel_dc3co_state {
> + struct mutex lock; /* Protects allowed and trigger fields */
> + bool allowed; /* DC3CO eligibility result */
> + u32 trigger; /* Bitmask of active DC3CO triggers */
> +};
> +
> struct i915_power_domains {
> /*
> * Power wells needed for initialization at driver init and suspend
> @@ -187,6 +206,9 @@ void intel_display_power_set_target_dc_state(struct intel_display *display,
> u32 state);
> u32 intel_display_power_get_current_dc_state(struct intel_display *display);
> bool intel_display_power_dc3co_supported(struct intel_display *display);
> +void intel_display_power_dc3co_update(struct intel_display *display,
> + bool allowed, u32 trigger);
> +bool intel_display_power_dc3co_allowed(struct intel_display *display);
>
> bool intel_display_power_is_enabled(struct intel_display *display,
> enum intel_display_power_domain domain);
--
Jani Nikula, Intel
next prev parent reply other threads:[~2026-05-27 12:24 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-26 19:18 [PATCH v4 00/13] drm/i915/display: Add DC3CO support Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 01/13] drm/i915/display: Remove TGL " Dibin Moolakadan Subrahmanian
2026-05-27 9:30 ` Manna, Animesh
2026-05-26 19:18 ` [PATCH v4 02/13] drm/i915/display: Switch DC3CO enable from standalone bit to DC level encoding Dibin Moolakadan Subrahmanian
2026-06-01 5:25 ` Manna, Animesh
2026-06-01 12:18 ` Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 03/13] drm/i915/display: Use FIELD_PREP() for DC state enable bits Dibin Moolakadan Subrahmanian
2026-06-01 5:30 ` Manna, Animesh
2026-06-01 12:22 ` Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 04/13] drm/i915/display: Add DC3CO DC_STATE enable/disable support Dibin Moolakadan Subrahmanian
2026-06-01 5:42 ` Manna, Animesh
2026-06-01 12:30 ` Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 05/13] drm/i915/display: Add DC3CO support check Dibin Moolakadan Subrahmanian
2026-05-27 12:26 ` Jani Nikula
2026-05-28 9:18 ` Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 06/13] drm/i915/display: Add HAS_DC3CO() macro Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 07/13] drm/i915/display: Add DC3CO eligibility computation Dibin Moolakadan Subrahmanian
2026-05-27 12:24 ` Jani Nikula [this message]
2026-05-28 11:29 ` Dibin Moolakadan Subrahmanian
2026-05-27 12:28 ` Jani Nikula
2026-05-28 9:46 ` Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 08/13] drm/i915/display: Store DC3CO eligibility in PSR state Dibin Moolakadan Subrahmanian
2026-05-27 12:30 ` Jani Nikula
2026-05-28 11:37 ` Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 09/13] drm/i915/display: PSR2: Set idle_frames to 0 for DC3CO Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 10/13] drm/i915/display: Enable DC3CO idle protocol in ALPM Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 11/13] drm/i915/display: PSR Add delayed work to exit DC3CO Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 12/13] drm/i915/display: Add helper to enable DC counter Dibin Moolakadan Subrahmanian
2026-06-01 5:47 ` Manna, Animesh
2026-06-01 12:35 ` Dibin Moolakadan Subrahmanian
2026-05-26 19:18 ` [PATCH v4 13/13] drm/i915/display: Add DC3CO count and residency in dmc debugfs Dibin Moolakadan Subrahmanian
2026-06-01 5:50 ` Manna, Animesh
2026-06-01 12:38 ` Dibin Moolakadan Subrahmanian
2026-05-26 20:14 ` ✓ CI.KUnit: success for drm/i915/display: Add DC3CO support (rev4) Patchwork
2026-05-26 20:14 ` ✓ i915.CI.BAT: " Patchwork
2026-05-26 20:52 ` ✓ Xe.CI.BAT: " Patchwork
2026-05-27 1:20 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-05-27 4:27 ` ✗ i915.CI.Full: " Patchwork
2026-05-27 10:16 ` ✓ i915.CI.Full: success " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2d54511166d5e97b5476dc0422d7f583a2543cf6@intel.com \
--to=jani.nikula@linux.intel.com \
--cc=animesh.manna@intel.com \
--cc=dibin.moolakadan.subrahmanian@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=uma.shankar@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.