.docname {XPS 13 9350 (2024)} .include {docs} ## Sound Install the firmware `sof-firmware` ### Random Freezes (SoundWire Kernel Panic) On kernel `7.1.x` the machine hard-hangs every day or two. The internal panel freezes on its last frame, the external DisplayPort monitors go black, the LED above the keyboard starts blinking, and nothing at all is written to the journal. Only a long press on the power button recovers it. The cause is a NULL pointer dereference in the Intel SoundWire interrupt handler. `sdw_intel_thread` walks the SoundWire link list and calls `sdw_cdns_irq(irq, link->cdns)` while the links are powered back up after a runtime suspend. One link is still listed with `cdns == NULL`, so the handler dereferences NULL. The kernel dies in interrupt context, which is why the journal stays empty — journald never gets a chance to flush. .collapse {Panic trace} ```txt Oops: general protection fault, kernel NULL pointer dereference 0x3c0: 0000 [#1] SMP NOPTI CPU: 3 UID: 0 PID: 807 Comm: irq/146-AudioDS Hardware name: Dell Inc. XPS 13 9350/0MMW13, BIOS 1.22.0 06/01/2026 RIP: 0010:sdw_cdns_irq+0x9/0x290 [soundwire_cadence] RSI: 0000000000000000 Call Trace: sdw_intel_thread+0x3b/0x70 [soundwire_intel] hda_dsp_interrupt_thread+0x99/0x380 [snd_sof_intel_hda_generic] irq_thread_fn+0x25/0x60 irq_thread+0x1cb/0x340 kthread+0xe4/0x120 ret_from_fork+0x2a7/0x330 kernel tried to execute NX-protected page - exploit attempt? (uid: 0) BUG: unable to handle page fault for address: ffff88f18fab5340 Oops: Oops: 0011 [#2] SMP NOPTI ``` The faulting instruction is `cmpb $0x0, 0x3c0(%rsi)` with `RSI = 0`. The second fault is what makes the hang unrecoverable rather than just killing the interrupt thread. Anything that repeatedly wakes the audio controller makes this far more likely — a Spotify stream running in the background is enough. Before the workaround the controller spent roughly 89% of its uptime runtime-suspended, so the race window was being hit constantly. Pin the audio controller out of runtime power management so the SoundWire links stay powered and the window never opens. `/etc/udev/rules.d/99-sof-audio-no-runtime-pm.rules`: ```txt ACTION=="add|bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x8086", ATTR{device}=="0xa828", ATTR{power/control}="on" ``` Matching on the PCI ID `8086:a828` rather than the slot `0000:00:1f.3` keeps the rule valid if the device is ever renumbered. `add|bind` covers both device registration and driver bind. Apply it without rebooting: ```sh sudo udevadm control --reload sudo udevadm trigger --action=add /sys/bus/pci/devices/0000:00:1f.3 ``` Verify. `control` must read `on` and `runtime_status` must read `active`: ```sh cat /sys/bus/pci/devices/0000:00:1f.3/power/{control,runtime_status} ``` From this point `runtime_suspended_time` must stop increasing, with all further time accruing to `runtime_active_time`. If it keeps climbing, the pin is not actually holding: ```sh cat /sys/bus/pci/devices/0000:00:1f.3/power/runtime_suspended_time cat /sys/bus/pci/devices/0000:00:1f.3/power/runtime_active_time ``` Confirm the rule also applies on a fresh boot rather than only surviving the manual trigger: ```sh udevadm test --action=add /sys/bus/pci/devices/0000:00:1f.3 2>&1 | grep power/control ``` .box {This is a mitigation, not a fix} type:{warning} The driver defect is still present. The rule only stops it from being triggered. If the freezes return, bypass SoundWire entirely by forcing the legacy HDA driver in `/etc/modprobe.d/`: ```txt options snd-intel-dspcfg dsp_driver=1 ``` This costs the internal speakers and the internal microphone array, since both sit behind SoundWire (`rt1318` amplifiers and an `rt715` microphone). USB and HDMI/DisplayPort audio keep working. .box {Ruled out} type:{note} `power-profiles-daemon` is not the cause, despite the timing looking suspicious — most of the panics predate its installation. See [Power Profiles](003-power-profiles.qd). The hardware is fine too: no machine check exceptions, no ECC or EDAC errors, and `fwupdmgr` reports all firmware current. Capturing a fresh trace would need `efi_pstore.pstore_disable=0` on the kernel command line, which means creating `/etc/kernel/cmdline`, regenerating the unified kernel image and re-signing it. `CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE` is set, so panics are not persisted by default. ## Camera The camera, while available on free software and without drivers, produces a very bad, raw image with green tint. To have a higher quality, we need to install a custom intel driver. Install `linux-firmware-intel libcamera-tools dkms linux-headers intel-vision-drivers-dkms-git pipewire-libcamera`. Make sure that the `intel_cvs` kernel module (and dependency) is loaded: `/etc/modules-load.d/intel_cvs.conf`: ```txt gpio_ljca usb_ljca intel_cvs ``` After rebooting `cam -l` should show `1: Internal front camera (\_SB_.LINK1)` after some warnings. `qcam` should start a raw camera stream. The raw camera stream will have a greenish tint. > Note: The Intel Vision Driver module must already be loaded when the ov02c10 sensor is probed. > If you cannot see your camera, run `rmmod ov02c10` && `modprobe ov02c10` as root and try again. For Firefox, open about:config (See Firefox#Configuration) and set media.webrtc.camera.allow-pipewire to "True". For Chromium, enable the flag enable-webrtc-pipewire-camera in chrome://flags/ or set it in your configuration file. ### Proprietary Hardware Stack The proprietary hardware stack requires additional components to be installed and configured, but it provides substantially better video quality vs using only open source drivers and software. First ensure that the above steps are complete at least to the point where qcam shows a raw camera stream. Download `intel-ipu7-dkms-git` and modify the PKBUILD file. ```sh mkdir ~/.camera_driver cd ~/.camera_driver git clone https://aur.archlinux.org/intel-ipu7-dkms-git.git cd intel-ipu7-dkms-git nvim PKGBUILD ``` - remove the dependency `intel-ivsc-firmware` from the `depends` section. - Change `source=("git+${url}")` to instead point to a specific commit and add a patch file to it `source=("git+https://github.com/intel/ipu7-drivers.git#commit=77e3a0065697314cc7437a6eefd7e0d36ab06a4b" "https://patch-diff.githubusercontent.com/raw/intel/ipu7-drivers/pull/67.patch")` - Add another `'SKIP'` to `sha256sums` - In the `prepare()` section, apply the patch: `patch -Np1 -i ../67.patch` Here is the pkgfile ```sh # Maintainer: Yamada Hayao # Contributer: Karim Vergnes pkgname=intel-ipu7-dkms-git _pkgname=ipu7-drivers pkgver=r77.77e3a00 pkgrel=1 pkgdesc="Intel IPU7 camera drivers (DKMS)" arch=('any') url="https://github.com/intel/${_pkgname}" license=('unknown') depends=('dkms') provides=('intel-ivsc-driver-dkms-git' 'intel-ipu7-dkms') conflicts=('intel-ivsc-driver-dkms-git') makedepends=('git') source=("git+https://github.com/intel/ipu7-drivers.git#commit=77e3a0065697314cc7437a6eefd7e0d36ab06a4b" "https://patch-diff.githubusercontent.com/raw/intel/ipu7-drivers/pull/67.patch") sha256sums=('SKIP' 'SKIP') pkgver() { cd $_pkgname printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" } prepare() { cd "$srcdir/$_pkgname" patch -Np1 -i ../67.patch sed -i "s/^PACKAGE_VERSION=\".*\"$/PACKAGE_VERSION=\"$pkgver\"/g" ./dkms.conf } package() { cd "$srcdir" install -dm755 "$pkgdir/usr/src" cp -rT "$_pkgname" "$pkgdir/usr/src/$_pkgname-$pkgver" } ``` Run the package build and install - `makepkg --syncdeps` - `makepkg --install` Install `intel-ipu7-camera-hal-git` Download `icamerasrc-git` and modify the PKBUILD file. ```sh cd ~/.camera_driver git clone https://aur.archlinux.org/icamerasrc-git.git cd icamerasrc-git nvim PKGBUILD ``` - replace dpendency `ipu6-camera-hal` with `ipu7-camera-hal` Run the package build and install - `makepkg --syncdeps` - `makepkg --install` ### Config Files Make sure that the kernel modules load in the correct order Remove the file `/etc/modules-load.d/intel_cvs.conf`. Create the file `/etc/modprobe.d/90-ipu7-usbio-order.conf` with ```txt softdep intel_ipu7 pre: usbio gpio_usbio i2c_usbio intel_cvs intel_skl_int3472_discrete ``` Create the file `/usr/lib/udev/rules.d/90-ipu7-psys.rules` ```txt KERNEL=="ipu7-psys0", MODE="0666", SYMLINK+="ipu-psys0" ``` Reboot the system. Check that the camera is now working with ```sh gst-launch-1.0 -v icamerasrc ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! videoconvert ! videoflip method=rotate-180 ! waylandsink ``` ### V4L2 Relay Now, we can create a V4L2 loopback device that presents the gstreamer/icamerasrc stream when activated. Install `v4l2-relayd`. Create the following file to instantiate the virtual v4l2loopback device on boot: `/etc/modprobe.d/v4l2loopback.conf`: ```txt options v4l2loopback card_label="Intel IPU7 Virtual Camera" ``` Create the systemd service file for the relay. `/etc/v4l2-relayd.d/intel-ipu.conf` ```ini VIDEOSRC="icamerasrc device-name=ov02c10-uf ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! videoconvert ! videoflip method=rotate-180" FORMAT=NV12 WIDTH=1920 HEIGHT=1080 FRAMERATE=30/1 CARD_LABEL="Intel IPU7 Virtual Camera" ``` Next, enable the `v4l2-relayd@intel-ipu.service`. After restarting your machine, any supported applications should see your camera as a standard V4L2 device with wide support.