|
|
|
@@ -0,0 +1,414 @@
|
|
|
|
|
.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:
|
|
|
|
|
<TASK>
|
|
|
|
|
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
|
|
|
|
|
</TASK>
|
|
|
|
|
|
|
|
|
|
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. This alone is not sufficient — see "Docking re-arms it" below for the second
|
|
|
|
|
trigger this misses.
|
|
|
|
|
|
|
|
|
|
.box {Do not do this with udev} type:{warning}
|
|
|
|
|
A udev rule writing `ATTR{power/control}="on"` on `add|bind` looks like the obvious lever and
|
|
|
|
|
matches correctly — `udevadm test` confirms it fires for both actions — but it does not hold.
|
|
|
|
|
`snd_sof_pci` calls `pm_runtime_allow()` from `sof_pci_probe_complete()`, which runs *after* the
|
|
|
|
|
uevents udev hooks, so the driver reverts `power/control` to `auto` on every boot.
|
|
|
|
|
|
|
|
|
|
This cost five further panics between 2026-08-11 and 2026-08-20 while the rule sat in
|
|
|
|
|
`/etc/udev/rules.d/` looking like active protection.
|
|
|
|
|
|
|
|
|
|
Gate the driver instead. Bit 0 of `sof_pci_debug` (`SOF_PCI_DISABLE_PM_RUNTIME`) makes
|
|
|
|
|
`sof_pci_probe_complete()` return before it reaches the runtime PM setup, so there is no ordering to
|
|
|
|
|
lose:
|
|
|
|
|
|
|
|
|
|
```txt
|
|
|
|
|
sof_pci_probe_complete:
|
|
|
|
|
testb $0x1, sof_pci_debug ; skip the block entirely when bit 0 is set
|
|
|
|
|
je ...
|
|
|
|
|
pm_runtime_set_autosuspend_delay(dev, 0x7d0) ; 2000 ms
|
|
|
|
|
__pm_runtime_use_autosuspend(dev, 1)
|
|
|
|
|
pm_runtime_allow(dev) ; this is what reverts power/control to "auto"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`/etc/modprobe.d/99-sof-no-runtime-pm.conf`:
|
|
|
|
|
|
|
|
|
|
```txt
|
|
|
|
|
options snd_sof_pci sof_pci_debug=1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`snd_sof_pci` is not in the initramfs, so this needs no `mkinitcpio` run and no re-signing of the
|
|
|
|
|
unified kernel image. It takes effect on the next boot.
|
|
|
|
|
|
|
|
|
|
Close the window immediately on a running system, without waiting for a reboot:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
echo on | sudo tee /sys/bus/pci/devices/0000:00:1f.3/power/control
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Check the ratio after a fresh boot, not just the manual write. Unmitigated, the controller spends
|
|
|
|
|
around 90% of uptime suspended and cycles constantly rather than settling — roughly 30 seconds of
|
|
|
|
|
active time accrues in the first 8 minutes, so the race window is being re-entered continuously:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
awk '{printf "suspended %d%%\n", 100*$1/($1+$2)}' \
|
|
|
|
|
<(paste /sys/bus/pci/devices/0000:00:1f.3/power/runtime_{suspended,active}_time)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Docking re-arms it
|
|
|
|
|
|
|
|
|
|
Pinning the PCI controller is not the end of it. A panic on 2026-08-21 happened with `sof_pci_debug=1`
|
|
|
|
|
active and `runtime_suspended_time` flat at `0` for the whole session — the PCI-level fix was
|
|
|
|
|
verified working right up to the crash. What was different: the Dell U2724DE dock had been unplugged
|
|
|
|
|
and replugged 72 minutes earlier.
|
|
|
|
|
|
|
|
|
|
The dock's DP monitors drive an ASoC card-level jack/ELD reconfiguration on every replug — this is
|
|
|
|
|
card-wide, not SoundWire-specific, since the internal speakers and the DP outputs share the same
|
|
|
|
|
`sof-soundwire` ALSA card. That reconfiguration independently resumes whichever SoundWire links the
|
|
|
|
|
card touches. Confirmed by sampling `runtime_active_time` across a reproduced replug: `link.1` and
|
|
|
|
|
`link.2` (the two `rt1318` speaker amps) went from suspended-and-static to active and climbing within
|
|
|
|
|
under a minute, while `link.0` (the unused `rt715` mic) stayed suspended throughout. Boot alone never
|
|
|
|
|
produces this — every link starts out uniformly suspended and stays that way until something asks for
|
|
|
|
|
audio.
|
|
|
|
|
|
|
|
|
|
That asymmetric state — some links live and taking interrupts, one still parked — is exactly the
|
|
|
|
|
precondition `sdw_intel_thread`'s walk over `cdns == NULL` needs. The PCI-level pin has no visibility
|
|
|
|
|
into it, because it only prevents the *controller* from ever entering runtime PM; the link and codec
|
|
|
|
|
devices underneath are separate PM domains that a jack event can wake regardless.
|
|
|
|
|
|
|
|
|
|
Pinning those nine devices individually with a udev `add|bind` rule would repeat the mistake already
|
|
|
|
|
made once with the PCI controller: it would look correct and might still be silently reverted by a
|
|
|
|
|
driver-internal call this doc hasn't found. Instead, assert the invariant repeatedly rather than trust
|
|
|
|
|
a single write to hold:
|
|
|
|
|
|
|
|
|
|
`/usr/local/bin/pin-sof-soundwire-pm.sh` walks the PCI device, its three `soundwire_intel.link.*`,
|
|
|
|
|
their `sdw-master-*` children, and every `/sys/bus/soundwire/devices/sdw:*` codec, writing `on` to
|
|
|
|
|
`power/control` wherever it isn't already set. It's idempotent and only logs when it actually changes
|
|
|
|
|
something.
|
|
|
|
|
|
|
|
|
|
`/etc/systemd/system/pin-sof-soundwire-pm.timer` runs it every 15 seconds, forever, so any revert this
|
|
|
|
|
doc hasn't identified self-heals within one tick regardless of the mechanism:
|
|
|
|
|
|
|
|
|
|
```txt
|
|
|
|
|
[Timer]
|
|
|
|
|
OnBootSec=10s
|
|
|
|
|
OnUnitActiveSec=15s
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`/etc/udev/rules.d/99-sof-soundwire-links-pm.rules` reasserts it immediately on the dock's own
|
|
|
|
|
Thunderbolt hotplug event, closing the gap between replug and the next timer tick, since the risky
|
|
|
|
|
moment is the resume race itself:
|
|
|
|
|
|
|
|
|
|
```txt
|
|
|
|
|
ACTION=="add", SUBSYSTEM=="thunderbolt", ATTR{vendor}=="0xd4", ATTR{device}=="0xc045", \
|
|
|
|
|
TAG+="systemd", ENV{SYSTEMD_WANTS}+="pin-sof-soundwire-pm.service"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
.box {Use `+=`, not `=`, for `SYSTEMD_WANTS`} type:{warning}
|
|
|
|
|
`/usr/lib/udev/rules.d/90-bolt.rules` already sets `ENV{SYSTEMD_WANTS}+="bolt.service"` on the
|
|
|
|
|
same `thunderbolt` subsystem. A first draft of this rule used `=` instead of `+=`; being numbered
|
|
|
|
|
`99-` it loaded after bolt's rule and silently clobbered it, so every dock replug stopped
|
|
|
|
|
requesting `bolt.service` at all. `udevadm test --action=add /sys/bus/thunderbolt/devices/1-1`
|
|
|
|
|
catches this — check the merged `SYSTEMD_WANTS` line lists both services, not just one.
|
|
|
|
|
|
|
|
|
|
Update the Thunderbolt vendor/device match if the dock is ever replaced:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cat /sys/bus/thunderbolt/devices/*/vendor /sys/bus/thunderbolt/devices/*/device \
|
|
|
|
|
/sys/bus/thunderbolt/devices/*/device_name
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Verify all nine devices are pinned:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
for d in /sys/bus/pci/devices/0000:00:1f.3 /sys/bus/pci/devices/0000:00:1f.3/soundwire_intel.link.* \
|
|
|
|
|
/sys/bus/pci/devices/0000:00:1f.3/soundwire_intel.link.*/sdw-master-* \
|
|
|
|
|
/sys/bus/soundwire/devices/sdw:*; do
|
|
|
|
|
printf '%-70s %s\n' "$d" "$(cat "$d/power/control")"
|
|
|
|
|
done
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Recognising it after the fact
|
|
|
|
|
|
|
|
|
|
The panic leaves nothing behind, so identify it by shape rather than by trace. `CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE`
|
|
|
|
|
is set and no pstore backend is registered, so `/sys/fs/pstore` and `/var/lib/systemd/pstore` are
|
|
|
|
|
both empty after a hang.
|
|
|
|
|
|
|
|
|
|
A crashed boot ends mid-heartbeat with no shutdown sequence. Compare the last line of each boot: a
|
|
|
|
|
clean shutdown ends in `Unmounted /efi` or `Stopping Flush Journal to Persistent Storage`, while a
|
|
|
|
|
panic ends on whatever was logging periodically — usually `kdeconnectd`, exactly on its 30-second
|
|
|
|
|
cadence, with the next tick missing:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
for b in $(journalctl --list-boots -q | awk '{print $1}'); do
|
|
|
|
|
printf "%4s %s\n" "$b" "$(journalctl -b "$b" -o short-iso -q | tail -1)"
|
|
|
|
|
done
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The machine is always idle when it dies, not under load, and the journal is silent on the kernel side
|
|
|
|
|
for the entire session — `journalctl -b -1 -k -p 4` shows only the usual boot-time noise.
|
|
|
|
|
|
|
|
|
|
.box {This is a mitigation, not a fix} type:{warning}
|
|
|
|
|
The driver defect is still present. Disabling runtime PM 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.
|
|
|
|
|
|
|
|
|
|
The battery charge-controller fault is a separate problem and not the cause of these hangs. It
|
|
|
|
|
presents the same way from the outside — the machine dies with no clean shutdown and nothing in
|
|
|
|
|
the journal — so check it off explicitly. In a SoundWire panic the battery is untouched
|
|
|
|
|
(`charge_now == charge_full` on the next boot) and `battery-charge-watchdog` logs only its
|
|
|
|
|
startup line, never a `FAULT`.
|
|
|
|
|
|
|
|
|
|
The two did co-occur on 2026-08-21 — the fault fired for 101 minutes that morning, resolving
|
|
|
|
|
itself 8 seconds before the dock was unplugged, with the panic following 72 minutes later — but
|
|
|
|
|
the mechanisms are unrelated. Same dock event, two independent bugs.
|
|
|
|
|
|
|
|
|
|
A dock replug on the same day also reproduced `pcieport 0000:39:00.0: not ready 1023ms after
|
|
|
|
|
resume; giving up`. Not yet investigated; noted here since it fires on the same trigger as the
|
|
|
|
|
SoundWire re-arm above and could be mistaken for a symptom of it.
|
|
|
|
|
|
|
|
|
|
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 <shun819.mail@gmail.com,>
|
|
|
|
|
# Contributer: Karim Vergnes <me@thesola.io>
|
|
|
|
|
|
|
|
|
|
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.
|