It’s been a while since i was actively following this thread and playing around with the x1e laptop.
Anyone know what the most up to date kernel source currently is?
It’s been a while since i was actively following this thread and playing around with the x1e laptop.
Anyone know what the most up to date kernel source currently is?
May depend on model, mine is 7.2.0-jg-0. Running it on sc8280xp, x1p, x1e,mainly Lenovo.
you got the url for source code?
Surface Pro 11.
LLM = glm-5.2
Today I tried to get the front camera on the SP11 working but after an hour or so of reboots etc it just wasn’t reliable.
For future reference and if anyone wants to try again with it here are the notes of what did and didn’t work and why it ultimately failed.
Repo owners referenced are:
jglathe
karsies-wq
================================================================
SP11 IMX681 front camera — summary of work
Machine: Microsoft Surface Pro 11th Edition (OLED), Snapdragon X1E
Kernel: 7.2-rc5-jg-0sp11v3-qcom-x1e (jglathe linux_ms_dev_kit)
Date: 2026-08-18
Source: https://github.com/karsies-wq/sp11-imx681-linux
Status: ABANDONED — C-PHY link not reliable across reboots/temperature
================================================================
0. THE GOAL
-----------
Enable the Sony IMX681 front camera as a webcam under Linux on the
ARM Snapdragon Surface Pro 11. The camera is MIPI C-PHY (not USB
UVC), wired to CSIPHY2/trio0 on the x1e80100 SoC.
1. WHAT WAS TRIED
-----------------
Full bring-up using the karsies-wq/sp11-imx681-linux repo, which
provides:
- Out-of-tree phy-qcom-mipi-csi2.ko (C-PHY receive path)
- Out-of-tree qcom-camss.ko (csid-680/vfe-680 bug fixes + crop)
- Out-of-tree ccs.ko (CCS generic sensor driver with IMX681
init/mode tables + static sensor data firmware)
- A patched UKI DTB with camera nodes wired for C-PHY on
CSIPHY2/trio0
- libcamera tuning yamls (factory CCMs from Windows CAMX blob)
- systemd units for boot-time module loading + privacy LED
- PipeWire drop-in (MemoryDenyWriteExecute=no for llvmpipe JIT)
Steps performed:
a. Cloned the repo, built all three modules against the running
kernel headers.
b. Fixed a missing ccs-pll.h header (fetched from mainline).
c. Installed modules to /lib/modules/.../updates/, ran depmod.
d. Created /etc/modprobe.d/sp11-camera.conf with C-PHY params
(force_cphy=1, cphy_trio=0, cphy_rate=0, cphy_cdr=0x4a,
imx681_cphy=1, imx681_windows=1).
e. Installed CCS static sensor data firmware
(/lib/firmware/ccs/ccs-sensor-4260-0681-0010.fw) to fix four
broken limit registers on the IMX681.
f. Baked modprobe.d into the initramfs so force_cphy applies at
early boot.
g. Patched the UKI kernel image DTB in-place (the EFI stub
ignores external DTBs).
h. Installed libcamera tuning yamls, scripts, systemd units.
i. Rebooted and verified.
Post-reboot debugging (two sessions):
j. Confirmed modules load with correct params, ccs binds to the
sensor, /dev/media0 + /dev/video0 appear, libcamera enumerates
"Internal front camera".
k. Found and cleared the ccs boot-race (PLL calculator overflows
a link-freq limit at first probe; reloading ccs fixes it).
l. Discovered the smiapp scaler subdev pins to 3840x2160 when
imx681_windows=Y (ccs-core.c:2404), not 3844x2640 as the
camera-start.sh script assumes. Fixed by using 3840x2160.
m. Ran CDR sweeps (0x00-0x6a) and AFE rate sweeps (0-3) to find
a working receive configuration.
n. Read CSIPHY/CSID status registers during streaming to get
the real packet count (dmesg "TOTAL_PKTS" reads the wrong
register offset).
2. WHAT WORKED
--------------
- Module build and install: all three modules compiled and loaded.
- DTB patch: camera nodes enabled in the UKI, sensor detected.
- ccs sensor bind: IMX681 on i2c bus 3, address 0x10, bound.
- Device nodes: /dev/media0, /dev/video0 created.
- libcamera enumeration: "Internal front camera" listed by
`cam --list`.
- Sensor I2C: all 429 register writes succeed, no I2C errors.
- Sensor streaming: the ccs driver writes MODE_SELECT=STREAMING
and the sensor begins transmitting C-PHY data.
- C-PHY PHY: CSIPHY2 3PH HW Version 0x40010000 comes up, trio0
shows activity.
- CSID: receives long packets (LONG_PKT IRQ bit set), confirming
the sensor TX and PHY RX path are functionally connected.
- On 13 Aug (prior session, by repo author): full frames captured
at 3844x2640, 181k pkts/2s at CDR=0x4a, recognizable portrait
image. The pipeline IS capable of working.
3. WHAT DIDN'T WORK
-------------------
- Reliable C-PHY link. On 18 Aug the link was extremely marginal:
13 Aug: 181,000 pkts/2s at CDR=0x4a
Session 1: 4 pkts at CDR=0x62, 0 at all other CDR values
Session 2: ~64 pkts at CDR=0x4a (per status registers),
0 per dmesg TOTAL_PKTS (wrong register offset)
SOT/EOT error bits set in CSI2_RX_IRQ_STATUS (0x1007) = the
receiver sees transitions but cannot reliably lock onto the
symbol stream.
- link_frequency override. The ccs driver selects 811.2 MHz
(idx18) from the DT array. Forcing 864 MHz (idx21) was accepted
by the control but broke the media pipeline (-EPIPE). Forcing
998.4 MHz (idx24) was rejected (ERANGE).
- sp11-camera-start.sh with imx681_windows=Y. The script sets
the pipeline to 3844x2640 but the scaler source is 3840x2160
in Windows mode, causing -EPIPE.
- ccs boot-race permanent fix. The sp11-camera-prepare guard
only checks "is ccs bound", not "is ccs in a working link-freq
state", so the broken state persists until manual reload.
- UKI DTB backup. The patch script failed to back up the pristine
kernel image on first run (missing /boot/uki-backup/ dir, no
set -e). The original DTB is permanently lost.
4. WHY IT FAILED
----------------
The C-PHY link between the IMX681 and the x1e80100 CSIPHY2 receiver
is not reliably trainable across reboots and temperature changes.
On 13 Aug, CDR=0x4a produced a clean link (181k pkts/2s, zero
errors). On 18 Aug, the same CDR value produced ~64 packets with
SOT/EOT errors, and no CDR value (0x00-0x6a) or AFE rate (1p0-1p8
Gsps) produced a clean link.
The werknotities (repo author's notes, line 218) explicitly warned:
"CDR 0x4a robuustheid over temperatuur/reboots in de gaten houden"
("monitor CDR 0x4a robustness over temperature/reboots")
This is a hardware-level signal integrity issue. The C-PHY receiver
(CDR/settle logic in the Qualcomm phy-qcom-mipi-csi2 driver) cannot
consistently lock onto the sensor's transmitted symbol stream.
Even if tuned to work at one temperature, it would not be reliable
over normal daily use — which is why the project was abandoned.
Contributing factors (not root cause):
- The link_frequency selected by ccs (811.2 MHz) may not match the
sensor's actual TX rate (~970 Msym/s from the Windows register
table). The yaml states the real sensor PLL is written by the
Windows mode table, not by ccs — so the link_freq only programs
the PHY receiver. A mismatch could cause settle/CDR miscalculation.
- The dmesg "TOTAL_PKTS" counter reads from register offset 0x300
(always 0), while the actual packet count is at 0x310. This made
diagnosis harder — the link appeared completely dead in dmesg
when it was actually receiving a small number of packets.
- The gpiolib_shared-proxy bug (TLMM pin 237 reads inverted from
what the consumer set) was investigated but ruled out — the
sensor responds to I2C and streams, so it is not held in reset.
5. POINTERS FOR FUTURE FIXES
----------------------------
If someone revisits this, here are the specific leads to follow:
a. PHY driver settle/CDR calculation
The SOT/EOT errors mean the receiver's CDR is not locking.
The phy-qcom-mipi-csi2-3ph-dphy.c settle count calculation
(phy_qcom_mipi_csi2_settle_cnt_calc, line 287) derives settle
from link_freq. If link_freq is wrong (811.2 MHz vs ~970 Msym/s
actual), the settle count is wrong. Fixing the link_freq
selection in ccs — or patching the PHY driver to use a fixed
settle count for this sensor — may help.
b. cphy_settle parameter
The phy_qcom_mipi_csi2 module has a cphy_settle parameter
(0=table default). This was NEVER tried. Sweeping it (e.g.
0x10-0x80) with CDR=0x4a at the correct link_freq may find a
combination where the receiver locks.
c. Fix the link_frequency selection
The DT has 29 link-frequency entries. ccs selects idx18
(811.2 MHz) by default. The yaml says 864 MHz is "the only
feasible C-PHY link". The ccs PLL calculator rejected 864 MHz
on this boot despite the yaml's min_vt_pix=160 override.
Investigate WHY the PLL calc rejects it — the yaml comment
(line 58-62) says "the real sensor PLL is written by the
Windows mode table" so the link_freq only affects the PHY.
Perhaps the DT link-frequencies array should contain ONLY
the correct value (970 MHz or 864 MHz), not 29 options.
d. Cold boot test
The link worked on 13 Aug and not on 18 Aug. Try a cold boot
(machine off for hours) to see if temperature is truly the
variable. If it works cold but not warm, this confirms the
signal integrity issue and means it is not fixable in software.
e. Patch sp11-camera-start.sh for 3840x2160
With imx681_windows=Y, the scaler source is 3840x2160
(ccs-core.c:2404). The script must use 3840x2160, not
3844x2640, or the pipeline will not start (-EPIPE).
f. Fix the dmesg TOTAL_PKTS counter
The camss driver's "sp11 csid stop" pr_info reads the packet
counter from register offset 0x300 (always 0). The actual
count is at 0x310. Fixing this in camss-csid-680.c would make
diagnosis accurate. The real count is available via
lees-cphy-status.sh in the meantime.
g. Fix the ccs boot-race permanently
The sp11-camera-prepare script should check for the
"no valid link frequencies" / "overflows" dmesg condition
and reload ccs, not just check "is ccs bound". Alternatively,
fix the PLL calculator so the first probe does not overflow.
h. Consult upstream
- karsies-wq (repo author) — has the deepest context on this
sensor/PHY combo.
- David Heidelberg (linux-media) — working on C-PHY camss
support upstream (WIP v4, Feb 2026). We would be the first
x1e80100 C-PHY user.
- jglathe (linux_ms_dev_kit kernel) — the kernel build.
i. Consider D-PHY instead of C-PHY
The IMX681 can do 2-lane D-PHY (Leopard Imaging module). The
werknotities tested D-PHY on all four csiphy's with no RX, but
that was before the Gilerson register table was confirmed
working. It may be worth re-testing D-PHY with the proven
sensor config.
j. UKI DTB backup
Always create /boot/uki-backup/ BEFORE running patch-uki-dtb.sh.
The script's backup step fails silently without set -e. If
revisiting, fix the script to add `set -e` and mkdir -p the
backup directory first.
6. ROLLBACK
-----------
All camera software was removed (modules, firmware, modprobe.d,
scripts, systemd units, libcamera yamls, video group membership).
The initramfs was regenerated. See the full install log
(sp11-imx681-install-log.txt) section 19 for details.
The only remaining change is the UKI DTB patch in the kernel image.
The camera DTB nodes are enabled but inert without the modules.
The DTB also carries a beneficial bluetooth BD-address fix.
To fully restore the pristine kernel: re-download the .deb from
jglathe/linux_ms_dev_kit GitHub releases, dpkg -i, update-initramfs.
Packages left installed (harmless, generally useful):
device-tree-compiler, libcamera-tools, v4l-utils, libv4l2rds0t64
================================================================
END
================================================================
Hmm someone solved that IMO SP11/Denali front camera (IMX681, C-PHY): reception on CSIPHY2 trio 0, SOT sync last blocker · Issue #74 · jglathe/linux_ms_dev_kit · GitHub
[Microsoft Surface Pro 11 — X1E80100 OLED]
Awesome — thanks @glathe!
I’ve just confirmed this is working. I’ve also forked your repo and am
working on in-tree drivers for the SP11: the phase55/MSHW0485 touchscreen,
the wsa884x PA-recovery profile (no left-speaker wedge at sustained full
volume), and the DP/DWC3 fixes. The work lives on the
sp11/integration-7.2.x
branch, with prebuilt packages in the
7.2.0-jg-0sp11v7 release.
I’ll open a PR against your 7.2.y line
for review soon; I just need to sort out the on-device volume-down rocker,
verify whether I can bring the DMIC clock back to 4.8 MHz vs the 2.4 MHz I
currently use, and a couple of other small things.
I guess you’re looking through the other issues, too ![]()
Is there going to be a time where we won’t have to deal with all this additional steps to actually have a functional installation?
Even after extracting qcom firmware from Windows partition I barely have most of the things working. I’m on Asus Zenbook A4 32Gb variant and still fighting with getting the WiFi work…
Hi @c2h6, there is a candidate for testing. Checked the dsdt.dsl and derived it will probably be like the lcd variant of the Ideapad slim5.
Hmm did you take look at zensanp/linux-book4-edge? They’re coming along nicely as it seems.
Isn’t that for Samsung rather than Asus Zenbook? Unless they have exactly the same hardware?
I’ve read A4… miswired to Galaxy-Book 4. Sorry for that. There is good support for A14 from @alexvinarskis .
I had to add
&pmk8550_pwm {
status = "okay";
};
to the dts and the default brightness was way too low ~100 (max is 4095) so i had to use brightnessctl initially
But it now seems to work thank you so much !
Ah yeah, my bad! I lost 1 on the way.
So the way I understand is that I need to apply these patches on the GitHub page to the kernel and build it with the patches?
Depends on “the kernel” but generally, yes. I did some integration for A14 a while back into my tree, but afaik work is ongoing.
Yeah… I gave up on this. Nothing seemed to work properly whatsoever which is seriously a shame… I hope that in the future the support for arm64 will be better, but for now I might as well stick with WSL2 until that happens.
Does hibernate work for you? On my T14s I just get a blank screen after I try to resume. I’m running @glathe’s 7.2.0-rc
I am running 7.2.0-12-qcom-x1e and I don’t have the option for hibernate but sleep and resume after closing the lid or manual sleep works as expected for me. I haven’t tested the battery drain on the current kernel.
All on a T14s.
EDIT:
Roughly 1.75% per hour of battery drain.
My bad. I forgot to mention I recompiled with hibernate support.