Mainline HDMI continuation, 2026-10-09 UTC
Evidence class: physical board, serial console, native Grim capture, and the operator’s monitor observation. A screenshot is not a photograph of the monitor. The corrected bundle has a matching fresh volatile boot and automatic relay startup. Physical picture/tap acceptance of that boot and automatic switching remain open; this change is not archived.
Original trial and identity
The interrupted Claude session built source edd74d1626d03770e08e328320b18118ece24508
and ran tools/coherent-shell-board-boot.py against its HDMI bundle. The
continuation found the board still running that volatile trial, with normal
panel boot files unchanged. The controller’s private raw capture and
serial-result.json remain under ~/tmp/k230-hdmi-board/candidate/.
The sanitized trial report preserves the controller
and loaded artifact hashes, running identities and unchanged-profile result.
The continuation’s private raw UART captures are under
~/tmp/k230-hdmi-continue-private/.
Host command:
python3 tools/coherent-shell-boot-inspect.py ~/tmp/k230-hdmi-bundle
It passed. Inspection records the immutable
bundle, kernel, system, DTB and boot-file hashes. The running system was
/nix/store/6armjz2q35gdyv5l8vas4k9mk48nzzhq-nixos-system-nixos-26.11.20260919.20b1ddd,
kernel 7.3.0-rc5. Initial serial state, captured at
2026-10-09T05:12:01Z, preserves these identities and DRM state.
The operator reported the monitor connected, powered on and black.
Shared-reset failure and live recovery
The original log initializes LT9611 at 2.53 seconds and decodes 1920 horizontal pixels at 4.77 seconds. Goodix begins probing at 4.83 seconds and registers its input at 4.98 seconds. Subsequent bridge reads report zero video, no EDID and disconnected HPD. The operator sees black. See DRM and touch state.
The touch driver in the read pinned source
drivers/input/touchscreen/goodix_berlin_core.c:goodix_berlin_probe() obtains
the reset with GPIOD_OUT_HIGH, which asserts the active-low GPIO24 before
goodix_berlin_power_on() releases it. This also resets LT9611, whose own
driver intentionally does not own the shared line.
The kernel’s regmap debugfs reads returned zeros, including chip revision,
system-init and Port-B registers. Reads used dd with nine-byte register
records and the register number as its block offset, for example:
dd if=/sys/kernel/debug/regmap/0-003b/registers bs=9 skip=32770 count=1 status=none
See reset register state. modprobe i2c-dev made the
confirmed I2C3 adapter, Linux adapter 0 on this boot, available to userspace.
With the connector temporarily forced on to suppress detect polling, these
two separate I2C transfers restored access:
i2ctransfer -f -y 0 w2@0x3b 0xff 0x80
i2ctransfer -f -y 0 w2@0x3b 0xee 0x01
i2ctransfer -f -y 0 w1@0x3b 0x00 r3
The ID read returned 0x17 0x02 0xe2; see raw ID.
A preceding attempted combined transfer and a preceding attempt before
loading i2c-dev did not restore access; they are not successful evidence.
Debugfs reads of page 0x83 and then 0x80 resynchronized the kernel’s cached
page selector after the raw access. Sway then received:
swaymsg 'output HDMI-A-1 power off'
swaymsg 'output HDMI-A-1 modeline 148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync'
swaymsg 'output HDMI-A-1 power on'
echo detect > /sys/class/drm/card0-HDMI-A-1/status
Commands ran as shell with SWAYSOCK=/run/shell/sway-ipc.sock, except the
root-only connector write. Recovery serial state
records a decoded 1920-pixel input, hsfreqrange 0x96, HPD 0x0d, automatic
connected status, a 256-byte EDID and 1080p modes. The bridge reports
vactive=1081 rather than 1080; this discrepancy remains recorded rather
than corrected by inference. No PHY tuning was needed in this recovery.
The operator then reported “screen works”. This is physical monitor confirmation of the live workaround, not of a fresh boot of the source fix.
At approximately 2026-10-09T05:23Z, the board ran:
runuser -u shell -- env XDG_RUNTIME_DIR=/run/shell WAYLAND_DISPLAY=wayland-1 \
grim /run/shell/mainline-hdmi.png
Native capture is 1080×1920 logical pixels, from physical 1920×1080 with Sway transform 90. The PNG was copied over the serial console using base64. It contains the live Home screen, not a host render.
Mouse follow-up
The operator reported no mouse cursor and no response to touch. Input discovery shows direct-touch events disabled, no touchpad input, no relay unit and no relay executable in the system PATH. The original HDMI bundle extends the ordinary mainline profile; it omitted the relay enabled by the earlier vendor HDMI trial profile.
The already-realized relay was imported into the board’s store, but starting
it was blocked by the absence of uinput in this kernel; see
module diagnostic. This import alone is not mouse proof.
The host then compiled the upstream drivers/input/misc/uinput.c against
the running Image’s exact kernel development output. The module was copied
to /run/k230-uinput-trial.ko with tools/push-file.py under the board lock;
the transfer verified MD5 10385a49550e6735a5f84271d08018ba on the board.
insmod /run/k230-uinput-trial.ko succeeded. A transient
k230-hdmi-trackpad-trial service started the already-realized relay:
systemd-run --unit=k230-hdmi-trackpad-trial --property=Restart=on-failure \
--property=DevicePolicy=closed --property='DeviceAllow=/dev/uinput rw' \
--property='DeviceAllow=char-input rw' --property=ProtectSystem=strict \
--property=ProtectHome=true --property=NoNewPrivileges=true \
/nix/store/v0n70zk76z0p3xky67613769l8pc2lrl-k230-touch-trackpad-riscv64-unknown-linux-gnu-0.1.0/bin/k230-touch-trackpad \
--shell-socket=/run/shell/sway-ipc.sock
Startup state shows the relay grabbing the actual
Goodix input and Sway recognizing an enabled virtual touchpad. This older
relay warns that --shell-socket is unknown and ignores it: it supplies
basic pointer/tap behavior, not the newer shell gesture integration. The
corrected bundle builds the current relay. Physical cursor movement and tap
acceptance must be recorded separately from this startup result.
At 2026-10-09T05:36:40Z, the newly built current-source relay
/nix/store/gy6r7r8pf8694pras6njlvgbpmjgg3n8-k230-touch-trackpad-riscv64-unknown-linux-gnu-0.1.0
replaced the older relay in transient service
k230-hdmi-trackpad-current-trial. Current startup
records its active state, successful grab and enabled virtual touchpad, with
no unknown-argument warning. The monitor remains automatically connected
with a 256-byte EDID. This update does not reboot or change the profile.
At 2026-10-09T05:42:05Z, a compositor command placed the cursor at logical
(540, 900), then Grim captured it with -c:
swaymsg 'seat seat0 cursor set 540 900'
grim -c /run/shell/hdmi-pointer.png
Native cursor capture shows the cursor. This is injected compositor movement, not finger input or a physical monitor photograph. It proves cursor rendering and does not complete the touch gate.
Source fix and remaining gates
The reset-ordering LT9611 source cross-compiled as an object against the
original kernel’s exact development tree. The same tree built an external
uinput module for the live mouse trial. The boot-inspector’s 15 tamper and
configuration fixtures pass, including the new HDMI profile identity.
Host checks record commands, store paths and source/module
hashes; object recipe and
module recipe preserve the commands’ inputs. These narrow
checks are not substitutes for the full-kernel build required by task 7.1.
The corrected HDMI DTB builds and decompiles. DTB checks
record its hash and graph/reset checks; reproduction command
checks reciprocal endpoints, one DSI output, no panel and touch ownership
of GPIO24/23. The corrected bundle also passes inspection. The default panel DTB builds
and decompiles with its panel present and no LT9611. The extracted common
controller body equals the original 94196f97 panel source except for the
touch label; this is a host regression check, not a new panel boot.
The continuation makes LT9611 wait for the I2C touch device to finish binding,
using the board-local lontium,shared-reset-owner phandle and a managed device
link. This prevents initialization before the shared reset and orders removal
and system suspend. The panel tree does not instantiate LT9611.
The separate k230-mainline-drm-shell-hdmi configuration enables the existing
relay and loads uinput; the HDMI boot bundle now selects that configuration.
The mainline DRM kernel enables INPUT_UINPUT=m. The complete corrected
kernel and bundle build now pass, including the
narrow nix build .#kernelMainlineDrm proof, bundle inspection and all 15
inspector fixtures; see full host checks and
matching bundle inspection. The matching fresh
boot and native captures are recorded below. Task 7.3
is now complete with the matching trial and operator acceptance recorded below.
The ordinary panel recovery below is serial proof; no physical panel taps
are inferred.
The inherited card-shell QEMU kernel build was stopped to prioritize HDMI and retain one heavy build at a time in this session. Its task 5.1 remains unproved; no QEMU pass or archive is claimed here.
Matching corrected-bundle board trial
The host exported an 18-path, 175,871,264-byte NAR closure delta over the private transfer link. Staging report records immutable bundle identity, transfer hashes and the resulting stage. Staging passed its closure, artifact and protected-profile checks. Raw UART and transport details remain private.
Before the corrected HDMI trial, the controller issued an ordinary reboot
and sent no U-Boot intervention. Panel recovery
records the original protected system, connected DSI-1, registered Goodix,
three active shell services and byte-identical boot files. The
controller recipe records its exact input checks.
This is serial recovery proof, not physical panel touch acceptance.
Corrected trial command, run under the controller’s exclusive board lock:
python3 tools/coherent-shell-board-boot.py \
--candidate ~/tmp/k230-hdmi-continue-private/hdmi-fixed-bundle \
--state ~/tmp/k230-hdmi-continue-private/fixed-stage/state.json \
--output ~/tmp/k230-hdmi-continue-private/fixed-trial
Trial report passes every loaded-file CRC and matches
running system
/nix/store/yndjf2iz1q1r0dndsbx154yr47bycak8-nixos-system-nixos-26.11.20260919.20b1ddd
and Image
/nix/store/17mn8cyc2bls0yrphlhpcikn77f491kq-linux-riscv64-unknown-linux-gnu-7.3.0-rc5/Image.
The persistent profile remains the protected panel system. No manual I2C
recovery, connector force or custom modeline was required on this fresh boot.
Live state, first captured at 2026-10-09T06:35:39Z
and repeated with a case-insensitive Goodix log filter, records:
- Goodix input registration at 2.570689 seconds, before LT9611 revision
0xe2at 2.739239 seconds. - Initial 1920-pixel video and DSI lane rate 891000 kbps,
hsfreqrange 0x96. - Automatic
connectedHDMI status, a 256-byte EDID and its mode list. - Sway’s selected EDID mode 1280×800 at 59.910 Hz, transform 90,
logical 800×1280. The corresponding later bridge check decodes 1280 pixels,
lane rate 445500 kbps and
hsfreqrange 0x96. - Four active services:
shell,shell-ui,theme-helperand the configuredk230-touch-trackpad;/dev/uinputexists, the relay grabs event1 and Sway recognizes the enabled virtual touchpad.
The vertical counter still reports one extra active line (1081, then 801). No hsfreqrange tuning was performed. The relay’s grab, rather than Sway’s raw-touch send-events flag, routes physical Goodix events exclusively to it.
The first native capture, at
2026-10-09T06:36:46Z, shows the terminal started by the existing unconditional
Sway exec and a rendered cursor. An attempted base64 UART copy failed
padding validation and is not accepted as image proof. The private HTTP copy
passed the board/host SHA256 comparison; see capture metadata.
The compositor then received swaymsg 'card_shell home'. At
2026-10-09T06:41:04Z, native Home capture shows the
shell and cursor at 800×1280. Home metadata records
commands, timestamp, dimensions and the matched transfer hash. This is a
native capture following an injected Home command, not a physical tap test
or monitor photograph. No pointer movement/click was injected during this
corrected-bundle trial.
The operator was asked to confirm the fresh monitor picture, finger-driven cursor movement and taps, then replied: “yeah hdmi works great it’s perfect continue lmk what you need”. Operator acceptance records the exact response and a read-only serial check confirming the same running system, connected HDMI and all four active services. This accepts the trial overall; it does not enumerate individual gestures, supply a photograph or establish gesture latency. The operator subsequently reconfirmed HDMI and explicitly waived a monitor photograph; the exact follow-up is in the same acceptance record. The optional Settings switch is separate work, not an acceptance gate for this trial. Task 7.3 is complete. Groups 3–5 and archive remain open. The board is left on the corrected volatile HDMI trial; an ordinary reboot retains the protected panel selection.
Publishing follow-up
The source/evidence checkpoint landed at 6c8d31a6. Its
CI run
passed the test steps but rejected four PNGs missing from the binary inventory;
Pages deployment was skipped. The continuation owns this failure. Exact
per-file DATA rows and hashes were added to docs/blob-inventory.md, and
python3 tools/blob-scan.py --no-vendor then passed. The
follow-up report preserves the failed revision,
log hash, correction and narrow validation. This bookkeeping correction does
not change the board’s running artifacts. The subsequent operator acceptance
above completes the corrected HDMI trial’s gate.