# The webcam on a Dell XPS 14 (Panther Lake) under Kubuntu 26.04

> The XPS 14's ov08x40 webcam just doesn't show up on Kubuntu 26.04. Four things were in the way - a missing CVS driver, missing camera packages, browsers grabbing the raw IPU7 devices, and a sensor mode that crashes PipeWire. A small GStreamer relay gives the browsers one camera that works.

Guide · Published 2026-11-04 · Updated 2026-11-04  
Web page: https://blog.jacq.cc/guides/xps-14-panther-lake-webcam-linux/

The webcam on my Dell XPS 14 (DA14260, Intel Panther Lake) didn't work on Kubuntu 26.04. No camera in the browser, and nothing in `cam -l` either.
So this is how I got it going - one missing kernel driver, a few packages, and a small relay that works around a sensor bug.

[Image: A drawing: a laptop with its webcam glowing green, a camera window with a green tick and a Built-in Camera label on the screen, a green ribbon cable from the webcam to a blue IPU7 chip, and a crossed-out No sensor found tag]

:::note[Status, November 2026]
Kubuntu 26.04, kernel 7.0.0-42-generic, libcamera 0.7.0, KDE Plasma 6.6, BIOS 1.12.0. Works in Brave and Edge at 1280×720 and 29 fps, upright and with neutral colours. The picture's a bit grainy in office light. And the relay only runs when I turn it on.
:::

## How the camera is wired

Before fixing anything I wanted to know what talks to what. On this laptop it's a lot more parts than I expected 😅

