Merge pull request #131 from spencerbull/update-linux-ptl-7.1.8

Update linux-ptl to 7.1.8
This commit is contained in:
David Heinemeier Hansson
2026-08-12 08:47:41 +02:00
committed by GitHub
8 changed files with 260 additions and 267 deletions
@@ -1,37 +0,0 @@
From 849489b94fe35172a4fea6e09acabacd273d8993 Mon Sep 17 00:00:00 2001
From: TsaiGaggery <gaggery.tsai@intel.com>
Date: Wed, 11 Mar 2026 14:21:39 -0700
Subject: [PATCH 17/17] ASoC: SDCA: Fix NULL pointer dereference in
sdca_jack_process()
Add NULL guard for card and card->snd_card before dereferencing.
During card teardown, component->card can be NULL when an IRQ fires.
---
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
index 49d317d..b52d88a 100644
--- a/sound/soc/sdca/sdca_jack.c
+++ b/sound/soc/sdca/sdca_jack.c
@@ -37,13 +37,21 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
struct device *dev = interrupt->dev;
struct snd_soc_component *component = interrupt->component;
struct snd_soc_card *card = component->card;
- struct rw_semaphore *rwsem = &card->snd_card->controls_rwsem;
+ struct rw_semaphore *rwsem;
struct jack_state *state = interrupt->priv;
- struct snd_kcontrol *kctl = state->kctl;
+ struct snd_kcontrol *kctl;
struct snd_ctl_elem_value *ucontrol __free(kfree) = NULL;
unsigned int reg, val;
int ret;
+ if (!card || !card->snd_card) {
+ dev_dbg(dev, "card not yet bound, deferring jack event\n");
+ return -ENODEV;
+ }
+
+ rwsem = &card->snd_card->controls_rwsem;
+ kctl = state->kctl;
+
guard(rwsem_write)(rwsem);
if (!kctl) {
@@ -1,20 +0,0 @@
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 8a7075c..197c238 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -701,8 +701,14 @@ static void _psr_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *co
* To support PSR version 02h and PSR version 03h without
* Y-coordinate requirement panels we would need to enable
* GTC first.
+ *
+ * Early Transport (version 04h) implies Y-coordinate
+ * support. Accept it without explicit Y-coordinate
+ * requirement bit.
*/
- connector->dp.psr_caps.su_support = y_req &&
+ connector->dp.psr_caps.su_support =
+ (y_req || connector->dp.psr_caps.dpcd[0] ==
+ DP_PSR2_WITH_Y_COORD_ET_SUPPORTED) &&
intel_alpm_aux_wake_supported(intel_dp);
drm_dbg_kms(display->drm, "PSR2 %ssupported\n",
connector->dp.psr_caps.su_support ? "" : "not ");
@@ -1,21 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From 44ed249f891712621c10e0deaf412ae98cc34b16 Mon Sep 17 00:00:00 2001
From: Gaggery Tsai <gaggery.tsai@intel.com>
Date: Tue, 28 Apr 2026 15:00:00 -0500
Subject: [PATCH] drm/i915/alpm: limit Panel Replay ALPM programming to PR
Subject: [PATCH] drm/i915/alpm: limit PR ALPM programming to Panel Replay
Linux 7 already carries the Panel Replay/PSR selective-update
granularity fixes from the old linux-ptl 0020 patch. Keep only the
remaining ALPM fix: avoid programming PR-specific ALPM controls when
Panel Replay is not active, and use the common helper for aux-less ALPM
selection.
PR_ALPM_CTL controls Panel Replay behavior, but the current path also
programs it whenever Adaptive Sync SDP is supported while Panel Replay
is inactive. Limit that register programming to actual Panel Replay
configurations.
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
---
drivers/gpu/drm/i915/display/intel_alpm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
index f4f1b68..a115b53 100644
index a7350ce..86f98ca 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -317,7 +317,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
@@ -381,7 +381,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS |
ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines);
@@ -24,14 +26,5 @@ index f4f1b68..a115b53 100644
u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
if (crtc_state->link_off_after_as_sdp_when_pr_active)
@@ -430,8 +430,8 @@ void intel_alpm_enable_sink(struct intel_dp *intel_dp,
val = DP_ALPM_ENABLE | DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE;
- if (crtc_state->has_panel_replay || (crtc_state->has_lobf &&
- intel_alpm_aux_less_wake_supported(intel_dp)))
+ if (intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) ||
+ (crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp)))
val |= DP_ALPM_MODE_AUX_LESS;
drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val);
--
2.55.0
@@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Gaggery Tsai <gaggery.tsai@intel.com>
Date: Tue, 28 Apr 2026 16:10:00 -0500
Subject: [PATCH] drm/i915: limit TRANS_PUSH frame changes to Panel Replay
Linux 7.1 carries the TRANS_PUSH frame-change infrastructure that
linux-ptl previously backported. Keep only the remaining linux-ptl
policy delta: use TRANS_PUSH for Panel Replay, but not for plain PSR2.
Plain PSR2 must keep using the old CURSURFLIVE frame-change path so
systems still boot when Panel Replay is disabled with
xe.enable_panel_replay=0.
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
---
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2171,7 +2171,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
intel_alpm_configure(intel_dp, crtc_state);
- if (HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display))
+ if (intel_psr_use_trans_push(crtc_state))
intel_vrr_psr_frame_change_enable(crtc_state);
}
@@ -4658,5 +4658,5 @@ bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
- return HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display) && crtc_state->has_psr;
+ return HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display) && crtc_state->has_panel_replay;
}
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -703,7 +703,7 @@ static u32 trans_vrr_push(const struct intel_crtc_state *crtc_state,
if (send_push)
trans_vrr_push |= TRANS_PUSH_SEND;
- if (HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display))
+ if (intel_psr_use_trans_push(crtc_state))
trans_vrr_push |= LNL_TRANS_PUSH_PSR_PR_EN;
return trans_vrr_push;
@@ -1,118 +1,219 @@
From 9126525701cdf19e6c3d2caf8a6ece559f99a99e Mon Sep 17 00:00:00 2001
From: Gaggery Tsai <gaggery.tsai@intel.com>
Date: Thu, 17 Apr 2026 10:30:00 -0700
Subject: [PATCH] drm/i915/psr: exit Panel Replay during updates to work around ALPM lag
Date: Mon, 10 Aug 2026 22:45:00 -0500
Subject: [PATCH] drm/i915/psr: restore DA14260 Panel Replay with ALPM lag
workaround
Panel Replay ALPM AUX-Less wake/sleep cycling cannot resume selective
updates at frame rate on the LGD OLED panel in the Dell XPS 14
DA14260. The panel's internal timing engine appears to need a
per-frame timing beacon to resume quickly after ALPM sleep; without
it, the source commits at 120 Hz but visible frames land around
15 Hz.
Panel Replay ALPM AUX-less wake/sleep cycling cannot resume selective
updates at frame rate on the LGD OLED panel in the Dell XPS 14 DA14260.
Upstream avoids the visible lag by disabling Panel Replay for the exact
Dell 1028:0db9 and LGD 00:22:b9 match, which also removes the idle power
savings.
Work around by temporarily exiting Panel Replay in
frontbuffer_flush() before each frame update. Re-entry into PR (with
ALPM) is deferred by 50 ms via dc3co_work so that during continuous
motion the link stays on (cursor/video smooth), and PR re-engages
after 50 ms of no further updates (idle power savings preserved).
Replace only that exact disable entry with a hardware-scoped workaround.
Exit Panel Replay for relevant frontbuffer activity and re-enter it after
50 ms of idle time. Use a dedicated delayed work item integrated under
the existing PSR mutex and frontbuffer busy-bit tracking; block normal
immediate re-entry while it is armed, wait for sink idle, and cancel it
on invalidate, pause, and disable.
The delay was chosen empirically:
| Delay | Idle (10x avg) | Cursor motion (3x avg) |
|--------|----------------|------------------------|
| 50 ms | 3268 mW | 8749 mW |
| 100 ms | 3436 mW | 9088 mW |
| 200 ms | 3484 mW | 9104 mW |
| stock | 3384 mW | ~15 Hz visible lag |
| PSR2 | 4060 mW | 9191 mW |
50 ms gives the best idle and cursor-motion power while remaining
subjectively identical in smoothness to longer delays.
Repurpose the existing dc3co_work delayed_work as the re-entry timer:
each frontbuffer_flush cancels+rearms it to 50 ms, and the work
handler calls intel_psr_activate() when it fires.
Other panels retain upstream behavior.
Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7521
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
---
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
index 03c4978..0743142 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -97,6 +97,7 @@ static void frontbuffer_flush(struct intel_display *display,
might_sleep();
intel_td_flush(display);
intel_drrs_flush(display, frontbuffer_bits);
+ intel_psr_panel_replay_exit(display);
intel_psr_flush(display, frontbuffer_bits, origin);
intel_fbc_flush(display, frontbuffer_bits, origin);
}
.../drm/i915/display/intel_display_types.h | 1 +
drivers/gpu/drm/i915/display/intel_psr.c | 65 ++++++++++++++++++-
drivers/gpu/drm/i915/display/intel_quirks.c | 9 +--
drivers/gpu/drm/i915/display/intel_quirks.h | 1 +
4 files changed, 71 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 2e6a857..51ae4ed 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1779,6 +1779,7 @@ struct intel_psr {
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
+ struct delayed_work panel_replay_reenable_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 cbf8cd4..9d69056 100644
index 598fe76..0ca20f5 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1200,6 +1200,8 @@ static void tgl_psr2_disable_dc3co(struct intel_dp *intel_dp)
psr2_program_idle_frames(intel_dp, psr_compute_idle_frames(intel_dp));
@@ -2445,6 +2445,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);
+ cancel_delayed_work_sync(&intel_dp->psr.panel_replay_reenable_work);
}
+static void intel_psr_activate(struct intel_dp *intel_dp);
/**
@@ -2476,6 +2477,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
cancel_work_sync(&psr->work);
cancel_delayed_work_sync(&psr->dc3co_work);
+ cancel_delayed_work_sync(&psr->panel_replay_reenable_work);
}
/**
@@ -3504,6 +3506,17 @@ static void intel_psr_handle_irq(struct intel_dp *intel_dp)
drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
}
+#define PANEL_REPLAY_REENABLE_DELAY_MS 50
+
static void tgl_dc3co_disable_work(struct work_struct *work)
+static bool panel_replay_alpm_cursor_lag_workaround_enabled(struct intel_dp *intel_dp)
+{
+ return intel_dp_is_edp(intel_dp) &&
+ intel_dp->psr.panel_replay_enabled &&
+ intel_dp->psr.sel_update_enabled &&
+ intel_has_dpcd_quirk(intel_dp,
+ QUIRK_PANEL_REPLAY_ALPM_CURSOR_LAG);
+}
+
static void intel_psr_work(struct work_struct *work)
{
struct intel_dp *intel_dp =
@@ -1210,6 +1212,13 @@ static void tgl_dc3co_disable_work(struct work_struct *work)
if (delayed_work_pending(&intel_dp->psr.dc3co_work))
@@ -3522,6 +3535,11 @@ static void intel_psr_work(struct work_struct *work)
if (intel_dp->psr.pause_counter)
goto unlock;
+ /* Panel Replay ALPM cursor-lag workaround re-activation path. */
+ if (intel_dp->psr.panel_replay_enabled &&
+ intel_dp->psr.enabled && !intel_dp->psr.active) {
+ intel_psr_activate(intel_dp);
+ /* The dedicated delayed work owns re-entry while the workaround is armed. */
+ if (panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp) &&
+ delayed_work_pending(&intel_dp->psr.panel_replay_reenable_work))
+ goto unlock;
+ }
+
tgl_psr2_disable_dc3co(intel_dp);
unlock:
mutex_unlock(&intel_dp->psr.lock);
@@ -4626,3 +4635,30 @@ bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state)
/*
* We have to make sure PSR is ready for re-enable
* otherwise it keeps disabled until next full enable/disable cycle.
@@ -3531,6 +3549,10 @@ static void intel_psr_work(struct work_struct *work)
if (!__psr_wait_for_idle_locked(intel_dp))
goto unlock;
return HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display) && crtc_state->has_panel_replay;
+ if (panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp) &&
+ delayed_work_pending(&intel_dp->psr.panel_replay_reenable_work))
+ goto unlock;
+
/*
* The delayed work can race with an invalidate hence we need to
* recheck. Since psr_flush first clears this and then reschedules we
@@ -3544,6 +3566,33 @@ static void intel_psr_work(struct work_struct *work)
mutex_unlock(&intel_dp->psr.lock);
}
+
+/*
+ * intel_psr_panel_replay_exit - exit Panel Replay during frontbuffer activity
+ *
+ * Exits PR on frontbuffer flush and arms dc3co_work with a 50 ms
+ * delay. Each subsequent flush cancels and rearms the timer. When it
+ * finally fires, tgl_dc3co_disable_work re-activates PR.
+ */
+void intel_psr_panel_replay_exit(struct intel_display *display)
+static void panel_replay_reenable_work(struct work_struct *work)
+{
+ struct intel_encoder *encoder;
+ struct intel_dp *intel_dp =
+ container_of(work, typeof(*intel_dp),
+ psr.panel_replay_reenable_work.work);
+
+ for_each_intel_encoder_with_psr(display->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ mutex_lock(&intel_dp->psr.lock);
+
+ mutex_lock(&intel_dp->psr.lock);
+ if (intel_dp->psr.panel_replay_enabled &&
+ intel_dp->psr.sel_update_enabled) {
+ if (intel_dp->psr.active)
+ intel_psr_exit(intel_dp);
+ mod_delayed_work(display->wq.unordered,
+ &intel_dp->psr.dc3co_work,
+ msecs_to_jiffies(50));
+ }
+ mutex_unlock(&intel_dp->psr.lock);
+ }
+ if (!intel_dp->psr.enabled ||
+ !panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp) ||
+ intel_dp->psr.pause_counter ||
+ READ_ONCE(intel_dp->psr.irq_aux_error))
+ goto unlock;
+
+ if (!__psr_wait_for_idle_locked(intel_dp))
+ goto unlock;
+
+ /* Recheck for activity or a newer deadline after the unlocked wait. */
+ if (delayed_work_pending(&intel_dp->psr.panel_replay_reenable_work) ||
+ intel_dp->psr.busy_frontbuffer_bits || intel_dp->psr.active)
+ goto unlock;
+
+ intel_psr_activate(intel_dp);
+unlock:
+ mutex_unlock(&intel_dp->psr.lock);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h
index 394b641..485d880 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.h
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
@@ -40,6 +40,7 @@ int intel_psr_debug_set(struct intel_dp *intel_dp, u64 value);
void intel_psr_invalidate(struct intel_display *display,
unsigned frontbuffer_bits,
enum fb_op_origin origin);
+void intel_psr_panel_replay_exit(struct intel_display *display);
void intel_psr_flush(struct intel_display *display,
unsigned frontbuffer_bits,
enum fb_op_origin origin);
+
static void intel_psr_configure_full_frame_update(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
@@ -3615,8 +3664,11 @@ void intel_psr_invalidate(struct intel_display *display,
INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe);
intel_dp->psr.busy_frontbuffer_bits |= pipe_frontbuffer_bits;
- if (pipe_frontbuffer_bits)
+ if (pipe_frontbuffer_bits) {
+ if (panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp))
+ cancel_delayed_work(&intel_dp->psr.panel_replay_reenable_work);
_psr_invalidate_handle(intel_dp);
+ }
mutex_unlock(&intel_dp->psr.lock);
}
@@ -3732,6 +3784,15 @@ void intel_psr_flush(struct intel_display *display,
if (intel_dp->psr.pause_counter)
goto unlock;
+ if (pipe_frontbuffer_bits &&
+ panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp)) {
+ intel_psr_exit(intel_dp);
+ mod_delayed_work(display->wq.unordered,
+ &intel_dp->psr.panel_replay_reenable_work,
+ msecs_to_jiffies(PANEL_REPLAY_REENABLE_DELAY_MS));
+ goto unlock;
+ }
+
if (origin == ORIGIN_FLIP ||
(origin == ORIGIN_CURSOR_UPDATE &&
!intel_dp->psr.psr2_sel_fetch_enabled)) {
@@ -3795,6 +3856,8 @@ void intel_psr_init(struct intel_dp *intel_dp)
INIT_WORK(&intel_dp->psr.work, intel_psr_work);
INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, tgl_dc3co_disable_work);
+ INIT_DELAYED_WORK(&intel_dp->psr.panel_replay_reenable_work,
+ panel_replay_reenable_work);
mutex_init(&intel_dp->psr.lock);
}
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
index 883f297..7c772a9 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
@@ -86,12 +86,13 @@ static void quirk_edp_limit_rate_hbr2(struct intel_display *display)
drm_info(display->drm, "Applying eDP Limit rate to HBR2 quirk\n");
}
-static void quirk_disable_edp_panel_replay(struct intel_dp *intel_dp)
+static void quirk_panel_replay_alpm_cursor_lag(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- intel_set_dpcd_quirk(intel_dp, QUIRK_DISABLE_EDP_PANEL_REPLAY);
- drm_info(display->drm, "Applying disable Panel Replay quirk\n");
+ intel_set_dpcd_quirk(intel_dp, QUIRK_PANEL_REPLAY_ALPM_CURSOR_LAG);
+ drm_info(display->drm,
+ "Applying Panel Replay ALPM cursor lag workaround\n");
}
struct intel_quirk {
@@ -267,7 +268,7 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
.subsystem_vendor = 0x1028,
.subsystem_device = 0x0db9,
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
- .hook = quirk_disable_edp_panel_replay,
+ .hook = quirk_panel_replay_alpm_cursor_lag,
},
};
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h
index 83214eb..8b083c6 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.h
+++ b/drivers/gpu/drm/i915/display/intel_quirks.h
@@ -22,6 +22,7 @@ enum intel_quirk_id {
QUIRK_FW_SYNC_LEN,
QUIRK_EDP_LIMIT_RATE_HBR2,
QUIRK_DISABLE_EDP_PANEL_REPLAY,
+ QUIRK_PANEL_REPLAY_ALPM_CURSOR_LAG,
};
void intel_init_quirks(struct intel_display *display);
--
2.55.0
@@ -1,22 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From 59070ec95c365d76081fa339a95f2b7bda94fd03 Mon Sep 17 00:00:00 2001
From: Spencer Bull <spencer.bull@dell.com>
Date: Mon, 30 Mar 2026 23:30:00 +0000
Subject: [PATCH] drm/edid: populate monitor range from DisplayID adaptive sync
Some eDP OLED panels advertise a VRR range only via the DisplayID 2.x
Adaptive Sync data block. In that case `display_info.monitor_range`
stays at 0/0 because DRM currently only fills it from the legacy EDID
monitor range descriptor.
Adaptive Sync data block. In that case display_info.monitor_range stays
at 0/0 because DRM currently only fills it from the legacy EDID monitor
range descriptor.
Intel's VRR capability path consumes `display_info.monitor_range`
directly, so the connector ends up with `vrr_capable=0` despite EDID
advertising Adaptive Sync.
Intel's VRR capability path consumes display_info.monitor_range directly,
so the connector ends up with vrr_capable=0 despite EDID advertising
Adaptive Sync.
Backfill `monitor_range` from the DisplayID 2.x Adaptive Sync data
block when the legacy descriptor did not provide a range.
Backfill monitor_range from the DisplayID 2.x Adaptive Sync data block
when the legacy descriptor did not provide a range.
---
drivers/gpu/drm/drm_displayid_internal.h | 1 +
drivers/gpu/drm/drm_edid.c | 86 ++++++++++++++++++++----
2 files changed, 74 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h
index 5b1b32f..b9b5320 100644
index 4590d6a..dbdc205 100644
--- a/drivers/gpu/drm/drm_displayid_internal.h
+++ b/drivers/gpu/drm/drm_displayid_internal.h
@@ -67,6 +67,7 @@ struct drm_edid;
@@ -28,16 +32,16 @@ index 5b1b32f..b9b5320 100644
#define DATA_BLOCK_2_CTA_DISPLAY_ID 0x81
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ff432ac..f83e445 100644
index df3c25b..354d4ff 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6527,6 +6527,46 @@ static void drm_get_monitor_range(struct drm_connector *connector,
@@ -6598,6 +6598,49 @@ static void drm_get_monitor_range(struct drm_connector *connector,
info->monitor_range.min_vfreq, info->monitor_range.max_vfreq);
}
+#define DISPLAYID_ADAPTIVE_SYNC_DESC_SIZE 6
+
+static void drm_update_displayid_adaptive_sync_range(struct drm_connector *connector,
+static bool drm_update_displayid_adaptive_sync_range(struct drm_connector *connector,
+ const struct displayid_block *block)
+{
+ struct drm_monitor_range_info *range = &connector->display_info.monitor_range;
@@ -48,7 +52,7 @@ index ff432ac..f83e445 100644
+
+ if (block->rev != 0 || block->num_bytes < DISPLAYID_ADAPTIVE_SYNC_DESC_SIZE ||
+ block->num_bytes % DISPLAYID_ADAPTIVE_SYNC_DESC_SIZE)
+ return;
+ return false;
+
+ for (i = 0; i < block->num_bytes; i += DISPLAYID_ADAPTIVE_SYNC_DESC_SIZE) {
+ const u8 *desc = &data[i];
@@ -72,16 +76,20 @@ index ff432ac..f83e445 100644
+ if (best_span) {
+ range->min_vfreq = best_min;
+ range->max_vfreq = best_max;
+ return true;
+ }
+
+ return false;
+}
+
static void drm_parse_vesa_mso_data(struct drm_connector *connector,
const struct displayid_block *block)
{
@@ -6648,26 +6688,41 @@ static void update_displayid_info(struct drm_connector *connector,
@@ -6720,26 +6763,43 @@ static void update_displayid_info(struct drm_connector *connector,
{
struct drm_display_info *info = &connector->display_info;
const struct displayid_block *block;
+ bool adaptive_sync_range = false;
+ bool displayid_base_logged = false;
struct displayid_iter iter;
@@ -120,10 +128,11 @@ index ff432ac..f83e445 100644
+
+ if (!info->monitor_range.min_vfreq && !info->monitor_range.max_vfreq &&
+ block->tag == DATA_BLOCK_2_ADAPTIVE_SYNC)
+ drm_update_displayid_adaptive_sync_range(connector, block);
+ adaptive_sync_range =
+ drm_update_displayid_adaptive_sync_range(connector, block);
}
+
+ if (info->monitor_range.min_vfreq && info->monitor_range.max_vfreq)
+ if (adaptive_sync_range)
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] DisplayID adaptive sync refresh rate range is %d Hz - %d Hz\n",
+ connector->base.id, connector->name,
@@ -133,3 +142,6 @@ index ff432ac..f83e445 100644
displayid_iter_end(&iter);
}
--
2.55.0
+13 -22
View File
@@ -2,9 +2,9 @@
# Based on Arch Linux linux package by Jan Alexander Steffens (heftig)
pkgbase=linux-ptl
pkgver=7.1.3.arch1
pkgver=7.1.8.arch1
pkgrel=1
pkgdesc='Linux with Panther Lake hardware backports (SDCA audio, PSR2, Panel Replay SU)'
pkgdesc='Linux for Panther Lake with Panel Replay power and OLED VRR fixes'
url='https://github.com/archlinux/linux'
arch=(
x86_64
@@ -40,10 +40,7 @@ _srctag=v${pkgver%.*}-${pkgver##*.}
source=(
https://cdn.kernel.org/pub/linux/kernel/v${pkgver%%.*}.x/${_srcname}.tar.{xz,sign}
$url/releases/download/$_srctag/linux-$_srctag.patch.zst{,.sig}
0017-ASoC-SDCA-Fix-NULL-pointer-dereference-in-sdca_jack_.patch
0019-drm-i915-psr-accept-early-transport-for-psr2.patch
0020-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch
0027-drm-i915-trans-push-frame-change-for-panel-replay.patch
0028-drm-i915-psr-exit-Panel-Replay-for-ALPM-lag.patch
0029-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch
)
@@ -53,29 +50,23 @@ validpgpkeys=(
647F28654894E3BD457199BE38DBBDC86092693E # Greg Kroah-Hartman
83BC8889351B5DEBBB68416EB8AC08600F108CDF # Jan Alexander Steffens (heftig)
)
b2sums=('b6466e2798627522f0339c670a223b21266f4d4ede39163867c0f122295e54c5d24093abb51d5c6c6c917de0cb199836e81f45f7c391a5cc138cac2a519438e8'
b2sums=('84b59e5572d91f5ea1bb603aa7691851bd9549e1bf18a6bec8e27eb8a6e2de2e33da2ad3e3aad501c793e9756e70245a16545e76b65a44ee52b33ccf5c3dd8e7'
'SKIP'
'b402dbf0b29131c2c3fe80406c5560e3e1a5c1384d6a1ba670793b343d57300ec312da7d3a4f7b3f44a6615b015d7fbebb2c7df832a99aa0e1941faef0481baa'
'308952977c15ac3ad976ff1d99d0d186814d4b03e1c8512fc3a4c0ac1ecce3f74be8f3900a7fd286492d4f930bedc089674bf713a278fa80c35413e0e6339f97'
'SKIP'
'b5c40077f538e67496f1c274774976d31c48af36a6bd0a5df570eddf097b18f79812ee811392534dae8b911dc1f2a9949d969f90ce4ad7bdf62692456908c1be'
'f893d63ef7b9e3ab05907117b561971a54c07422c46f7ec4511470b5dc81ab53815b6c73fac2b829fac43f4c480caa2f26741d604ad9ea5ecb460f7750f71635'
'217aed0e9dbb96ed845a1d686be7df3e27602600ab8b5fb663a54dbcd550c8e4bb2acce3bb8ed4d6ef268d5de1c6068d97d374de8ea2f208389a13dbb1ffa1c3'
'63339c2b7a073302c3e56148c1834fd9aed2adfcbb282c79fbc491c0013d9e16409cb46e3e3ff4d2cf6f39818b3873b449939e8d8c43acc664529a6e32229beb'
'4daaa96fac95436ad83ada07bb313ba1219b8b6c30f21b3d131d0f4731cd3739190c398b39ea9db636318b107b4ddd9c43ff7e15ac738d94dd2cfcc70d115264'
'c17328b6025bb55f229591506d7fff887f5da9580caf59e675dbaeee17447ef07254f70cf5282d6c46b4820a10724090a3e96b728f685dbbe26e1d08d17958d2')
b2sums_x86_64=('f08103d44e5506637ed115067c714e6184e0de538eea1c45a3d2ee8160a36d91755ca5f6cf1f4d7bc4500ed62bc69ca51fa21bef26a40c3a49c4e0f8df835c16')
'e672cd8d1f48756cf1062f84b83b4f676504cc6b44496511816a670435e00ccc22720fcbc36d013fd9b393389b955de5ec90715429ddbdcea860e1be80ab13fd'
'5ebe470414df104da9b9b20076369df0fd853ee50800926125c73641aad79dae8f52ab57ff793d9644d4f7834195d17e356567914d7a074b315f9de4924d4836'
'ed167ad347e83f072316b0d980ad192d97d0c4a69f6d1841a96089aa17caa0e57cb785214ed9297290f034420b5d0838dc75f84c7e9a9459eb49fd9dc22f3a3e')
b2sums_x86_64=('b10d80423aa3eb65e2046bf5b1998f9a7bdbc97494c6881881f50ffcdb5fe2e242782f59dbb6402cd77ce64b988dbf295fd9fa54f20180c76fbe88b82e1dbc9d')
# https://www.kernel.org/pub/linux/kernel/v7.x/sha256sums.asc
sha256sums=('be41c068e88f5242a19bccdbffbe077b18c47b45f627e2325504b4fab79dd1dc'
sha256sums=('ff01dcb449279d5b4cfccdb01fee639cf5ff1803f1749a77844dd33915422c49'
'SKIP'
'861ea54a40c1d25296422fd48eac2e02b46e0071b3d99a6c28555ae3acc8edd7'
'351cfb04db323bf5dd55ae8ce626650d20ba61441d202cadd8e198c6b9ef8f36'
'SKIP'
'167446c23001fe9d8dbe017e57a36f7f6e69f67a6b501ccbd9f4301ff08f8a47'
'a65fb17db3c5c44a9d1728d0bf182f20e0867eaabcdc20c76329e65d5cae2dd1'
'0ab145668a04b983b110b49fbd5a12f55c69106c7bb49cb968fff87392cc1c46'
'd4355299c1917a53b366e91c07e30bf595ade63654cfbca5ea8a2238730084a5'
'39530f920476e79578f41fbed94de825dd0e2285d578d1b5c5302e65e39b045f'
'3f6e98250b864125501a9968118861424977b3765eb4fcba7248735ed0b667ae')
'150f059eaf36580f9ca8eff4f917d8c3ee4eb5493507cbc29ce8e91b3ec56a93'
'82f3b6548b8badb9ec9ccc504c3d5d3ebdcb5f89837d5c48048ff8678f92dd61'
'1a0bebfba76248bbda67f8812278835de71754412369454ce60f4dde0bd81916')
export KBUILD_BUILD_HOST=archlinux
export KBUILD_BUILD_USER=$pkgbase
+11 -12
View File
@@ -1,17 +1,17 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86 7.1.3-arch1 Kernel Configuration
# Linux/x86 7.1.8-arch1 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="gcc (GCC) 16.1.1 20260625"
CONFIG_CC_VERSION_TEXT="gcc (GCC) 16.1.1 20260728"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=160101
CONFIG_CLANG_VERSION=0
CONFIG_AS_IS_GNU=y
CONFIG_AS_VERSION=24601
CONFIG_AS_VERSION=24700
CONFIG_LD_IS_BFD=y
CONFIG_LD_VERSION=24601
CONFIG_LD_VERSION=24700
CONFIG_LLD_VERSION=0
CONFIG_RUSTC_VERSION=109601
CONFIG_RUSTC_VERSION=109701
CONFIG_RUST_IS_AVAILABLE=y
CONFIG_RUSTC_LLVM_VERSION=220108
CONFIG_RUSTC_LLVM_MAJOR_VERSION=22
@@ -342,7 +342,7 @@ CONFIG_PERF_EVENTS=y
CONFIG_SYSTEM_DATA_VERIFICATION=y
CONFIG_PROFILING=y
CONFIG_RUST=y
CONFIG_RUSTC_VERSION_TEXT="rustc 1.96.1 (31fca3adb 2026-06-26) (Arch Linux rust 1:1.96.1-1)"
CONFIG_RUSTC_VERSION_TEXT="rustc 1.97.1 (8bab26f4f 2026-07-14) (Arch Linux rust 1:1.97.1-1)"
CONFIG_BINDGEN_VERSION_TEXT="bindgen 0.72.1"
CONFIG_TRACEPOINTS=y
@@ -459,12 +459,12 @@ CONFIG_X86_MINIMUM_CPU_FAMILY=64
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_IA32_FEAT_CTL=y
CONFIG_X86_VMX_FEATURE_NAMES=y
CONFIG_BROADCAST_TLB_FLUSH=y
CONFIG_CPU_SUP_INTEL=y
CONFIG_CPU_SUP_AMD=y
CONFIG_CPU_SUP_HYGON=y
CONFIG_CPU_SUP_CENTAUR=y
CONFIG_CPU_SUP_ZHAOXIN=y
CONFIG_BROADCAST_TLB_FLUSH=y
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_DMI=y
@@ -5113,7 +5113,6 @@ CONFIG_PINCTRL_MAX7360=m
CONFIG_PINCTRL_MCP23S08_I2C=m
CONFIG_PINCTRL_MCP23S08_SPI=m
CONFIG_PINCTRL_MCP23S08=m
CONFIG_PINCTRL_STMFX=m
CONFIG_PINCTRL_SX150X=y
CONFIG_PINCTRL_UPBOARD=m
CONFIG_PINCTRL_CS42L43=m
@@ -6055,7 +6054,6 @@ CONFIG_MFD_WM831X_SPI=y
CONFIG_MFD_WM8350=y
CONFIG_MFD_WM8350_I2C=y
CONFIG_MFD_WM8994=m
CONFIG_MFD_STMFX=m
CONFIG_MFD_WCD934X=m
CONFIG_MFD_ATC260X=m
CONFIG_MFD_ATC260X_I2C=m
@@ -7752,7 +7750,7 @@ CONFIG_SND_SOC_AMD_YC_MACH=m
CONFIG_SND_AMD_ACP_CONFIG=m
CONFIG_SND_SOC_AMD_ACP_COMMON=m
CONFIG_SND_SOC_ACPI_AMD_MATCH=m
CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS=m
CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS=y
CONFIG_SND_SOC_AMD_ACP_PDM=m
CONFIG_SND_SOC_AMD_ACP_LEGACY_COMMON=m
CONFIG_SND_SOC_AMD_ACP_I2S=m
@@ -11435,12 +11433,13 @@ CONFIG_EROFS_FS_SECURITY=y
CONFIG_EROFS_FS_BACKED_BY_FILE=y
CONFIG_EROFS_FS_ZIP=y
CONFIG_EROFS_FS_ZIP_LZMA=y
CONFIG_EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS=16
CONFIG_EROFS_FS_ZIP_DEFLATE=y
CONFIG_EROFS_FS_ZIP_ZSTD=y
CONFIG_EROFS_FS_ZIP_ACCEL=y
CONFIG_EROFS_FS_ONDEMAND=y
CONFIG_EROFS_FS_PCPU_KTHREAD=y
CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y
# CONFIG_EROFS_FS_PAGE_CACHE_SHARE is not set
CONFIG_VBOXSF_FS=m
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
@@ -12019,7 +12018,7 @@ CONFIG_CRYPTO_LIB_UTILS=y
CONFIG_CRYPTO_LIB_AES=y
CONFIG_CRYPTO_LIB_AES_ARCH=y
CONFIG_CRYPTO_LIB_AESCFB=y
CONFIG_CRYPTO_LIB_AES_CBC_MACS=m
CONFIG_CRYPTO_LIB_AES_CBC_MACS=y
CONFIG_CRYPTO_LIB_AESGCM=y
CONFIG_CRYPTO_LIB_ARC4=m
CONFIG_CRYPTO_LIB_GF128MUL=m