# Cameras on the Lenovo Duet 3 (`lenovo-wormdingler`) — TODO

The front and rear cameras do **not** work on the current Mobile NixOS image.
This file is a starting point for picking the work back up later, so we don't
have to re-diagnose from scratch.

## Current state (May 2026)

Empirical, taken on the running device:

```
$ uname -a
Linux ideapad 6.5.0 #1-mobile-nixos SMP Tue Jan  1 00:00:00 UTC 1980 aarch64 GNU/Linux

$ ls /dev/video*
/dev/video0   ← Qualcomm Venus video decoder (h.264/h.265 dec)
/dev/video1   ← Qualcomm Venus video encoder (h.264/h.265 enc)

$ ls /dev/media*                    # nothing — no media controller graph at all
$ lsmod | grep -i camss             # nothing
$ wpctl status | grep -A1 Sources   # nothing — PipeWire has no camera sources
```

Relevant kernel config bits in `/proc/config.gz` on the running image:

```
CONFIG_MEDIA_CAMERA_SUPPORT=y          ← media framework is on
# CONFIG_VIDEO_QCOM_CAMSS is not set   ← Qualcomm Camera Subsystem driver is OFF
# CONFIG_VIDEO_OV5675 is not set       ← every relevant sensor driver is OFF
# CONFIG_VIDEO_OV13858 is not set
# CONFIG_VIDEO_HI556 is not set
# (full grep of `VIDEO_OV*` / `VIDEO_HI*` is all `not set`)
```

So the *media framework* is enabled, but the *ISP driver* (CAMSS) and every
plausible sensor driver are off, and no out-of-tree modules are shipped. The
two `/dev/video*` nodes are the Venus codecs, not cameras — that's why
`snapshot` reports "no camera found."

## Why this is non-trivial

1. **Kernel rebuild required.** `mobile-nixos` builds its own kernel for this
   device (see `mobile.kernel.structuredConfig` in `hardware.nix`, where we
   already enable `CIFS` and `EXFAT_FS`). Adding camera support means adding:
   - `VIDEO_QCOM_CAMSS = module;`
   - The right sensor driver(s) — and we don't currently know which ones the
     Duet 3 actually uses. The `wormdingler` Chromium-OS DT references a pair
     of OV-series sensors but the exact part numbers can vary by SKU and
     production batch.
   - Their dependencies (`I2C`, `V4L2`, `MEDIA_CONTROLLER`, etc. — most are
     already pulled in by `MEDIA_CAMERA_SUPPORT`).

2. **Device-tree wiring.** Even with the drivers compiled in, the device tree
   has to describe the CCI bus, the sensor I²C addresses, the regulators, the
   reset/enable GPIOs, and the CSI port mapping. Mobile NixOS' DT for
   wormdingler may or may not include these nodes — needs verification by
   reading the upstream device file at
   `${inputs.mobile-nixos}/devices/lenovo-wormdingler/`.

3. **libcamera is the user-space side.** CAMSS is not a "single v4l2 device"
   driver — it exposes a media-controller graph that has to be configured by
   libcamera (per-sensor IPA, format negotiation, etc.). Apps then talk to
   libcamera via the `libcamerasrc` PipeWire module or directly. So the
   user-space stack is:
   - `pkgs.libcamera` (system-wide)
   - `pkgs.pipewire` already running, but needs the libcamera module enabled
     (`services.pipewire.libcamera = …` or equivalent — check current option
     name)
   - GUI: `snapshot`, `gnome-camera`, or anything that talks to PipeWire
     video sources.

## Investigation checklist

When picking this up again, do these in order:

1. **Identify the actual sensors.** The cleanest way:
   - Read the upstream Mobile NixOS device file for wormdingler
     (`devices/lenovo-wormdingler/default.nix` and any `.dts` overlays).
   - Cross-check with the Chromium OS overlay at
     <https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/refs/heads/main/overlay-trogdor/>
     and the upstream Linux DTS at
     `arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-*.dts`.
   - As a runtime cross-check, when CAMSS is eventually loaded, `dmesg | grep -i
     -E 'cci|sensor|isp'` will print the I²C probe attempts.

2. **Enable kernel options** in `modules/hosts/ideapad/hardware.nix` under
   `mobile.kernel.structuredConfig`:

   ```nix
   (helpers: with helpers; {
     VIDEO_QCOM_CAMSS = module;
     # plus whatever sensors step 1 identified, e.g.:
     # VIDEO_OV5675 = module;
     # VIDEO_OV13858 = module;
   })
   ```

   Cross-build on the 14900k via the existing flow (binfmt aarch64 + push back).
   Reboot, then check:

   ```
   ls /dev/media*                                  # expect at least /dev/media0
   sudo dmesg | grep -i -E 'camss|sensor|isp|cci'  # probe history
   sudo modprobe -v qcom-camss                     # if not auto-loaded
   ```

3. **Install diagnostic tools** for this round of work (do **not** keep these
   in the long-term config unless cameras actually work):

   ```nix
   environment.systemPackages = with pkgs; [
     v4l-utils       # provides v4l2-ctl, media-ctl
     libcamera       # provides `cam`, `qcam`
   ];
   ```

   Then:

   ```
   v4l2-ctl --list-devices
   media-ctl -p                # dumps the full media-controller graph
   cam -l                      # libcamera's view of available cameras
   ```

4. **Wire libcamera into PipeWire.** Once `cam -l` shows at least one camera,
   enable PipeWire's libcamera module (option name may have shifted; current
   nixpkgs typically has `services.pipewire.wireplumber.extraConfig` or
   similar). Then `wpctl status` should show new Sources under "Video", and
   `snapshot` will see them.

5. **Re-add a camera GUI** to `configuration.nix`. `snapshot` is the simplest
   touch-first option; `gnome-camera` and `cheese` are alternatives.

## Why nothing else is being touched right now

Steps 1–4 above are speculative — there's no guarantee the Duet 3 cameras have
working mainline-Linux sensor drivers at all. The conservative move is to
leave the config tablet-usable without them, document the dead end, and revisit
when there's time for a real spike.