[Image: How the camera is wired: the ov08x40 sensor sends pictures over two MIPI CSI-2 lanes through Intel's CVS chip to the IPU7 in the Panther Lake chip; its settings go over an I2C bus from a Synaptics SVP7500 USB-IO bridge, which also switches power, reset and the privacy LED, and talks to the Panther Lake chip over USB]

- ov08x40 - the 8 MP sensor at the top of the screen. Sends raw pictures over two MIPI CSI-2 lanes
- IPU7 - Intel's camera block inside the Panther Lake chip. Its input part (ISYS) takes the raw frames and writes them to memory, and that's it. It doesn't make a colour picture, that's left to software
- Intel CVS chip - sits between the sensor and the IPU7. It can use the camera on its own (for presence detection), so it hangs on to the sensor until a driver asks for it
- Synaptics SVP7500 - a USB-IO bridge. The sensor's settings go over an I2C bus that belongs to this bridge, so they actually travel over USB. Its GPIO pins switch the sensor's power, reset and privacy LED. And the CVS chip and the Windows Hello IR sensor are on the same I2C bus as well

[Image: An ov08x40 camera module: a small dark square block with a lens in the middle, joined by a short orange flex cable to a long connector strip]

That's an ov08x40 module like the one in the lid - the sensor and lens in the square block, and a flex cable to the connector, which carries the MIPI lanes, the I2C bus and power.

The Synaptics bridge shows up in `lsusb` as `06cb:0701 Synaptics, Inc. SVP7500`, and the sensor sits under it:

```bash
readlink -f /sys/bus/i2c/devices/i2c-OVTI08F4:00
# /sys/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3:1.0/usbio.usbio-i2c.1/i2c-13/i2c-OVTI08F4:00
```

## What was wrong

Four separate problems, and each one was hiding behind the one before:

1. No `intel_cvs` driver. Without it the CVS chip never lets go of the sensor, so the kernel never creates it
2. No camera software - libcamera's tools and its PipeWire and GStreamer plugins weren't installed
3. Brave and Edge opened the 32 raw IPU7 capture devices, which never give a picture
4. PipeWire crashes below 2560×1440. The sensor's smaller mode sends broken frames, and libcamera aborts on them

## What you need

| Part | Notes |
| --- | --- |
| Dell XPS 14 DA14260 | Or another Panther Lake laptop with an ov08x40 behind a CVS chip. Check `ls /sys/bus/i2c/devices/` for `i2c-OVTI08F4:00` and `i2c-INTC10E1:00` |
| Kubuntu 26.04 | Ubuntu's 7.0 kernel. Other Ubuntu 26.04 flavours should work the same, I guess |
| sudo | For the packages |

## Step 1: Download the files

Grab them all in one go:

```bash
mkdir xps-14-webcam && cd xps-14-webcam
for f in setup-root.sh install.sh camera-relay.service camera-relay.sh camera-relay.desktop 51-camera-relay.conf ov08x40.yaml; do
  curl -fsSO https://blog.jacq.cc/xps-14-webcam/$f
done
```

Seven files: [setup-root.sh](https://blog.jacq.cc/xps-14-webcam/setup-root.sh) and [install.sh](https://blog.jacq.cc/xps-14-webcam/install.sh) set everything up, the other five are what they install. MIT licence ([LICENSE](https://blog.jacq.cc/xps-14-webcam/LICENSE)).

## Step 2: The CVS driver and the camera packages

The kernel loads the camera drivers in a chain, and each one waits for the one above it. On a fresh Kubuntu 26.04 the chain just stops at `intel_cvs`:

[Image: What has to load before the camera shows up: usbio, then int3472-discrete, then intel_cvs, which was missing, then ov08x40, then intel_ipu7_isys]

`intel_cvs` isn't in Ubuntu's normal kernel modules - it's in a separate signed package, `linux-modules-vision-generic`. Without it, the IPU7 driver knows about the sensor from ACPI (`OVTI08F4:00`) but never actually gets one, and `cam -l` says `No sensor found for /dev/media0`.

```bash
bash setup-root.sh
```

It asks for the sudo password and installs:

- `linux-modules-vision-generic`: the CVS driver
- `libcamera-tools`, `libspa-0.2-libcamera`, `gstreamer1.0-libcamera`: libcamera, its `cam` tool and its PipeWire and GStreamer plugins
- `gstreamer1.0-tools`, `gstreamer1.0-pipewire`: `gst-launch-1.0` and `pipewiresink` for the relay

It ends with 🟢 SUCCESS. If it says `intel_cvs not loaded yet`, reboot. Then have a look at the kernel log:

```bash
journalctl -k -b | grep -E 'ownership|bind ov08x40'
```

```text
Intel CVS driver i2c-INTC10E1:00: cvs_common_probe:Transfer of ownership success
intel_ipu7_isys.isys intel_ipu7.isys.40: bind ov08x40 13-0036 nlanes is 2 port is 0
```

Then ask libcamera:

```bash
cam -l
```

Only the end of the output matters. Here's mine, with the timestamps cut:

```text
INFO Camera camera_manager.cpp:340 libcamera v0.7.0
ERROR V4L2 v4l2_subdevice.cpp:1201 'ov08x40 13-0036': Unable to get rectangle 2 on pad 0/0: Inappropriate ioctl for device
WARN CameraSensor camera_sensor_legacy.cpp:402 'ov08x40 13-0036': The PixelArraySize property has been defaulted to 3856x2176
...
WARN CameraSensor camera_sensor_legacy.cpp:427 'ov08x40 13-0036': The sensor kernel driver needs to be fixed
WARN CameraSensorProperties camera_sensor_properties.cpp:548 No static properties available for 'ov08x40'
WARN IPAProxy ipa_proxy.cpp:192 Configuration file 'ov08x40.yaml' not found for IPA module 'simple', falling back to '/usr/share/libcamera/ipa/simple/uncalibrated.yaml'
WARN IPASoft soft_simple.cpp:104 IPASoft: Failed to create camera sensor helper for ov08x40
INFO Camera camera_manager.cpp:223 Adding camera '\_SB_.LNK1' for pipeline handler simple
Available cameras:
1: Internal front camera (\_SB_.LNK1)
```

The `ERROR` and `WARN` lines look bad, but the camera works with all of them:

- "Unable to get rectangle" - the ov08x40 driver doesn't report its crop areas, so libcamera fills in the full 3856×2176 sensor size
- "No static properties" and no sensor helper - libcamera has no entry for this sensor, so it guesses its timings and gain
- "ov08x40.yaml not found" - `cam` doesn't know about the tuning file from [Step 5](#step-5-fix-the-picture). Only the relay passes it in

At boot the log also shows a whole bunch of `int3472-discrete … cannot find GPIO chip INTC10E2:00, deferring`. They look like the problem, but they're harmless: `INTC10E2` is the USB-IO bridge's GPIO chip, and it turns up a moment later.

`ubuntu-drivers` also suggests `intel-ipu7-dkms`. You don't need it - it adds modules for Intel's own camera stack, not libcamera.

## Step 3: Why PipeWire's own camera crashes

With the sensor there, PipeWire shows a libcamera camera straight away. And it works at full size. But as soon as a browser asks for 640×480 or 1280×720, PipeWire crashes.

[Image: Why the relay always asks for 2560×1440: a request for 1280×720 picks the binned 1928×1088 mode, whose pixel values are broken, the histogram overflows and PipeWire crashes; a request for 2560×1440 keeps the sensor in its full 3856×2176 mode with clean values, and the relay scales that to 1280×720]

For anything up to 1920×1080, libcamera switches the sensor to its binned 1928×1088 mode. In that mode the raw frames are broken: 2,121,824 of 2,123,776 pixel values were above 1023, the most a 10-bit pixel can hold. So pretty much every pixel. The full 3856×2176 mode is clean. The broken values overflow a 64-bin histogram in libcamera's software ISP, and Ubuntu's hardened build aborts on that.

I tested it with `cam`: 640×480, 1280×720, 1920×1080 and 1924×1088 crash. 2560×1440, 3840×2160 and 3848×2176 work.
I think it's a bug in the kernel's `ov08x40` driver for the binned mode. I haven't found a report of it.

So the fix - never let anything ask for less than 2560×1440, and scale down afterwards.

## Step 4: The relay

The relay is just one GStreamer pipeline, run by a systemd user service. It reads 2560×1440 from libcamera, scales it to 1280×720, and offers that to PipeWire as a camera called "Built-in Camera".

[Image: The relay, from sensor to browser: the sensor and IPU7 deliver raw frames, libcamera's soft-ISP makes the colour picture on the GPU with statistics on the CPU, GStreamer scales to 1280×720 on the CPU, and PipeWire offers it as Built-in Camera to Brave and Edge]

The main bit of [camera-relay.service](https://blog.jacq.cc/xps-14-webcam/camera-relay.service):

```text
gst-launch-1.0 -e libcamerasrc saturation=1.3 \
  ! video/x-raw,width=2560,height=1440 \
  ! videoconvertscale n-threads=4 \
  ! video/x-raw,format=YUY2,width=1280,height=720,framerate=30/1 \
  ! pipewiresink mode=provide client-name=camera-relay \
    'stream-properties="props,media.class=Video/Source,media.role=Camera,node.name=camera-relay,node.description=\"Built-in Camera\""'
```

- `libcamerasrc` asks for 2560×1440, which keeps the sensor in its full mode
- `videoconvertscale` scales on the CPU, with 4 threads
- `pipewiresink mode=provide` makes the relay a PipeWire camera. It offers one fixed format, and that matters: Brave and Edge skip a PipeWire camera that only lists size ranges, with `NotFoundError: Requested device not found`. My first try used a `v4l2loopback` device, and it failed for exactly that reason

Install it:

```bash
bash install.sh
```

It installs the service, the colour tuning file ([Step 5](#step-5-fix-the-picture)), the WirePlumber rules ([Step 6](#step-6-get-the-browsers-to-use-it)), a `camera-relay` command in `~/.local/bin`, and a KDE menu entry "Camera Relay (on/off)". Then turn it on:

```bash
camera-relay start
```

[Image: The KDE application menu with Camera Relay (on/off) among the favourites, next to Edge, Brave and VS Code. Its tooltip reads: Turn the built-in camera on or off for browsers and video calls]

Each start or stop pops up a notification:

[Image: Two KDE notifications from Camera relay: a green dot with Camera relay on, and a red dot with Camera relay off]

`camera-relay stop` turns it off, and `camera-relay toggle` (or the menu entry) flips it. While it runs, the privacy LED is on and the relay uses about 56 % of one CPU core. So I turn it off after a call.

## Step 5: Fix the picture

The first picture had a yellow-green cast. libcamera has no tuning for this sensor, so it falls back to `uncalibrated.yaml`, and on mine blue came out about 13 % low. [ov08x40.yaml](https://blog.jacq.cc/xps-14-webcam/ov08x40.yaml) fixes that:

```yaml
algorithms:
  - BlackLevel:
      blackLevel: 4096   # ov08x40: 64 at 10 bit, in libcamera's 16-bit scale
  - Awb:
  - Ccm:
      ccms:
        - ct: 6500
          ccm: [ 1.0, 0,    0,
                 0,   0.92, 0,
                 0,   0,    1.28 ]
  - Adjust:
  - Agc:
```

The service passes it in with `LIBCAMERA_SIMPLE_TUNING_FILE`. The colour matrix cuts green a little and lifts blue. I tuned it by eye in office light, so other light might want other numbers. Edit `~/.config/camera-relay/ov08x40.yaml`, then `camera-relay stop` and `camera-relay start`.

On [webcamtests.com](https://webcamtests.com), the average colour of the picture went from a hue of 75° (yellow-green) and 15.75 % saturation to under 1 %, so a neutral grey. The picture and the result below are with the tuning file, and that run gave 0.52 %.

[Image: The camera pointed at a white painted block wall in an office, with a desk chair and a monitor at the bottom right. The wall comes out a neutral white]

[Image: The webcamtests.com result panel: Built-in Camera, 1280×720 at 29 FPS, average colour a neutral grey, saturation 0.52 %]

### Saturation and contrast

`libcamerasrc` takes `saturation` and `contrast` (1.0 is no change). The relay runs with `saturation=1.3` for a bit more colour.
The catch: the colour matrix has to be in the tuning file for saturation to do anything - with `uncalibrated.yaml` it had no effect. Contrast works the same way, and I've left it at 1.0 for now. To try other values, edit the `ExecStart` line in `~/.config/systemd/user/camera-relay.service`:

```text
gst-launch-1.0 -e libcamerasrc saturation=1.3 contrast=1.1 ! ...
```

Then `systemctl --user daemon-reload` and restart the relay.

Manual exposure, gain and colour gains do nothing on this sensor. `libcamerasrc` accepts them and the picture just doesn't change. libcamera logs `Failed to create camera sensor helper for ov08x40` - it has no gain model for it.

### Upside down

The sensor is mounted upside down in the lid. libcamera knows that from ACPI and sets the sensor's own flip bits, so the picture comes out upright with no `videoflip` in the pipeline.

Once, the picture showed upside down in Edge, which was weird. After a `camera-relay stop` and `camera-relay start` it was upright again, and I haven't seen it since. I don't know what caused it.
If it happens to you, restart the relay before you add a `videoflip method=rotate-180` - with the flip bits set as well, that would turn a good picture upside down.

## Step 6: Get the browsers to use it

Chromium-based browsers only look for PipeWire cameras with an option turned on. Without it they open the raw IPU7 devices and get nothing.

[Image: How a browser finds the camera: with the option off, Brave or Edge opens the 32 raw ipu7 devices and gets no picture; with the PipeWire camera option on, it asks the camera portal, KDE asks once, and PipeWire hands over the relay's Built-in Camera. WirePlumber rules hide the raw devices and turn off PipeWire's own libcamera camera]

[51-camera-relay.conf](https://blog.jacq.cc/xps-14-webcam/51-camera-relay.conf) is a WirePlumber rule that turns off PipeWire's own libcamera camera (the one that crashes) and hides the 32 raw `ipu7` devices. `install.sh` puts it in `~/.config/wireplumber/wireplumber.conf.d/` and restarts WirePlumber.

Brave - paste this into the address bar, set "PipeWire Camera support" to "Enabled", and click "Relaunch":

```text
brave://flags/#enable-webrtc-pipewire-camera
```

Edge has the same option, but `edge://flags` doesn't show it. So `install.sh` turns it on from the command line instead. It writes a copy of Edge's launcher to `~/.local/share/applications/microsoft-edge.desktop` with this added to the `Exec=` line:

```text
--enable-features=WebRtcPipeWireCamera
```

KDE uses that copy instead of the system launcher. It only kicks in when Edge starts fresh, so quit it first with "⋯ → Close Microsoft Edge", then start it from the menu.
Running `microsoft-edge --enable-features=…` while Edge is open doesn't work - it just opens a new window in the running Edge, without the option.

To check it worked, open `edge://version` and look for `WebRtcPipeWireCamera` in the "Command-line" row.

The first time a site asks for the camera, KDE asks "Allow Apps to Use the Camera?" - click OK.

If PipeWire restarts or crashes while the browser's open, restart the browser too. Otherwise it hangs on to a dead camera.

## Watch out for

- BIOS updates - someone with the same model on BIOS 1.12.0 gets no frames at all ([omarchy #16792](https://github.com/omacom/omarchy/issues/16792)). Mine works on 1.12.0, so I'm not sure what's different. Check the camera after a BIOS update
- Suspend - on the XPS 16 the sensor is gone after a suspend ([omarchy #10624](https://github.com/omacom/omarchy/issues/10624)). I haven't seen it on mine yet. If it happens, reboot
- Grain - in office light the auto-exposure runs the sensor near its longest exposure at about 10× gain, so the picture's noisy. The binned mode would collect more light per pixel, but that's the broken one
- The GPU - the software ISP runs on the GPU. I've had one KDE graphics hang while the relay ran. KDE hangs on this laptop without the camera too, so I don't know yet if it's related
- Apps that read `/dev/video*` directly (not through PipeWire) don't see the relay

When a kernel or libcamera update fixes the binned mode, the relay can go - just delete the WirePlumber rule and PipeWire's own camera comes back.

## Undo

```bash
camera-relay stop
rm ~/.config/systemd/user/camera-relay.service \
   ~/.config/wireplumber/wireplumber.conf.d/51-camera-relay.conf \
   ~/.local/bin/camera-relay \
   ~/.local/share/applications/camera-relay.desktop \
   ~/.local/share/applications/microsoft-edge.desktop
systemctl --user daemon-reload
systemctl --user restart wireplumber
```

## Sources

- [omarchy #10948](https://github.com/omacom/omarchy/issues/10948): ov08x40 missing from the media graph on the XPS 14 DA14260
- [intel/vision-drivers #36](https://github.com/intel/vision-drivers/issues/36): `intel_cvs` needed for IPU7 on Panther Lake
- [CachyOS #804](https://github.com/CachyOS/linux-cachyos/issues/804): IPU7 camera on a Panther Lake Dell XPS
- [omarchy #16792](https://github.com/omacom/omarchy/issues/16792): XPS 14 DA14260 on BIOS 1.12.0, no frames
- [Debian bug #1147085](https://bugs.debian.org/1147085): the CVS driver is in Linux 7.2

## Change history

- 2026-11-04: First published.

Licence: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Credit "HomeLab Series (blog.jacq.cc)" with a link to https://blog.jacq.cc/guides/xps-14-panther-lake-webcam-linux/. Code downloads: MIT. Details: https://blog.jacq.cc/licence/
