Skip to content

[SL7] Support for Surface Laptop 7 with Intel Ultra 2 #1710

Description

@7HE-W0R1D

System

  • Surface Laptop 7 for Business with Intel
  • Intel Core Ultra 258V with Arc 130V graphics
  • 32Gb + 512 Gb
  • Kernel: 6.13.6-1.surface.fc41

Tested on Fedora 41 Workstation, out of box these works:

  • Touchscreen
  • Surface Dock USB, Display
  • USB A Port

the following are not working:

  • Keyboard (works in grub)
  • Touchpad (works in grub)
  • Battery info (shows as no battery in Fedora)

The rest (bluetooth, USB C port, camera) are not tested yet.

I'm messing around with the kernel and now it boots into a black screen with a dash, so I collected the diagnostic.sh in TTY2 instead.

Here below is the archive generated from diagnostic.sh:

diagnostics.tar.gz

Sorry if the post is very messy. I only have one keyboard so have to constantly switch between laptop & PC to search web and type command. I'll do more testing and update the post tomorrow. Please let me know how I can best contribute. As a previous SP4 owner I'm more than happy to do something for the project!

Activity

  1. rushlife commented on Mar 14, 2025

    @rushlife

    Thank you so much for what you're doing. It is awesome.

  2. qzed commented on Mar 14, 2025

    @qzed
    Member

    Can you try applying the following change?

    diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
    index 6cef456a40f1..081d326e7983 100644
    --- a/drivers/platform/surface/surface_aggregator_registry.c
    +++ b/drivers/platform/surface/surface_aggregator_registry.c
    @@ -480,6 +480,9 @@ static const struct acpi_device_id ssam_platform_hub_acpi_match[] = {
     	/* Surface Laptop 6 */
     	{ "MSHW0530", (unsigned long)ssam_node_group_sl6 },
     
    +	/* Surface Laptop 7 (Intel) */
    +	{ "MSHW0551", (unsigned long)ssam_node_group_sl7 },
    +
     	/* Surface Laptop Go 1 */
     	{ "MSHW0118", (unsigned long)ssam_node_group_slg1 },
     
    
  3. 7HE-W0R1D commented on Mar 16, 2025

    @7HE-W0R1D
    Author

    Hi! I compiled a kernel with this patch and now the following also works:

    • Keyboard
    • Battery status
    • Charging (charging might be working without this patch but cannot confirm that)

    The following is not working:

    • Trackpad
    • speaker
    • Microphone

    However, with the latest 6.13.6-200 official fedora kernel, the trackpad works out of the box, and it stopped working after I installed my own 6.13.0 kernel. I think it is very possible to make keyboard and trackpad work at the same time?

  4. rushlife commented on Mar 16, 2025

    @rushlife

    Hello, I don't know if this is useful information, but when I tested this unit, the trackpad was fully functional with kernel 6.14, which I had manually installed from the Ubuntu mainline.

  5. 7HE-W0R1D commented on Mar 16, 2025

    @7HE-W0R1D
    Author

    Thanks for the info. Actually with the official fedora 6.13 kernel, touchpad only registers one finger at a time, meaning gestures like two finger scroll, zoom, and right click are not working. I'm compiling the mainline 6.14 kernel and will report what's different.

  6. vixalien commented on Mar 16, 2025

    @vixalien

    @7HE-W0R1D cool! please report back on what works!

  7. vixalien commented on Mar 16, 2025

    @vixalien

    I also noticed that ssam_node_group_sl7 only contains a few nodes, and lacks for example, the keyboard. any advice on how to find out which nodes need to be in the list?

  8. 7HE-W0R1D commented on Mar 17, 2025

    @7HE-W0R1D
    Author

    So far my attempts to build and boot 6.13.7 and 6.14 kernels are out of luck, both of them present me with black screen with a dash on the upper left corner.

  9. rushlife commented on Mar 17, 2025

    @rushlife

    F#ck :(

  10. 7HE-W0R1D commented on Mar 17, 2025

    @7HE-W0R1D
    Author

    On the bright side, its probably my config that messed up with the kernel compiled, resulting in the black screen. Since I just started to learn these from last week.

  11. qzed commented on Mar 18, 2025

    @qzed
    Member

    I also noticed that ssam_node_group_sl7 only contains a few nodes, and lacks for example, the keyboard. any advice on how to find out which nodes need to be in the list?

    It has a keyboard node: https://github.com/linux-surface/kernel/blob/8b87bc2d8d00488493dc389fe768d6f9ad034fff/drivers/platform/surface/surface_aggregator_registry.c#L302.

    The entry was originally added by @konradybcio for the ARM variant, so not sure if the touchpad is connected differently there. You could try adding ssam_node_hid_sam_touchpad as a node to see if any of that works. Also, are there any unhandled event lines in the dmesg log when you are trying to use the touchpad (on kernels for which the keyboard is working but the touchpad is not)?

    You can also try playing around with the script that I mentioned here: linux-surface/surface-aggregator-module#45 (comment) (you need to modprobe surface_aggregator_cdev before running that). With that you can figure out which slot has devices connected.

    Finally, it could be that the touchpad is an IPTS/ITHC device... @StollD might be able to help with that.

  12. rushlife commented on Mar 18, 2025

    @rushlife

    hi, as I wrote above, the touchpad works since kernel 6.14 without any problem

  13. qzed commented on Mar 18, 2025

    @qzed
    Member

    @rushlife So both the touchpad and the keyboard (with patches)? I think 6.14 might include the new upstream ITHC patches. Also just single-touch or also multi-touch?

  14. rushlife commented on Mar 18, 2025

    @rushlife

    Hi Max,

    I don't know if multitouch was working during my very short testing period, but the touchpad worked well (haptic feedback was also okay). As I explained above, I didn't apply any patches to the kernel; I just installed the kernel packages from mainline.ubuntu.com on the Kubuntu 25.04 distro. After I realized I didn't have any keyboard functionality, I started googling for a solution and found this GitHub project. So no, there weren't any patches installed for kernel 6.14, and the touchpad was working just fine. The keyboard, not so much. And while I am a Linux noob, I gave up on this device and returned it. But if there is any progress, I will buy this unit again.

  15. 7HE-W0R1D commented on Mar 20, 2025

    @7HE-W0R1D
    Author

    I also noticed that ssam_node_group_sl7 only contains a few nodes, and lacks for example, the keyboard. any advice on how to find out which nodes need to be in the list?

    It has a keyboard node: https://github.com/linux-surface/kernel/blob/8b87bc2d8d00488493dc389fe768d6f9ad034fff/drivers/platform/surface/surface_aggregator_registry.c#L302.

    The entry was originally added by @konradybcio for the ARM variant, so not sure if the touchpad is connected differently there. You could try adding ssam_node_hid_sam_touchpad as a node to see if any of that works. Also, are there any unhandled event lines in the dmesg log when you are trying to use the touchpad (on kernels for which the keyboard is working but the touchpad is not)?

    You can also try playing around with the script that I mentioned here: linux-surface/surface-aggregator-module#45 (comment) (you need to modprobe surface_aggregator_cdev before running that). With that you can figure out which slot has devices connected.

    Finally, it could be that the touchpad is an IPTS/ITHC device... @StollD might be able to help with that.

    Hi! Sorry for the late reply. Took me a few days to learn these, but I finally managed to install 6.13.7 (previously 6.13.0) with the Surface patch by disabling the Intel SkyLake ACPI INT3472 module. Still no touchpad even with the ssam_node_hid_sam_touchpad node added. Here below are some notable logs from dmesg:

    [    0.290012] ACPI: \_SB_.PC00.D3C_: New power resource
    [    0.294440] ACPI: \: Can't tag data node
    [    0.297588] ACPI: \PIN_: New power resource
     
     
    [    2.483240] surface_hid 01:15:01:03:00: unexpected descriptor length: got 0, expected 9
    [    2.483248] surface_hid 01:15:01:03:00: probe with driver surface_hid failed with error -71
     
    [    3.781560] systemd[1]: bpf-restrict-fs: Failed to load BPF object: No such process
     
    [    5.086343] Bluetooth: hci0: Failed to load Intel firmware file intel/ibt-0190-0291-pci.sfi (-2)
    [    5.086421] Bluetooth: hci0: Failed to read MSFT supported features (-56)
    

    I will try to build other variations and try the script you mentioned to see what happens!

  16. 54 remaining items

  17. ghostplant commented on Jun 2, 2026

    @ghostplant

    @e5h5 Using this build: #2147 (comment)

    I get these errors during booting the OS (sound still not working):

    [Kernel dmesg]
    sof-audio-pci-intel-inl: xxxxxxxxx: error sof_probe_work failed err: -2
    
    [    3.302777] sof-audio-pci-intel-lnl 0000:00:1f.3: SoundWire enabled on CannonLake+ platform, using SOF driver
    [    3.302794] sof-audio-pci-intel-lnl 0000:00:1f.3: enabling device (0000 -> 0002)
    [    3.302887] sof-audio-pci-intel-lnl 0000:00:1f.3: DSP detected with PCI class/subclass/prog-if 0x040100
    [    4.101303] sof-audio-pci-intel-lnl 0000:00:1f.3: bound 0000:00:02.0 (ops intel_audio_component_bind_ops [xe])
    [    4.108487] sof-audio-pci-intel-lnl 0000:00:1f.3: use msi interrupt mode
    [    4.126783] sof-audio-pci-intel-lnl 0000:00:1f.3: No SoundWire machine driver found for the ACPI-reported configuration:
    [    4.126788] sof-audio-pci-intel-lnl 0000:00:1f.3: link 0 mfg_id 0x025d part_id 0x1320 version 0x3
    [    4.126791] sof-audio-pci-intel-lnl 0000:00:1f.3: link 0 mfg_id 0x025d part_id 0x1320 version 0x3
    [    4.126793] sof-audio-pci-intel-lnl 0000:00:1f.3: link 3 mfg_id 0x025d part_id 0x0721 version 0x3
    [    4.126799] sof-audio-pci-intel-lnl 0000:00:1f.3: Use SoundWire default machine driver with function topologies
    [    4.126800] sof-audio-pci-intel-lnl 0000:00:1f.3: hda codecs found, mask 4
    [    4.126802] sof-audio-pci-intel-lnl 0000:00:1f.3: NHLT device BT(0) detected, ssp_mask 0x4
    [    4.126804] sof-audio-pci-intel-lnl 0000:00:1f.3: BT link detected in NHLT tables: 0x4
    [    4.126806] sof-audio-pci-intel-lnl 0000:00:1f.3: DMICs detected in NHLT tables: 0
    [    4.127374] sof-audio-pci-intel-lnl 0000:00:1f.3: SOF firmware and/or topology file not found.
    [    4.127376] sof-audio-pci-intel-lnl 0000:00:1f.3: Supported default profiles
    [    4.127377] sof-audio-pci-intel-lnl 0000:00:1f.3: - ipc type 1 (Requested):
    [    4.127379] sof-audio-pci-intel-lnl 0000:00:1f.3:  Firmware file: intel/sof-ipc4/lnl/sof-lnl.ri
    [    4.127380] sof-audio-pci-intel-lnl 0000:00:1f.3:  Topology file: intel/sof-ipc4-tplg/sof-lnl-dummy.tplg
    [    4.127381] sof-audio-pci-intel-lnl 0000:00:1f.3: Check if you have 'sof-firmware' package installed.
    [    4.127382] sof-audio-pci-intel-lnl 0000:00:1f.3: Optionally it can be manually downloaded from:
    [    4.127383] sof-audio-pci-intel-lnl 0000:00:1f.3:    https://github.com/thesofproject/sof-bin/
    [    5.131749] sof-audio-pci-intel-lnl 0000:00:1f.3: error: sof_probe_work failed err: -2
    [lspci]
    00:1f.3 Multimedia audio controller: Intel Corporation Lunar Lake-M HD Audio Controller (rev 10)
            Subsystem: Realtek Semiconductor Co., Ltd. Device 3074
            Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
            Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
            Latency: 64
            Interrupt: pin A routed to IRQ 16
            IOMMU group: 19
            Region 0: Memory at 2051200000 (64-bit, non-prefetchable) [size=512K]
            Region 4: Memory at 2051000000 (64-bit, non-prefetchable) [size=2M]
            Capabilities: [50] Power Management version 3
                    Flags: PMEClk- DSI- D1- D2- AuxCurrent=55mA PME(D0-,D1-,D2-,D3hot+,D3cold+)
                    Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
            Capabilities: [c0] Vendor Specific Information: Intel <unknown>
            Capabilities: [60] MSI: Enable- Count=1/1 Maskable- 64bit+
                    Address: 0000000000000000  Data: 0000
            Kernel driver in use: sof-audio-pci-intel-lnl
            Kernel modules: snd_sof_pci_intel_lnl, snd_hda_intel
    
  18. nierdal commented on Jul 22, 2026

    @nierdal

    Surface Laptop 7 (Intel, Lunar Lake): full bring-up report, everything working

    Hardware: Surface Laptop for Business 7th Edition with Intel, Core Ultra 7 268V (Lunar Lake), 32 GB
    Distro/kernel: Fedora 44 KDE, stock Fedora kernel 6.19.10 (not the linux-surface kernel), Secure Boot disabled

    I went through a full hardware bring-up on this machine with Fable and everything now works: speakers, internal microphone, webcam, ambient light sensor (with native auto brightness), the haptic touchpad including physical clicks, keyboard, battery, fan, platform profiles and power button wake. As far as I can tell, the internal mic and the light sensor had not been done before on this model.

    I tried to document root causes rather than just recipes, so the fixes can be upstreamed. Everything runs with three out-of-tree module rebuilds. No DSDT overrides, no custom kernel.

    Component Status What it took
    Wi-Fi (BE201), BT, touchscreen, Xe GPU, NPU works nothing, stock
    Touchpad (cursor + gestures) works iptsd, the quickspi PTP collection is mute (section 5)
    Keyboard, battery, fan, platform profile works 3-line surface_aggregator_registry patch (MSHW0551)
    Headset jack (out + mic) works comes with the speaker fix
    Speakers works snd-soc-sdw-utils patches (a, b, d below)
    Internal mic array works backports from master (c)
    Webcam works, ~18.8 fps 1-line ov02c10 clock patch
    Ambient light sensor works 1-line registry patch, SAM HID sensor node (section 4)
    Haptic touchpad (physical clicks, tuning) works iptsd fork + thresholds + clickfinger (section 5)
    Power button wake, greeter keyboard race works udev rule + modules-load.d (section 6)

    1. SAM / keyboard / battery / fan: MSHW0551 (3 lines)

    On x86 the SAM controller enumerates and streams events, but nothing listens. surface_serial_hub logs endless rtl: dropping unexpected command message (rqid = 0x0101) and /sys/class/power_supply/ is empty.

    Root cause: surface_aggregator_registry.c has no ACPI match entry for MSHW0551. Mainline already defines ssam_node_group_sl7 (battery, AC, fan, perf profile, SAM keyboard) but only references it from the device tree table (microsoft,romulus13/15, the Snapdragon SL7). On x86 builds the symbol is dead code and GCC elides it. The fix is the same 3 lines this project already carries in patches/6.19/0007-surface-sam.patch:

    /* Surface Laptop 7 */
    { "MSHW0551", (unsigned long)ssam_node_group_sl7 },

    Rebuild just that one module out of tree, drop it in /lib/modules/$(uname -r)/updates/, depmod -a. Result: BAT1/ADP1 with real telemetry, internal keyboard (Microsoft Surface 045E:0C9A), surface_fan, and 4 ACPI platform profiles. Should be trivially upstreamable since the node group already exists in mainline.

    2. Audio: four independent bugs stacked

    Topology: Realtek RT721 (jack codec, SoundWire link 3) plus RT1320 amp(s) on link 0, SOF IPC4 "function topologies". Four separate defects on this machine:

    (a) SDCA topologies never load (DAI link naming)

    The generic SoundWire machine driver builds DAI links named SDW0-Playback, and sof_sdw_get_tplg_files() maps links to topology files by substring matching SimpleJack / SmartAmp / SmartMic in the link name. Those suffixes are only appended when ctx->append_dai_type is set, which only happens when one link carries multiple DAI types (soc_sdw_utils.c: ctx->append_dai_type |= (num_link_dailinks > 1)). On this machine each link carries one type, so no suffix, so only sof-hdmi-pcm5-id3.tplg loads and there are zero analog PCMs, even though all the needed sof-sdca-*.tplg files ship in alsa-sof-firmware. Forcing append_dai_type = true fixes it. Arguably the substring matcher should tolerate un-suffixed names upstream.

    (b) Ghost amplifier: BIOS declares 2x RT1320, only one exists

    ACPI _ADR tables declare two RT1320s on link 0 (same part, same unique_id, different class_id). Only one ever answers SoundWire enumeration (device_number = N/A, state UNATTACHED, verified over many reboots; the two ACPI nodes SWRA/SWRB are byte-identical, which looks like a copy-paste BIOS table from a SKU with two amps). The generic driver happily builds the ghost into the speaker DAI link, and every stream start dies in snd_soc_link_prepare() with -ENODATA (DPN_PortCtrl register write failed). Fix: in asoc_sdw_parse_sdw_endpoints(), skip any ACPI-declared peripheral whose matching sdw_slave is still SDW_SLAVE_UNATTACHED (and treat unique_id 0xf in _ADR as a wildcard when matching). This is a generically useful guard, not SL7 specific.

    (c) Internal microphone: two backports from master

    The mic array hangs off the RT1320's DMIC inputs (ACPI declares an SDCA SmartMic function on the amp; the 6.19 rt1320-sdw codec driver already ships the rt1320-aif2 "DP8-10 Capture" DAI and the SDCA MIC control plumbing for dev_id 0x6981). What 6.19 lacks is purely the machine driver wiring, which master has since added:

    1. The second (MIC type) DAI on the 0x1320 entry in codec_info_list (soc_sdw_utils.c): rt1320-aif2, SOC_SDW_DAI_TYPE_MIC, SOC_SDW_DMIC_DAI_ID, asoc_sdw_rt_dmic_rtd_init.
    2. Master's soc_sdw_rt_dmic.c, which counts SmartMic-capable RT1320s and emits cfg-mics:N into card->components. Without cfg-mics, alsa-ucm 1.2.16 and later hard-fails (${var:Mics}' is not defined, snd_use_case_mgr_open returns -22) and PipeWire silently falls back to stereo-fallback with no mic and no UCM speaker routing. That interaction is worth knowing about: the new UCM configs require the new kernel components string.

    With both backported: a 00-04: Microphone PCM, mic:rt1320-1 cfg-mics:1 in components, a "Microphones" source in PipeWire, and real captured audio (peaks at -5 dBFS). Anyone on a kernel that includes those master commits should get this for free; on 6.19 and earlier you need the two backports.

    (d) Side effect: the amp loses its "-1" suffix

    Once the RT1320 has a MIC DAI it is no longer "purely an amp", so hda.c's find_acpi_adr_device() stops numbering it (rt1320 instead of rt1320-1). Two things break: asoc_sdw_rt_amp_spk_rtd_init() returns -EINVAL unless the prefix contains -1/-2 (card probe fails), and the UCM speaker macros cset rt1320-1 ... controls. Master avoids this with the explicit .is_amp flag on codec_info; on 6.19 an equivalent fix is renumbering attached amps in asoc_sdw_parse_sdw_endpoints() (once per device, ghosts excluded). Nice property: after (b) and (d) the single real amp is always rt1320-1, so stock alsa-ucm 1.2.16 config works unmodified.

    All four changes live in one out-of-tree rebuild of snd-soc-sdw-utils (plus its 15 companion sources; watch out for the soc_sdw_rt_amp_coeff_tables.h and ../codecs/rt1308.h include deps).

    3. Webcam: OV02C10 wired to 12 MHz, driver demands 19.2 MHz

    The full IPU7 stack works on 6.19 (firmware loads, CSE auth passes, Found supported sensor OVTI02C1:00). The only failure is:

    ov02c10 i2c-OVTI02C1:00: error -EINVAL: external clock 12000000 is not supported
    

    Microsoft feeds the sensor 12 MHz; the driver (still in current master) hard-requires 19.2 MHz. Downgrading the check to a warning (same approach as walkingchimp's surface-laptop-7-intel-webcam repo) lets the sensor probe and stream. The PLL registers remain tuned for 19.2 MHz so everything runs at 12/19.2 = 0.625 speed: measured 18.78 fps vs 30 nominal, exactly the predicted ratio, plus one benign csi2-0: Short packet discarded per session.

    Notes beyond the existing workaround repo:

    • No userspace bridge is needed on a current stack. libcamera 0.7 (Simple pipeline + SoftISP) with pipewire-plugin-libcamera and wireplumber picks the sensor up natively and exposes a portal camera ("Built-in Front Camera") to browsers at the full 18.78 fps. The 12 fps ceiling in that repo is its Python processing, not the sensor.
    • Hide the 30+ raw IPU7 /dev/video* nodes from app pickers with a wireplumber rule (device.disabled = true on device.name = "~v4l2_device.pci-0000_00_05.*"), otherwise every camera dialog lists a wall of dead "ipu7" entries.
    • I attempted a blind PLL rescale for true 30 fps (scaling the 0x0304/0x0305 multiplier by 19.2/12); the register writes were accepted but had zero measurable effect, so the real PLL layout differs from the obvious guess. A proper fix needs the OV02C10 datasheet. Upstream 12 MHz support would help several Lunar Lake designs, since intel_ipu7 provides a 12 MHz img_clk here.

    4. Ambient light sensor: it's a SAM HID sensor collection (1 line)

    Windows advertises adaptive brightness, so the sensor exists, but it is not a host-visible I2C device. Dead ends first, so nobody repeats them:

    • ACPI MSHW0380 at \_SB_.PC00.I2C0.FINK declares three I2cSerialBus connections on i2c_designware.0 (0x3e, 0x44, 0x39 at 100 kHz). Auditing the full official Windows driver package (119 INFs) shows MSHW0380 is the Surface Display Hardware Driver (Tcon/FPGA); its UMDF DLL contains zero light sensor code, and no INF in the entire package binds a light sensor. 0x39 is the standard address of an ams TMD3719 ALS/color/flicker sensor, which probably does exist physically behind the display, but the EC/display firmware owns it.
    • Do not probe those I2C addresses. Touching 0x39 wedges i2c_designware.0 (a line is held low) until reboot. FINK has no _PS0 and its _DEP points at \_SB.SSH_, the EC.

    The actual mechanism is the same as on Surface Pro 8/9/11 and the Laptop Studio: the EC publishes the sensor as a HID sensor collection, SSAM node 01:15:01:06:00. Mainline already defines ssam_node_hid_sam_sensors; it is just missing from ssam_node_group_sl7. Add one line next to the keyboard node:

    &ssam_node_hid_sam_sensors,

    Result, all automatic: SAM HID device 045E:0C9B appears, hid-sensor-hub binds, hid-sensor-als autoloads, iio:device0 shows up ("als", in_illuminance_raw, real lux values), iio-sensor-proxy picks it up, and you get native auto brightness in Plasma 6.6+ / GNOME. Trivially upstreamable together with the MSHW0551 entry.

    5. Haptic touchpad: iptsd tuning and the physical click problem

    The touchpad (quickspi-hid 045E:0C9F, Sensel haptic pad, 120x80 mm) needs iptsd for heatmap processing; the firmware's PTP touchpad HID collection is mute (see iptsd#192, iptsd#197). Practical findings beyond that:

    • All clicks are software. Stock iptsd never emits BTN_LEFT/BTN_RIGHT; the haptic "click" feedback is firmware-internal. So clicking equals libinput tap-to-click, and any compositor that loses its per-device tap setting (the virtual touchpad is recreated on every iptsd restart) silently loses all clicks. Persist your touchpad settings keyed to IPTSD Virtual Touchpad 045E:0C9F.

    • Contact detection thresholds are a razor's edge on this pad (all measured via evdev captures): defaults (24/20) make light-touch slides flicker (69 touch sessions in 60 s of continuous sliding, each fragment becoming a ghost tap-click); 16/12 detects noise as contacts (20-45 mm position teleports); 20/14 makes contacts sticky (2-3 s release lag, taps rejected); the SLS2 preset's Neutral = average plus offset causes heavy position jitter here (all taps rejected as motion). Working compromise: ActivationThreshold = 20, DeactivationThreshold = 16, everything else default. Avoid PeakSuppressionRadius >= 2, it suppresses the real second finger.

    • Physical clicks and Windows-like behavior: alex-lentz's iptsd fork decodes the firmware's force press bit into real BTN_LEFT, adds a button debounce, and a tracker guard against position teleports. With it, enable the clickfinger click method in the compositor: 1-finger press = left, 2-finger press = right, 3-finger = middle. Without clickfinger a two-finger press registers as a left click, because the combined force of two fingers trips the firmware's press bit. Two-finger tap right-click stays unreliable regardless (the second, lighter finger often sits below the detection threshold), so clickfinger is the robust right click path.

    • The ghost tap cure: bridge detection dropouts at the source. Even at the best thresholds, contacts "blink": raw captures show a continuous one-finger slide fragmenting into dozens of 8-100 ms touch sessions, and both fingers of a scroll blinking together. libinput reads each fragment as a tap, giving ghost left clicks while sliding and ghost right clicks while two-finger scrolling. No libinput knob fixes this. What fixed it: a small iptsd patch adding a [Touchpad] LiftGraceMs option. A contact that disappears is not reported lifted until it has been gone that long; held contacts keep their slot and the BTN_TOOL finger count stays stable. 110 ms eliminated every ghost tap here with no perceptible lag (70 ms was almost enough). It's about 40 lines in touch.hpp plus config plumbing, happy to share or send a PR.

    • Palm rejection via touch size: iptsd reports ABS_MT_TOUCH_MAJOR, so libinput's size-based palm detection works once you give it a threshold. Nobody had written the quirks file. Measured here: fingertip around 850-1100 units, palm/thumb around 1550-1650. /etc/libinput/local-overrides.quirks:

      [IPTSD Virtual Touchpad]
      MatchUdevType=touchpad
      MatchName=IPTSD Virtual Touchpad*
      AttrPalmSizeThreshold=1400
    • Suspend kills gestures: after s2idle the firmware falls back to basic mouse reports and iptsd silently receives nothing (cursor and physical click survive, gestures die). Restart iptsd from a suspend.target hook.

    6. Assorted platform fixes

    • Bluetooth (BE201, PCIe) breaks suspend entirely: btintel_pcie times out entering D2 ("Timeout on alive interrupt"), which aborts every system suspend with -16 (the laptop silently retries in a loop with the lid closed, draining the battery) and leaves hci0 dead until a PCI remove/rescan. Workaround: a /usr/lib/systemd/system-sleep/ script that does modprobe -r btintel_pcie on pre and reloads it on post.
    • Power button doesn't wake from s2idle (lid does): the power button lives on the SAM keyboard, behind the EC's UART (surface_serial_hub), whose wakeup is disabled by default. echo enabled > /sys/.../serial0/serial0-0/power/wakeup (udev rule on SUBSYSTEM=="serial", DRIVER=="surface_serial_hub") fixes it.
    • Internal keyboard dead at the SDDM greeter (revived by USB keyboard hotplug): the SAM keyboard appears about 8 s into boot, right while the greeter's compositor initializes. Force-loading surface_aggregator_registry and surface_hid via /etc/modules-load.d/ removes the race.
    • Sleep of death, random failure to wake from s2idle (black screen, power button and lid both dead, Fn-lock LED still toggles because the keyboard MCU is independent, only a 30 s forced power-off recovers). The journal shows suspend entering s2idle and then nothing. Likely culprit found in the ACPI tables: the DSDT declares GPE \_GPE._LAB (GPE 0xAB, level triggered) whose body calls SLAB(), an External method that no loaded table defines (the whole Intel GPE1 SLxx handler SSDT is missing from the firmware). Every time the GPE fires the method aborts with AE_NOT_FOUND, the level GPE stays asserted, and it storms at about 5/s for minutes after each resume (tens of thousands of ACPI Error lines per boot), alongside bursts of No handler or method for GPE xx, disabling event and No installed handler for fixed event - PowerButton (about 2700 per resume, the PM registers read 0xFF during early wake). A stuck level GPE firing during the s2idle noirq wake loop can wedge it exactly like this. Fix: mask the broken GPE with acpi_mask_gpe=0xAB on the kernel command line (and immediately via echo mask > /sys/firmware/acpi/interrupts/gpeAB). Nothing is lost, that handler can never execute anyway.
    • Factory display ICC profiles ship in the Windows driver MSI (identify the hash-named payload files by the acsp signature at offset 36): "sRGB", "Vivid" and "HDR" profiles for the panel with full wtpt/XYZ/TRC characterization. Caveat: used as-is they wash out the screen under KWin (grey blacks). Two causes: a bogus bkpt tag set to exactly 10% of white, and Microsoft's MHC2 tag declaring a 0.1 to 600 nit range, which KWin 6.2+ parses with priority and uses to remap SDR output. Strip the private tags (MHC2, ACFI, mscs, msb3, DVB1) and zero bkpt; the resulting plain profiles work perfectly in Plasma's per-output color profile setting. When replacing a profile file under the same path, switch the output to "None" and back to force KWin to reload it.

    Reproducibility notes

    • All three modules are built out of tree against the running kernel's kernel-devel and installed in /lib/modules/$K/updates/ (must be rebuilt for every kernel). Pin your kernel or automate the rebuild.
    • Fedora-specific trap: dnf install kernel-devel without a version pulls kernel-devel-matched, which drags in a partial newer kernel and flips the default boot entry to it. Always dnf install "kernel-devel-$(uname -r)".
    • After reloading the audio stack (snd_soc_sof_sdw must be removed first or everything stays pinned), restart PipeWire and wireplumber. A stale wireplumber holds an outdated card view and will show off/stereo-fallback profiles even when UCM is fine. spa-acp-tool -c0 info and alsaucm -c sof-soundwire set _verb HiFi list _devices are the fastest way to tell kernel-side from UCM-side failures.

    Happy to share the exact patch files if useful. Nothing here is speculative, every root cause above was verified on the device (dynamic debug, SoundWire sysfs state, register level probing).

  19. ghostplant commented on Jul 22, 2026

    @ghostplant

    Thanks. Can you share the patch? Does "shutting down Ubuntu" work normally instead of getting stuck into black-screen?

  20. nierdal commented on Jul 22, 2026

    @nierdal

    Sure, here you go! And I can't say for Ubuntu, but for Fedora the sutting down work perflectly.

    surface-laptop-7-intel-patches.zip

  21. alex-lentz commented on Jul 22, 2026

    @alex-lentz

    I just want to make sure I high level grasp before I decide it's worth grabbing that laptop I was going to get rid of and giving it a go - you got basically everything working (except maybe touchscreen?) on the latest Fedora and without the surface-linux-kernel?

  22. nierdal commented on Jul 22, 2026

    @nierdal

    Yes, that's right , with one correction: the touchscreen is actually one of the things that just works out of the box, nothing needed. Stock Fedora 44, stock Fedora kernel, no linux-surface kernel.

    To set expectations though, "stock kernel" doesn't mean "install and done". You need to rebuild the kernel modules (small patches: one for keyboard/battery/fan, one for audio, one for the webcam), install iptsd for touchpad gestures, and drop in a handful of config files. Secure Boot has to be off for the unsigned modules, and you have to rebuild them after every kernel update, so I pin my kernel. Maybe two hours of work following the writeup.

    Out of the box you get: display, touchscreen, Wi-Fi, Bluetooth, GPU, NPU, USB, and basic touchpad (cursor and click, no gestures). After the patches: keyboard, battery, fan, speakers, mic, webcam at ~19 fps, light sensor with auto brightness, full touchpad, working suspend. The only thing not perfect is the webcam frame rate (19 instead of 30).

    So if the alternative is getting rid of the laptop, it's absolutely worth a go. To make it easier, you can use an AI CLI model (Claude-CLI, Codex, etc..) and give it my files and instructions.

  23. ghostplant commented on Jul 23, 2026

    @ghostplant

    Wish the repo maintainer to make a new ubuntu release with this applied!

  24. richiemort79 commented on Jul 27, 2026

    @richiemort79

    This is excellent progress indeed! What needs to happen to role this stuff into the linux-surface kernel?

  25. richiemort79 commented on Jul 27, 2026

    @richiemort79

    @nierdal - are you planning to PR these against linux-surface/kernel?

  26. Matthijsvdww commented on Jul 27, 2026

    @Matthijsvdww

    @nierdal Amazing writeup! I have no prior linux experience, but I will do anything to get away from Windows. Will try this out in the coming weeks.

  27. kazenshi commented on Aug 5, 2026

    @kazenshi

    @nierdal can you provide comprehensive instructions for the average user to apply your patches on their machine so that we can also test?

  28. richiemort79 commented on Aug 5, 2026

    @richiemort79

    @kazenshi if you have time to debug you can try this https://github.com/richiemort79/sl7-linux-enablement which is nearly ready but I haven't had time to test on a an actual install yet.

  29. richiemort79 commented on Aug 5, 2026

    @richiemort79

    @kazenshi if you have time to debug you can try this https://github.com/richiemort79/sl7-linux-enablement which is nearly ready but I haven't had time to test on a an actual install yet.

    I've made progress with this today and its basically usable as a daily now. still some issues I can't work out with audio, screen brightness controls, webcam. I am no expert at this but the scripts will roll patches etc into your current kernel on Zorin.

  30. walkingchimp commented on Sep 1, 2026

    @walkingchimp

    Opened #2263 with what I think is the root cause of the intermittent suspend hangs on SL7 Intel: s2idle wedges in dw8250_suspend on ttyS4 (the SAM UART), because free_irq() never returns while IRQ 16 (idma64.4, ttyS4) is storming - 1.5 billion interrupts in 19h. Soft lockup, CPU pinned for hours. Ruled out evdi, GPE 0xAB and Bluetooth. Also a warning in there: do not arm pm_trace on this machine.

  31. ghostplant commented on Sep 1, 2026

    @ghostplant

    I follow @e5h5 's patch on the audio driver, a strange thing is that the speaker doesn't work, but earphone can work, so I have to always plug in the earphone to hear the audio.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions