Repository navigation
[SL7] Support for Surface Laptop 7 with Intel Ultra 2 #1710
Description
Activity
Thank you so much for what you're doing. It is awesome.
Reacted by BreakfastBerry and Angelo VerlainCan 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 },
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?
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.
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.
@7HE-W0R1D cool! please report back on what works!
I also noticed that
ssam_node_group_sl7only 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?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.
F#ck :(
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.
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_touchpadas a node to see if any of that works. Also, are there anyunhandled eventlines 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_cdevbefore 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.
Reacted by BreakfastBerryhi, as I wrote above, the touchpad works since kernel 6.14 without any problem
@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?
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.
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_touchpadas a node to see if any of that works. Also, are there anyunhandled eventlines 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_cdevbefore 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 INT3472module. Still no touchpad even with thessam_node_hid_sam_touchpadnode added. Here below are some notable logs fromdmesg:[ 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!
54 remaining items
@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_intelSurface 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 disabledI 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_registrypatch (MSHW0551)Headset jack (out + mic) works comes with the speaker fix Speakers works snd-soc-sdw-utilspatches (a, b, d below)Internal mic array works backports from master (c) Webcam works, ~18.8 fps 1-line ov02c10clock patchAmbient 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_hublogs endlessrtl: dropping unexpected command message (rqid = 0x0101)and/sys/class/power_supply/is empty.Root cause:
surface_aggregator_registry.chas no ACPI match entry forMSHW0551. Mainline already definesssam_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 inpatches/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/ADP1with 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, andsof_sdw_get_tplg_files()maps links to topology files by substring matchingSimpleJack/SmartAmp/SmartMicin the link name. Those suffixes are only appended whenctx->append_dai_typeis 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 onlysof-hdmi-pcm5-id3.tplgloads and there are zero analog PCMs, even though all the neededsof-sdca-*.tplgfiles ship inalsa-sof-firmware. Forcingappend_dai_type = truefixes it. Arguably the substring matcher should tolerate un-suffixed names upstream.(b) Ghost amplifier: BIOS declares 2x RT1320, only one exists
ACPI
_ADRtables declare two RT1320s on link 0 (same part, sameunique_id, differentclass_id). Only one ever answers SoundWire enumeration (device_number = N/A, stateUNATTACHED, verified over many reboots; the two ACPI nodesSWRA/SWRBare 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 insnd_soc_link_prepare()with-ENODATA(DPN_PortCtrl register write failed). Fix: inasoc_sdw_parse_sdw_endpoints(), skip any ACPI-declared peripheral whose matchingsdw_slaveis stillSDW_SLAVE_UNATTACHED(and treatunique_id0xfin_ADRas 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-sdwcodec driver already ships thert1320-aif2"DP8-10 Capture" DAI and the SDCA MIC control plumbing fordev_id 0x6981). What 6.19 lacks is purely the machine driver wiring, which master has since added:- The second (MIC type) DAI on the
0x1320entry incodec_info_list(soc_sdw_utils.c):rt1320-aif2,SOC_SDW_DAI_TYPE_MIC,SOC_SDW_DMIC_DAI_ID,asoc_sdw_rt_dmic_rtd_init. - Master's
soc_sdw_rt_dmic.c, which counts SmartMic-capable RT1320s and emitscfg-mics:Nintocard->components. Withoutcfg-mics, alsa-ucm 1.2.16 and later hard-fails (${var:Mics}' is not defined,snd_use_case_mgr_openreturns-22) and PipeWire silently falls back tostereo-fallbackwith 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: MicrophonePCM,mic:rt1320-1 cfg-mics:1in 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'sfind_acpi_adr_device()stops numbering it (rt1320instead ofrt1320-1). Two things break:asoc_sdw_rt_amp_spk_rtd_init()returns-EINVALunless the prefix contains-1/-2(card probe fails), and the UCM speaker macros csetrt1320-1 ...controls. Master avoids this with the explicit.is_ampflag oncodec_info; on 6.19 an equivalent fix is renumbering attached amps inasoc_sdw_parse_sdw_endpoints()(once per device, ghosts excluded). Nice property: after (b) and (d) the single real amp is alwaysrt1320-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 thesoc_sdw_rt_amp_coeff_tables.hand../codecs/rt1308.hinclude 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 supportedMicrosoft 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 discardedper 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-libcameraand 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 = trueondevice.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_ipu7provides a 12 MHzimg_clkhere.
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
MSHW0380at\_SB_.PC00.I2C0.FINKdeclares three I2cSerialBus connections oni2c_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_PS0and its_DEPpoints 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 definesssam_node_hid_sam_sensors; it is just missing fromssam_node_group_sl7. Add one line next to the keyboard node:&ssam_node_hid_sam_sensors,
Result, all automatic: SAM HID device
045E:0C9Bappears,hid-sensor-hubbinds,hid-sensor-alsautoloads,iio:device0shows 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 = averageplus offset causes heavy position jitter here (all taps rejected as motion). Working compromise:ActivationThreshold = 20,DeactivationThreshold = 16, everything else default. AvoidPeakSuppressionRadius >= 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] LiftGraceMsoption. 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 intouch.hppplus 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_pcietimes 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 doesmodprobe -r btintel_pcieon 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 onSUBSYSTEM=="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_registryandsurface_hidvia/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 callsSLAB(), an External method that no loaded table defines (the whole Intel GPE1SLxxhandler 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 ofNo handler or method for GPE xx, disabling eventandNo 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 withacpi_mask_gpe=0xABon the kernel command line (and immediately viaecho 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
acspsignature 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 bogusbkpttag set to exactly 10% of white, and Microsoft'sMHC2tag 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 zerobkpt; 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-develand 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-develwithout a version pullskernel-devel-matched, which drags in a partial newer kernel and flips the default boot entry to it. Alwaysdnf install "kernel-devel-$(uname -r)". - After reloading the audio stack (
snd_soc_sof_sdwmust be removed first or everything stays pinned), restart PipeWire and wireplumber. A stale wireplumber holds an outdated card view and will showoff/stereo-fallbackprofiles even when UCM is fine.spa-acp-tool -c0 infoandalsaucm -c sof-soundwire set _verb HiFi list _devicesare 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).
Reacted by Jaeho Lee and NekocatReacted by Jaeho Lee and NekocatReacted by Jaeho Lee- The second (MIC type) DAI on the
Thanks. Can you share the patch? Does "shutting down Ubuntu" work normally instead of getting stuck into black-screen?
Sure, here you go! And I can't say for Ubuntu, but for Fedora the sutting down work perflectly.
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?
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.
Reacted by ghostplantWish the repo maintainer to make a new ubuntu release with this applied!
This is excellent progress indeed! What needs to happen to role this stuff into the linux-surface kernel?
@nierdal - are you planning to PR these against linux-surface/kernel?
@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.
@nierdal can you provide comprehensive instructions for the average user to apply your patches on their machine so that we can also test?
@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.
@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.
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.
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.
System
Tested on Fedora 41 Workstation, out of box these works:
the following are not working:
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!