Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/HANDOFF-2026-08-10-d10.md
Fimeg a8e590a98a HANDOFF 2026-08-10: the d10, dark and untouchable
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.
2026-08-09 22:38:05 -04:00

11 KiB
Raw Blame History

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:

  1. 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.
  2. panel-summit sends no DCS display-on, and never sets dsi->lanes, format or mode_flags. That is correct for a Touch Bar, where the loader leaves the panel running. D10's ADT says #lanes = 2. If adp-mipi reprograms 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:

  1. apple/t8010-smartio.bin was not on the rootfs. SIO DMA times out (-ETIMEDOUT after the 60 s sysfs fallback), apple-spi gets 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. Now CONFIG_EXTRA_FIRMWARE, compiled into the Image — the only placement that beats rootfs to the probe.
  2. # CONFIG_REGULATOR is not set silently dropped REGULATOR_APPLE_PMIC_TOUCH (drivers/regulator/apple-pmic-touch-regulator.c, marked default y if ARCH_APPLE), so apple_z2's mandatory hv/core supplies resolved to no-op stubs and the controller was never powered.
  3. Runtime report activation was gated to D11. apple_z2_enable_d11_reports_locked() is what turns runtime reports on; D10 never called it. Four is_d11() sites now go through apple_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 touch variant — 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_disable both supplies, 20 ms, then normal power-on) because regulator_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

  1. Do not read MMIO on live display registers. Probing /dev/mem to identify a register window put the phone into recovery twice. A wrong reg in a DT node is safe by comparison — the driver maps what it is told and fails to probe with an errno.
  2. A device node is not a working device. A registered input device 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.
  3. 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.
  4. config_16k is the bare upstream reference — no PCIE_APPLE_H9P, no APPLE_SIO, no TOUCHSCREEN_APPLE_Z2. Building d10 from it yields a kernel with no storage and no touch. Use config-d10-full-16k.
  5. status = "disabled" on framebuffer0 does nothing. m1n1's kboot fills and re-enables /chosen/framebuffer itself. Only initcall_blacklist=simpledrm_platform_driver_init removes it.
  6. pgrep -f matches your own ssh command line. It killed a session and produced two false "phone is down" readings in one night.
  7. Warm re-exploit is not a cold boot. Rails, clocks and controller state survive it.

6. Open, ranked

  1. Touch. §3's single boot. Everything else on the device is watching a screen that cannot answer.
  2. The panel is dark under ADP. §2. Read the real timings out of m1n1 or the ADT rather than guessing again, and give panel-summit a d10 prepare that sets dsi->lanes = 2 and sends a DCS display-on.
  3. The panel cannot sleep. Blank shells out to blueline-screen-toggle, absent here, so it no-ops; Dim is brightnessctl set 10, an absolute that is 0.5% of 2047 and reads as off. The device therefore offers lit-forever or black-forever. eb0292c fixes the dim and needs a CI build plus pacman -Syu. The parity fix is viewtop owning the blank as a verb — it holds the CRTC and has power.rs with the EBUSY deferral on both bodies.
  4. Buttons are unrouted. gpio-keys reports KEY_MUTE, KEY_VOLUMEDOWN, KEY_VOLUMEUP, KEY_POWER on event1, and viewtop already classifies the last three (buttons.rs:52-54). Nothing routes them on this body. KEY_MUTE is the ringer switch and has no Button variant anywhere — new hardware the Pixel does not have.
  5. sessiond eb0292c and Souveraine bf469c4 need to reach the device by package, not by hand.
  6. hyprctl is 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).