Fixes the camera on Xiaomi Redmi Note 9 Pro (joyeuse) and other SM7125 (Atoll) phones running postmarketOS / mainline Linux. Upstream qcom-camss ships a malformed CSIPHY v1.2.2 lane register table — sensors stream, but no frames reach /dev/video0. This swaps the table and adds the two missing PHY-enable writes.
After install: GNOME Snapshot opens the front camera, shows live preview, captures photos and records video.
Boot into your phone, then:
KREL=$(uname -r)
[ "$KREL" = "6.14.7-sm7125" ] || { echo "wrong kernel: $KREL"; exit 1; }
# fetch + verify
curl -fLO https://github.com/asidko/qcom-camss-mainline/releases/latest/download/qcom-camss.ko
strings qcom-camss.ko | grep '^vermagic' # must contain: 6.14.7-sm7125
# backup + install
KO=/lib/modules/$KREL/kernel/drivers/media/platform/qcom/camss/qcom-camss.ko
sudo cp "$KO" /root/qcom-camss.ko.orig
sudo install -m644 qcom-camss.ko "$KO"
sudo depmod -a "$KREL"
sudo rebootOr one-shot:
curl -fL https://github.com/asidko/qcom-camss-mainline/releases/latest/download/install.sh | sudo bash
sudo rebootOpen Snapshot (GNOME's camera app). Live preview, photos, video capture all work.
ls /dev/media0 /dev/video0 # both should exist
sudo dmesg | grep camss # no -ENXIO errorssudo install -m644 /root/qcom-camss.ko.orig \
/lib/modules/$(uname -r)/kernel/drivers/media/platform/qcom/camss/qcom-camss.ko
sudo depmod -a && sudo rebootThe patch never touches /boot, DTBs, or any persistent device state. Rollback is byte-clean.
The driver leaks IRQ state on hot reload (modprobe -r then modprobe fails with IRQ csiphy0 not found — even the original .ko). Cold boot avoids it. Build off-device, then reboot once.
- Patch 1 (
patches/0001-…): replaceslane_regs_sc7180[5][23]with the verbatim v1.2.2 2-phase table from downstreamcam_csiphy_1_2_2_hwreg.h::csiphy_2ph_v1_2_2_reg[5][19]. - Patch 2 (
patches/0002-…): addsCTRL0 = 0x02(v1.2.2 PHY-enable) andCTRLn(33) = 0x01(terminator strobe) tocsiphy_lanes_enable(). v0.2.0: provenance comment expanded with downstream source citations + cross-rev context (v1.2.1 sm8250 / v1.2.3 sm6350 packaging). - Patch 3 (
patches/0003-…) (v0.2.0+): clears staleoutput->buf[]references and resets gen2active_numinvfe_flush_buffers(). Defensive fix: closes a use-after-recycle hazard reachable from the STREAMON-rollback path (next probe tripsWARN_ONatvideobuf2-core.c:1187). Not reachable on normal-path STREAMON/STREAMOFF; only fires when a failing STREAMON walks the flush path. Gated to gen2 VFE variants (VFE-170 / VFE-480) to avoid corrupting the gen1 union arm.
Background, register-level breakdown, and silicon ID details: docs/DESIGN_DECISIONS.md.
For any kernel other than 6.14.7-sm7125 you must rebuild against your tree. Full recipe (including Docker + OrbStack tuning for macOS hosts): docs/BUILD_FROM_SOURCE.md.
- Xiaomi Redmi Note 9 Pro (
joyeuse, Snapdragon 720G / SM7125) - postmarketOS edge,
linux-postmarketos-qcom-sm7125 6.14.7-r0 - Sensors: OV16A1Q (16 MP front, 4-lane D-PHY) + S5K5E9 (5 MP macro, 2-lane D-PHY)
- GNOME 47 + Snapshot 50
Should apply to other Atoll-family devices (curtana, gram) — silicon and DT are family-shared. Untested.
Downstream register tables: MiCode/Xiaomi_Kernel_OpenSource@curtana-q-oss. Upstream driver: Linaro (Robert Foss, Todor Tomov, Bryan O'Donoghue).
GPL-2.0-only. See LICENSE.