From 49214baae52860df10f18f237cfdb4bdfba09570 Mon Sep 17 00:00:00 2001 From: Gaggery Date: Tue, 21 Apr 2026 05:39:32 -0700 Subject: [PATCH] linux-ptl: [EXPERIMENTAL] enable Panel Replay Selective Update with cursor fix (#77) * linux-ptl: add package with audio, wifi, and Panel Replay SU patches Adds the linux-ptl Omarchy package for Panther Lake (PTL) hardware. The stock Arch linux kernel on PTL is missing: SDCA audio class driver backports, an iwlwifi generation-data fix, and Panel Replay SU enablement + cursor-lag workaround. Ship them in this package until they land upstream and Arch picks them up. Patch sets ========== Audio (SDCA backports on 6.19.10) 0001-0005, 0007-0008, 0010, 0012-0014, 0017 Cirrus CS35L57 amps and SDCA jack on Dell XPS OLED require the SDCA class driver plus a NULL-pointer fix (0017). Without these the sound card never registers. 0006/0009/0011/0015/0016 from the full upstream series are already in 6.19.10 stable and not needed. WiFi 0018-wifi-iwlwifi-mld-correctly-set-wifi-generation-data.patch Backport from wifi-next to fix wifi generation data reporting on Intel AX/BE radios in PTL. Display (PSR2 + Panel Replay SU) 0019-drm-i915-psr-accept-early-transport-for-psr2.patch 0020-drm-i915-psr-fix-su-granularity-source-for-psr2.patch 0022-drm-i915-psr-allow-psr-with-vrr-on-ptl.patch Enable PSR2 Early Transport and fix the SU-granularity DPCD source so PSR2 is not rejected at compute_config on OLED panels (LGD 2880x1800 etc). Also allow PSR with VRR on PTL. 0026-drm-i915-psr-handle-Panel-Replay-full-line-SU-granul.patch PR SU can advertise X granularity = 0xFFFF (full-line). Without this the modulo check rejects PR SU. 0027-drm-i915-trans-push-frame-change-for-panel-replay.patch Program TRANS_PUSH Frame Change path so PR SU cursor/plane updates actually trigger selective updates. 0028-drm-i915-psr-exit-Panel-Replay-for-ALPM-lag.patch Workaround for the LGD OLED panel (Dell XPS 14 DA14260, sink OUI 00:22:b9). PR ALPM AUX-Less wake/sleep cycling on this panel cannot resume selective updates at frame rate, producing ~15 Hz visible motion from a 120 Hz source. The workaround exits PR in frontbuffer_flush() and uses the existing dc3co_work delayed_work as a 50 ms idle timer. During continuous motion the timer is re-armed by each flush, so the link stays awake and motion is smooth; after 50 ms of genuine idle, dc3co_work fires and PR re-activates with ALPM for power savings. Compared to a per-commit exit/re-enter approach (earlier revision of this PR), the delayed re-entry keeps video and animation playback smooth: per-commit cycling pays the panel's wake-to-display latency on every frame, which is visible as playback stutter. 50 ms was chosen empirically against 100 ms and 200 ms on the same device; 50 ms gives the best idle and cursor-motion power while remaining subjectively identical in smoothness to the longer delays. Power on Dell XPS 14 OLED (LGD 2880x1800 @ 120 Hz, battery, brightness 268/512, 10-run averaged idle): PR SU + delayed-re-entry WA : 3268 mW (smooth) PR SU stock (cursor laggy) : 3384 mW PR SU + WA 100 ms : 3436 mW PR SU + WA 200 ms : 3484 mW PSR2 : 4060 mW (baseline) config.x86_64 changes ===================== Required for the kernel to boot cleanly on this hardware: CONFIG_PINCTRL_INTEL_PLATFORM=y (was =m) Without this the PTL GPIO controller is a late-loaded module and early probe of CS35L57 audio amps (spk-id-gpios) and the I2C touchpad time out with EPROBE_DEFER / -110 ETIMEDOUT. CONFIG_VFAT_FS=y, CONFIG_FAT_FS=y, CONFIG_MSDOS_FS=y, CONFIG_NLS_ISO8859_1=y (all were =m) Required for the ESP /boot to mount in the initramfs / UKI boot flow. Without these the box drops to emergency mode. CONFIG_RUST is disabled in this package because Arch Rust 1.94.1 is too new for kernel 6.19.x Rust code. * Backport DisplayID adaptive sync VRR parsing * add vrr patch * fix linux-ptl patch indentation * linux-ptl: renumber DisplayID VRR patch --------- Co-authored-by: Gaggery Tsai Co-authored-by: Spencer Bull --- ...-psr-accept-early-transport-for-psr2.patch | 19 +++ ...r-fix-su-granularity-source-for-psr2.patch | 56 ++++++++ ...m-i915-psr-allow-psr-with-vrr-on-ptl.patch | 36 +++++ ...dle-Panel-Replay-full-line-SU-granul.patch | 35 +++++ ...s-push-frame-change-for-panel-replay.patch | 60 ++++++++ ...5-psr-exit-Panel-Replay-for-ALPM-lag.patch | 116 +++++++++++++++ ...r-range-from-displayid-adaptive-sync.patch | 136 ++++++++++++++++++ pkgbuilds/edge/linux-ptl/PKGBUILD | 19 ++- pkgbuilds/edge/linux-ptl/config.x86_64 | 10 +- 9 files changed, 477 insertions(+), 10 deletions(-) create mode 100644 pkgbuilds/edge/linux-ptl/0019-drm-i915-psr-accept-early-transport-for-psr2.patch create mode 100644 pkgbuilds/edge/linux-ptl/0020-drm-i915-psr-fix-su-granularity-source-for-psr2.patch create mode 100644 pkgbuilds/edge/linux-ptl/0022-drm-i915-psr-allow-psr-with-vrr-on-ptl.patch create mode 100644 pkgbuilds/edge/linux-ptl/0026-drm-i915-psr-handle-Panel-Replay-full-line-SU-granul.patch create mode 100644 pkgbuilds/edge/linux-ptl/0027-drm-i915-trans-push-frame-change-for-panel-replay.patch create mode 100644 pkgbuilds/edge/linux-ptl/0028-drm-i915-psr-exit-Panel-Replay-for-ALPM-lag.patch create mode 100644 pkgbuilds/edge/linux-ptl/0029-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch diff --git a/pkgbuilds/edge/linux-ptl/0019-drm-i915-psr-accept-early-transport-for-psr2.patch b/pkgbuilds/edge/linux-ptl/0019-drm-i915-psr-accept-early-transport-for-psr2.patch new file mode 100644 index 0000000..bb6d885 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl/0019-drm-i915-psr-accept-early-transport-for-psr2.patch @@ -0,0 +1,19 @@ +diff -ruN 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 2026-04-06 23:05:21.088563236 -0700 ++++ b/drivers/gpu/drm/i915/display/intel_psr.c 2026-04-06 23:05:32.080081783 -0700 +@@ -716,8 +716,14 @@ + * 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. + */ +- intel_dp->psr.sink_psr2_support = y_req && ++ intel_dp->psr.sink_psr2_support = ++ (y_req || intel_dp->psr_dpcd[0] == ++ DP_PSR2_WITH_Y_COORD_ET_SUPPORTED) && + intel_alpm_aux_wake_supported(intel_dp); + drm_dbg_kms(display->drm, "PSR2 %ssupported\n", + intel_dp->psr.sink_psr2_support ? "" : "not "); diff --git a/pkgbuilds/edge/linux-ptl/0020-drm-i915-psr-fix-su-granularity-source-for-psr2.patch b/pkgbuilds/edge/linux-ptl/0020-drm-i915-psr-fix-su-granularity-source-for-psr2.patch new file mode 100644 index 0000000..d6601e5 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl/0020-drm-i915-psr-fix-su-granularity-source-for-psr2.patch @@ -0,0 +1,56 @@ +diff -ruN a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c +--- a/drivers/gpu/drm/i915/display/intel_alpm.c 2026-04-06 22:15:28.734440462 -0700 ++++ b/drivers/gpu/drm/i915/display/intel_alpm.c 2026-04-06 22:16:30.831931436 -0700 +@@ -317,7 +317,7 @@ + ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS | + ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines); + +- if (intel_dp->as_sdp_supported) { ++ if (intel_dp->as_sdp_supported && crtc_state->has_panel_replay) { + u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1; + + if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] & +@@ -432,8 +432,8 @@ + + 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); +diff -ruN 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 2026-04-06 22:15:28.733325868 -0700 ++++ b/drivers/gpu/drm/i915/display/intel_psr.c 2026-04-06 23:05:46.639364241 -0700 +@@ -498,7 +498,8 @@ + { + u8 su_capability = 0; + +- if (intel_dp->psr.sink_panel_replay_su_support) { ++ if (intel_dp->psr.sink_panel_replay_su_support && ++ panel_replay_global_enabled(intel_dp)) { + if (drm_dp_dpcd_read_byte(&intel_dp->aux, + DP_PANEL_REPLAY_CAP_CAPABILITY, + &su_capability) < 0) +@@ -513,7 +514,8 @@ + static unsigned int + intel_dp_get_su_x_granularity_offset(struct intel_dp *intel_dp) + { +- return intel_dp->psr.sink_panel_replay_su_support ? ++ return (intel_dp->psr.sink_panel_replay_su_support && ++ panel_replay_global_enabled(intel_dp)) ? + DP_PANEL_REPLAY_CAP_X_GRANULARITY : + DP_PSR2_SU_X_GRANULARITY; + } +@@ -521,7 +523,8 @@ + static unsigned int + intel_dp_get_su_y_granularity_offset(struct intel_dp *intel_dp) + { +- return intel_dp->psr.sink_panel_replay_su_support ? ++ return (intel_dp->psr.sink_panel_replay_su_support && ++ panel_replay_global_enabled(intel_dp)) ? + DP_PANEL_REPLAY_CAP_Y_GRANULARITY : + DP_PSR2_SU_Y_GRANULARITY; + } diff --git a/pkgbuilds/edge/linux-ptl/0022-drm-i915-psr-allow-psr-with-vrr-on-ptl.patch b/pkgbuilds/edge/linux-ptl/0022-drm-i915-psr-allow-psr-with-vrr-on-ptl.patch new file mode 100644 index 0000000..2548e89 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl/0022-drm-i915-psr-allow-psr-with-vrr-on-ptl.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gaggery Tsai +Date: Tue, 8 Apr 2026 15:00:00 -0700 +Subject: [PATCH] drm/i915/psr: Allow PSR with VRR on Panther Lake + +The blanket VRR rejection in _psr_compute_config() prevents PSR2 +from coexisting with VRR on all platforms. On Panther Lake (PTL, +DISPLAY_VER 30), PSR2 + VRR has been tested and works correctly. + +The existing Wa_16011303918 in intel_psr2_config_valid() already +handles the Alderlake-P stepping-specific VRR incompatibility. + +Remove the blanket check to allow PSR2 + VRR on platforms where +no specific workaround applies. + +Signed-off-by: Gaggery Tsai +--- + drivers/gpu/drm/i915/display/intel_psr.c | 6 ------ + 1 file changed, 6 deletions(-) + +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 +@@ -1712,12 +1712,6 @@ static bool _psr_compute_config(struct intel_dp *intel_dp, + if (!CAN_PSR(intel_dp) || !display->params.enable_psr) + return false; + +- /* +- * Currently PSR doesn't work reliably with VRR enabled. +- */ +- if (crtc_state->vrr.enable) +- return false; +- + entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, adjusted_mode); + if (entry_setup_frames >= 0) { + intel_dp->psr.entry_setup_frames = entry_setup_frames; diff --git a/pkgbuilds/edge/linux-ptl/0026-drm-i915-psr-handle-Panel-Replay-full-line-SU-granul.patch b/pkgbuilds/edge/linux-ptl/0026-drm-i915-psr-handle-Panel-Replay-full-line-SU-granul.patch new file mode 100644 index 0000000..384fa13 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl/0026-drm-i915-psr-handle-Panel-Replay-full-line-SU-granul.patch @@ -0,0 +1,35 @@ +From: Gaggery Tsai +Date: Thu, 10 Apr 2026 00:00:00 -0700 +Subject: [PATCH] drm/i915/psr: handle Panel Replay full-line SU granularity + +Panel Replay SU reports X granularity = 0xFFFF meaning full-line. +Without this, psr2_granularity_check() rejects PR SU because +2880 % 65535 != 0. + +Signed-off-by: Gaggery Tsai +--- + drivers/gpu/drm/i915/display/intel_psr.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +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 +@@ -1326,9 +1326,17 @@ + const int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay; + const int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay; + u16 y_granularity = 0; ++ u16 w_granularity = intel_dp->psr.su_w_granularity; ++ ++ /* ++ * Panel Replay SU can report 0xFFFF meaning full-line granularity. ++ * Substitute crtc_hdisplay so the modulo check passes. ++ */ ++ if (w_granularity == 0xFFFF) ++ w_granularity = crtc_hdisplay; + + /* PSR2 HW only send full lines so we only need to validate the width */ +- if (crtc_hdisplay % intel_dp->psr.su_w_granularity) ++ if (crtc_hdisplay % w_granularity) + return false; + + if (crtc_vdisplay % intel_dp->psr.su_y_granularity) diff --git a/pkgbuilds/edge/linux-ptl/0027-drm-i915-trans-push-frame-change-for-panel-replay.patch b/pkgbuilds/edge/linux-ptl/0027-drm-i915-trans-push-frame-change-for-panel-replay.patch new file mode 100644 index 0000000..85f33fb --- /dev/null +++ b/pkgbuilds/edge/linux-ptl/0027-drm-i915-trans-push-frame-change-for-panel-replay.patch @@ -0,0 +1,60 @@ +From: Gaggery Tsai +Date: Thu, 10 Apr 2026 10:00:00 -0700 +Subject: [PATCH] drm/i915: send TRANS_PUSH Frame Change for Panel Replay cursor updates + +Panel Replay Selective Update requires a software-triggered Frame +Change event via TRANS_PUSH to send dirty regions to the panel. +Cursor updates (legacy_cursor_update) skip TRANS_PUSH_SEND, so the +panel never receives cursor position changes under Panel Replay SU. + +Fix by sending TRANS_PUSH with LNL_TRANS_PUSH_PSR_PR_EN for cursor +updates when Panel Replay is active. + +Signed-off-by: Gaggery Tsai +--- +diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h +--- a/drivers/gpu/drm/i915/display/intel_vrr_regs.h ++++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h +@@ -97,6 +97,7 @@ + #define TRANS_PUSH(display, trans) _MMIO_TRANS2((display), (trans), _TRANS_PUSH_A) + #define TRANS_PUSH_EN REG_BIT(31) + #define TRANS_PUSH_SEND REG_BIT(30) ++#define LNL_TRANS_PUSH_PSR_PR_EN REG_BIT(16) + + #define _TRANS_VRR_VSYNC_A 0x60078 + #define TRANS_VRR_VSYNC(display, trans) _MMIO_TRANS2((display), (trans), _TRANS_VRR_VSYNC_A) +diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c +--- a/drivers/gpu/drm/i915/display/intel_crtc.c ++++ b/drivers/gpu/drm/i915/display/intel_crtc.c +@@ -732,7 +732,8 @@ + * which would cause the next frame to terminate already at vmin + * vblank start instead of vmax vblank start. + */ +- if (!state->base.legacy_cursor_update) ++ if (!state->base.legacy_cursor_update || ++ new_crtc_state->has_panel_replay) + intel_vrr_send_push(NULL, new_crtc_state); + + local_irq_enable(); +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 +@@ -597,7 +597,7 @@ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + +- if (!crtc_state->vrr.enable) ++ if (!crtc_state->vrr.enable && !crtc_state->has_panel_replay) + return; + + if (dsb) +@@ -605,7 +605,8 @@ + + intel_de_write_dsb(display, dsb, + TRANS_PUSH(display, cpu_transcoder), +- TRANS_PUSH_EN | TRANS_PUSH_SEND); ++ TRANS_PUSH_EN | TRANS_PUSH_SEND | ++ (crtc_state->has_panel_replay ? LNL_TRANS_PUSH_PSR_PR_EN : 0)); + + if (dsb) + intel_dsb_nonpost_end(dsb); diff --git a/pkgbuilds/edge/linux-ptl/0028-drm-i915-psr-exit-Panel-Replay-for-ALPM-lag.patch b/pkgbuilds/edge/linux-ptl/0028-drm-i915-psr-exit-Panel-Replay-for-ALPM-lag.patch new file mode 100644 index 0000000..d79e6eb --- /dev/null +++ b/pkgbuilds/edge/linux-ptl/0028-drm-i915-psr-exit-Panel-Replay-for-ALPM-lag.patch @@ -0,0 +1,116 @@ +From: Gaggery Tsai +Date: Thu, 17 Apr 2026 10:30:00 -0700 +Subject: [PATCH] drm/i915/psr: exit Panel Replay during updates to work around ALPM lag + +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. + +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). + +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. + +Signed-off-by: Gaggery Tsai +--- + drivers/gpu/drm/i915/display/intel_frontbuffer.c | 1 + + drivers/gpu/drm/i915/display/intel_psr.c | 33 ++++++++++++++++++ + drivers/gpu/drm/i915/display/intel_psr.h | 1 + + 3 files changed, 35 insertions(+) + +--- 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); + } +--- 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); +--- a/drivers/gpu/drm/i915/display/intel_psr.c ++++ b/drivers/gpu/drm/i915/display/intel_psr.c +@@ -1217,6 +1217,8 @@ static void tgl_psr2_enable_dc3co(struct intel_dp *intel_dp) + psr2_program_idle_frames(intel_dp, psr_compute_idle_frames(intel_dp)); + } + ++static void intel_psr_activate(struct intel_dp *intel_dp); ++ + static void tgl_dc3co_disable_work(struct work_struct *work) + { + struct intel_dp *intel_dp = +@@ -1227,6 +1229,13 @@ static void tgl_dc3co_disable_work(struct work_struct *work) + if (delayed_work_pending(&intel_dp->psr.dc3co_work)) + 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); ++ goto unlock; ++ } ++ + tgl_psr2_disable_dc3co(intel_dp); + unlock: + mutex_unlock(&intel_dp->psr.lock); +@@ -4593,2 +4593,29 @@ u8 intel_psr_needed_vblank_count_for_frontbuffer_flush(struct intel_display *dis + return psr_min_guardband; + } ++ ++/* ++ * 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) ++{ ++ struct intel_encoder *encoder; ++ ++ 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); ++ 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); ++ } ++} diff --git a/pkgbuilds/edge/linux-ptl/0029-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch b/pkgbuilds/edge/linux-ptl/0029-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch new file mode 100644 index 0000000..f018345 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl/0029-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spencer Bull +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. + +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. +--- + drivers/gpu/drm/drm_displayid_internal.h | 1 + + drivers/gpu/drm/drm_edid.c | 50 ++++++++++++++++++++++++++++++++++------ + 2 files changed, 43 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/drm_displayid_internal.h ++++ b/drivers/gpu/drm/drm_displayid_internal.h +@@ -67,6 +67,7 @@ + #define DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY 0x28 + #define DATA_BLOCK_2_CONTAINER_ID 0x29 + #define DATA_BLOCK_2_TYPE_10_FORMULA_TIMING 0x2a ++#define DATA_BLOCK_2_ADAPTIVE_SYNC 0x2b + #define DATA_BLOCK_2_VENDOR_SPECIFIC 0x7e + #define DATA_BLOCK_2_CTA_DISPLAY_ID 0x81 + +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -6527,6 +6527,46 @@ + 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, ++ const struct displayid_block *block) ++{ ++ struct drm_monitor_range_info *range = &connector->display_info.monitor_range; ++ const u8 *data = (const u8 *)(block + 1); ++ u16 best_min = 0, best_max = 0; ++ unsigned int best_span = 0; ++ int i; ++ ++ if (block->rev != 0 || block->num_bytes < DISPLAYID_ADAPTIVE_SYNC_DESC_SIZE || ++ block->num_bytes % DISPLAYID_ADAPTIVE_SYNC_DESC_SIZE) ++ return; ++ ++ for (i = 0; i < block->num_bytes; i += DISPLAYID_ADAPTIVE_SYNC_DESC_SIZE) { ++ const u8 *desc = &data[i]; ++ u16 min_vfreq = desc[2]; ++ u16 max_vfreq = ((((u16)desc[4]) & 0x3) << 8) | desc[3]; ++ unsigned int span; ++ ++ max_vfreq += 1; ++ if (!min_vfreq || max_vfreq <= min_vfreq) ++ continue; ++ ++ span = max_vfreq - min_vfreq; ++ if (span <= best_span) ++ continue; ++ ++ best_min = min_vfreq; ++ best_max = max_vfreq; ++ best_span = span; ++ } ++ ++ if (best_span) { ++ range->min_vfreq = best_min; ++ range->max_vfreq = best_max; ++ } ++} ++ + static void drm_parse_vesa_mso_data(struct drm_connector *connector, + const struct displayid_block *block) + { +@@ -6648,26 +6688,41 @@ + { + struct drm_display_info *info = &connector->display_info; + const struct displayid_block *block; ++ bool displayid_base_logged = false; + struct displayid_iter iter; + + displayid_iter_edid_begin(drm_edid, &iter); + displayid_iter_for_each(block, &iter) { ++ /* ++ * Primary use is a DisplayID base section property, but later ++ * blocks may still carry useful metadata like adaptive sync ranges. ++ */ ++ if (!displayid_base_logged) { ++ drm_dbg_kms(connector->dev, ++ "[CONNECTOR:%d:%s] DisplayID extension version 0x%02x, primary use 0x%02x\n", ++ connector->base.id, connector->name, ++ displayid_version(&iter), ++ displayid_primary_use(&iter)); ++ if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && ++ (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || ++ displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) ++ info->non_desktop = true; ++ ++ displayid_base_logged = true; ++ } ++ ++ 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); ++ } ++ ++ if (info->monitor_range.min_vfreq && info->monitor_range.max_vfreq) + drm_dbg_kms(connector->dev, +- "[CONNECTOR:%d:%s] DisplayID extension version 0x%02x, primary use 0x%02x\n", ++ "[CONNECTOR:%d:%s] DisplayID adaptive sync refresh rate range is %d Hz - %d Hz\n", + connector->base.id, connector->name, +- displayid_version(&iter), +- displayid_primary_use(&iter)); +- if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && +- (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || +- displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) +- info->non_desktop = true; +- +- /* +- * We're only interested in the base section here, no need to +- * iterate further. +- */ +- break; +- } ++ info->monitor_range.min_vfreq, ++ info->monitor_range.max_vfreq); ++ + displayid_iter_end(&iter); + } + diff --git a/pkgbuilds/edge/linux-ptl/PKGBUILD b/pkgbuilds/edge/linux-ptl/PKGBUILD index 5bf50c2..9a6ea89 100644 --- a/pkgbuilds/edge/linux-ptl/PKGBUILD +++ b/pkgbuilds/edge/linux-ptl/PKGBUILD @@ -3,8 +3,8 @@ pkgbase=linux-ptl pkgver=6.19.10.arch1 -pkgrel=1 -pkgdesc='Linux with Panther Lake hardware backports (SDCA audio, WiFi 7)' +pkgrel=3 +pkgdesc='Linux with Panther Lake hardware backports (SDCA audio, WiFi 7, PSR2, Panel Replay SU)' url='https://github.com/archlinux/linux' arch=( x86_64 @@ -43,6 +43,13 @@ source=( 0014-ASoC-SDCA-Limit-values-user-can-write-to-Selected-Mo.patch 0017-ASoC-SDCA-Fix-NULL-pointer-dereference-in-sdca_jack_.patch 0018-wifi-iwlwifi-mld-correctly-set-wifi-generation-data.patch + 0019-drm-i915-psr-accept-early-transport-for-psr2.patch + 0020-drm-i915-psr-fix-su-granularity-source-for-psr2.patch + 0022-drm-i915-psr-allow-psr-with-vrr-on-ptl.patch + 0026-drm-i915-psr-handle-Panel-Replay-full-line-SU-granul.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 ) source_x86_64=(config.x86_64) validpgpkeys=( @@ -55,8 +62,9 @@ b2sums=('f91cdd0b8727ce50ba286b321e85f394ff7e2eff27cde6e6e85e8abfc627b2b069bb567 '9632ace64efb38ee784d731ea85aeb285f0c3db486112122c17059c359c490a54c6ef7cd9d1d1cdecc8ae1d43df94536890b83a6671c1166a6b2148308f1baf3' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' - 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP') -b2sums_x86_64=('0fe195286246b83f0859f79dd2f6c633f5370057aa6afad4525309822ade855f7f6ebcfb01109786313c9331ad61d667b0257ecc7b7f239d2f962c9d34f0b10d') + 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' + 'SKIP' 'SKIP' 'SKIP' 'SKIP') +b2sums_x86_64=('9742088ab0381d8196046e42e8acb4ce01ea77461fada77dc90d197e859631e73b06ead4d512f15ab619b33ebad7bca58a10d4506d66916a99c40f9f52708a53') # https://www.kernel.org/pub/linux/kernel/v6.x/sha256sums.asc sha256sums=('466d441a0ea5e04b7023618b7b201bfd60effab225f806fd41ce663484395a1c' @@ -64,7 +72,8 @@ sha256sums=('466d441a0ea5e04b7023618b7b201bfd60effab225f806fd41ce663484395a1c' '96410b474e9b3efc2e03e5bb8e3819f41313e943f2157c215094668200cb069d' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' - 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP') + 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' + 'SKIP' 'SKIP' 'SKIP' 'SKIP') export KBUILD_BUILD_HOST=archlinux export KBUILD_BUILD_USER=$pkgbase diff --git a/pkgbuilds/edge/linux-ptl/config.x86_64 b/pkgbuilds/edge/linux-ptl/config.x86_64 index 31c6a59..673fa79 100644 --- a/pkgbuilds/edge/linux-ptl/config.x86_64 +++ b/pkgbuilds/edge/linux-ptl/config.x86_64 @@ -5202,7 +5202,7 @@ CONFIG_PINCTRL_BAYTRAIL=y CONFIG_PINCTRL_CHERRYVIEW=y CONFIG_PINCTRL_LYNXPOINT=m CONFIG_PINCTRL_INTEL=y -CONFIG_PINCTRL_INTEL_PLATFORM=m +CONFIG_PINCTRL_INTEL_PLATFORM=y CONFIG_PINCTRL_ALDERLAKE=m CONFIG_PINCTRL_BROXTON=m CONFIG_PINCTRL_CANNONLAKE=m @@ -11316,9 +11316,9 @@ CONFIG_UDF_FS=m # # DOS/FAT/EXFAT/NT Filesystems # -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="ascii" CONFIG_FAT_DEFAULT_UTF8=y @@ -11567,7 +11567,7 @@ CONFIG_NLS_ISO8859_8=m CONFIG_NLS_CODEPAGE_1250=m CONFIG_NLS_CODEPAGE_1251=m CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_2=m CONFIG_NLS_ISO8859_3=m CONFIG_NLS_ISO8859_4=m