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

219 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
```sh
~/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:**
```sh
~/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).