Display pipe binds and the panel stays dark; touch worked once and stopped. Both have a named single-boot test rather than a theory. Driver changes and rails are ruled out by test; the display path is not.
11 KiB
HANDOFF — 2026-08-10, the iPhone 7
For Codex. The d10 is at 172.16.43.1, root, ~/.ssh/ani. It is running, it is
reachable, and it shows nothing on the glass and takes no touch. Both of
those are regressions from earlier the same night, and both have a named next
test rather than a theory.
Read docs/tasks/63-d10-second-body.md and devices/d10/README.md. Everything
below is what a fresh session would otherwise spend hours rediscovering.
1. State right now
| kernel | 7.2.0-rc1-g2e349ddf2fe3-dirty, variant adp4, booted with -a |
| display | ADP owns card0. CRTC active=1, fb=43, plane 750x1334+0+0, connector card0-DSI-1 connected+enabled. Panel dark. |
| touch | apple_z2 bound on spi0.0, init completes, IRQ never moves for a finger |
| session | greetd → casey on seat0/tty1, sessiond + shell active, locked |
| backlights | two, both raised — the darkness is content, not brightness |
The boot that produced this used boot.sh -a, which blacklists simpledrm so ADP
is the only DRM device. Booting without -a gives simpledrm back and the
screen works. That is the first thing to do if the device needs to be usable
before it needs to be understood.
~/Projects/hoolock/boot.sh -k adp2 # simpledrm, screen works
~/Projects/hoolock/boot.sh -k adp4 -a # ADP alone, dark
DFU is buttons only: power off, Vol-Down + Power 8s, release Power, keep Vol-Down ~10s. The script waits for it and drives everything after.
2. The display pipe binds and the panel stays dark
This is new capability, not a broken thing that used to work. No T8010 has
ever had a DRM display pipe — Sandcastle, pmOS, uPhone and the original 2020
boot all scan out simple-framebuffer. ADP now binds here:
[drm] Initialized adp 0.1.0 for 206200000.display-pipe on minor 1
Every address was derived, not guessed: read off the phone's own ADT and
cross-checked against HoolockLinux/linux:tests/adp commit 2b3b1a7fc
("t8012 dts: display pipe" — T8012 is T2, A10-family, and its disp0_dart is
literally apple,t8010-dart).
| node | reg | irq |
|---|---|---|
disp0 |
be 0x06200000/0x9000, fe 0x06400000/0x4000 |
be 154, fe 158 |
disp0_dart |
0x06304000/0x4000 |
156 |
disp0_mipi |
0x06600000/0x100000 — byte-identical to T8012's |
163 |
The be/fe split is not a coin flip: ADP binds only be/fe by name, pokes be
to 0x40f4 and fe to 0x100, and T8012's IRQ layout puts its DART between
the pipe's two (210/212/214 there, 154/156/158 here).
Two things in this port were guessed, and the darkness is almost certainly one of them:
- The mode timings. Nothing in the ADT publishes a raster, so
panel-summit's d10 mode carries porches I invented —750 758 774 790 / 1334 1338 1346 1354, 64179 kHz. m1n1 already programmed Apple's real timings and ADP re-modesets over them. panel-summitsends no DCS display-on, and never setsdsi->lanes,formatormode_flags. That is correct for a Touch Bar, where the loader leaves the panel running. D10's ADT says#lanes = 2. Ifadp-mipireprograms the host from unset defaults, the link comes up wrong.
Where to look for real timings: m1n1 programmed them, so m1n1-pauli's display
path knows. The ADT mipi-dsim node carries phy-test, sac-frequency-list,
agile-line-count = 9, #lanes = 2 — enough to reconstruct, none of it read
yet. Do not probe MMIO to find out (see §5).
3. Touch worked once. Three layers were fixed; a fourth is unexplained
It genuinely worked, on the first boot after the rails came up: 2407 events,
270 SYN_REPORT, 13 balanced down/up, X 53..735, Y 107..1333, with
MT_TOUCH_MAJOR and MT_ORIENTATION. Kernel-native apple_z2, no hx-touchd,
no Sandcastle daemon — which is ahead of every other port on this hardware.
Three real defects were found and fixed, each hiding the next:
apple/t8010-smartio.binwas not on the rootfs. SIO DMA times out (-ETIMEDOUTafter the 60 s sysfs fallback),apple-spigets no TX DMA, the SPI bus never probes. The blobs existed since 2026-08-08 but shipped in the install ramdisk only, and the disk-boot blob has no initramfs. NowCONFIG_EXTRA_FIRMWARE, compiled into the Image — the only placement that beats rootfs to the probe.# CONFIG_REGULATOR is not setsilently droppedREGULATOR_APPLE_PMIC_TOUCH(drivers/regulator/apple-pmic-touch-regulator.c, markeddefault y if ARCH_APPLE), soapple_z2's mandatoryhv/coresupplies resolved to no-op stubs and the controller was never powered.- Runtime report activation was gated to D11.
apple_z2_enable_d11_reports_locked()is what turns runtime reports on; D10 never called it. Fouris_d11()sites now go throughapple_z2_is_gen2_reports()= D10 ∨ D11.
And it still does not work. The init trace is clean and complete — firmware
blobs load, firmware ready IRQ received, wake, D9 info, surface geometry read
back off the part (5850×10405, 13 units/mm), "report initialization complete",
d11-e2 sent and answered. Then apple-z2-irq (166) does not move for a
finger. Not a parse problem, not routing: the controller stops raising the line.
Ruled out by test, not by reasoning:
- The driver changes. Booted the original
touchvariant — no ADP, none of the z2 edits, the exact kernel that gave 2407 events. IRQ delta 0. - The rails. Added a forced power cycle at probe
(
regulator_force_disableboth supplies, 20 ms, then normal power-on) becauseregulator_enable()on an already-on rail is only a refcount bump and a warm re-exploit inherits them up. No change. A driver rebind cleanly re-inits (IRQ 3→6, full trace) and still yields nothing on touch.
Untested, and the leading candidate: the display path. That working boot was
the last one where simpledrm drove the panel. Apple's touch controllers sync to
display scan — t8010-ipad7.dtsi gives its touchscreen display-sync-gpios,
and D10's disp0 carries function-lcd_enable. Every boot since has changed
the display: first ADP alongside simpledrm, then ADP alone.
The one boot that settles it:
~/Projects/hoolock/boot.sh -k touch # note: no -a, so simpledrm drives the panel
ssh -i ~/.ssh/ani root@172.16.43.1 'grep apple-z2-irq /proc/interrupts' # twice, touching between
That restores the exact conditions of the run that worked. If the IRQ climbs, touch is display-coupled and the fix is ordering, not the z2 driver. If it stays frozen, the regression predates every change made after that boot and the search moves to what else the first boot had — it was the first boot after a true cold power-off, and nothing since has been one.
4. What shipped, and where
| repo | ref | what |
|---|---|---|
Fimeg/hoolock-d10 |
0e80de6 (new repo) |
the whole d10 port — boot.sh, board DTS from the ADT, the kernel patch, config-d10-full-16k, BOOT-d10.md. Apple firmware, SysCfg and the ADT dump are gitignored |
SouveraineOS |
37b570e..46685ae |
devices/ matrix, TASK-63, START-HERE now names both phones |
Souveraine |
b2774c8..bf469c4 |
dim-by-percent; lock surface answers on a cold start |
The kernel commit 2e349ddf2 lives on archdev only (~/Projects/hoolock/linux-pauli,
a clone of Pauli1Go/HoolockLinux that cannot be pushed to). It is exported as
PAF/evidence/d10-adp-touch-2026-08-09.patch and duplicated in hoolock-d10.
That commit also captured the 141-line t8010-d10.dts board port, which had
been sitting uncommitted against the 14-line mainline stub.
One revert is in the archdev tree and not in the patch: the LAST-command
-EPROTO check at apple_z2.c:851 was widened to D10 and put back to D11-only,
because making a protocol check stricter can only cause failures. Rebuild before
trusting the tree.
5. Traps, each of which cost real time
- Do not read MMIO on live display registers. Probing
/dev/memto identify a register window put the phone into recovery twice. A wrongregin a DT node is safe by comparison — the driver maps what it is told and fails to probe with an errno. - A device node is not a working device. A registered
inputdevice with unpowered rails is byte-identical to working touch in/proc/bus/input/devices. Verify with events (SYN_REPORT, balanced down/up, changing ABS) or with the IRQ counter. This was asserted wrongly more than once. - Change one thing per boot. ADP and the z2 gates landed together; when touch died there was no way to attribute it, and isolating it cost three more boots.
config_16kis the bare upstream reference — noPCIE_APPLE_H9P, noAPPLE_SIO, noTOUCHSCREEN_APPLE_Z2. Building d10 from it yields a kernel with no storage and no touch. Useconfig-d10-full-16k.status = "disabled"onframebuffer0does nothing. m1n1'skbootfills and re-enables/chosen/framebufferitself. Onlyinitcall_blacklist=simpledrm_platform_driver_initremoves it.pgrep -fmatches your own ssh command line. It killed a session and produced two false "phone is down" readings in one night.- Warm re-exploit is not a cold boot. Rails, clocks and controller state survive it.
6. Open, ranked
- Touch. §3's single boot. Everything else on the device is watching a screen that cannot answer.
- The panel is dark under ADP. §2. Read the real timings out of m1n1 or the
ADT rather than guessing again, and give
panel-summita d10preparethat setsdsi->lanes = 2and sends a DCS display-on. - The panel cannot sleep.
Blankshells out toblueline-screen-toggle, absent here, so it no-ops;Dimisbrightnessctl set 10, an absolute that is 0.5% of 2047 and reads as off. The device therefore offers lit-forever or black-forever.eb0292cfixes the dim and needs a CI build pluspacman -Syu. The parity fix is viewtop owning the blank as a verb — it holds the CRTC and haspower.rswith the EBUSY deferral on both bodies. - Buttons are unrouted.
gpio-keysreportsKEY_MUTE,KEY_VOLUMEDOWN,KEY_VOLUMEUP,KEY_POWERon event1, and viewtop already classifies the last three (buttons.rs:52-54). Nothing routes them on this body.KEY_MUTEis the ringer switch and has noButtonvariant anywhere — new hardware the Pixel does not have. sessiond eb0292candSouveraine bf469c4need to reach the device by package, not by hand.hyprctlis still asked for windows, monitors, layers and workspaces. Dead under viewtop on both bodies; blueline merely still has the binary.
Connects to
TASK-63 (owner), TASK-25/27/28 (the overlay-vs-package hole, three more
instances), TASK-43/51/53 (viewtop), TASK-61 (the colour path — ADP changes what
"the compositor owns the LUT" means here), DEVICE-STATE-MACHINE.md §12 (the
blank belongs in the executor table, not a script named after one phone),
devices/README.md (the per-body matrix).