PAF becomes saf/device (history kept), STATE.md dissolves into saf/state.md with the dated era archived, the substrate SAF moves up from souveraine, and every agreement points at saf/INDEX.md and nowhere else. one map, nothing to remember
5.9 KiB
PAF · Display — SW43408 panel, DSI, bias rails (SOLVED 2026-07-10)
Current regression — verified on glass 2026-07-11
On current kernel 7.1.1-sdm845-g56b0a053bef8, a true unplugged cold boot
still produces a green flash during boot. Green flashes also remain on wake.
During AP-side DT2W testing the first double tap sometimes does a visible
green-flash/black half-wake and the second wakes the panel. The kernel trace
shows the first gesture reaches panel prepare and is immediately followed by
unprepare; there are no DSI/DPU errors. In one successful wake the visible
frame remained stale despite a synchronized system clock and live Hyprland +
Quickshell processes. This is an observation, not proof of a panel-only
root cause; preserve it for the display/DPMS investigation.
Recovery and clock distinction, 2026-07-11: after an instrumented
libssc-triggered lockup, blueline-screen-toggle on re-prepared the panel but
it unprepared again seconds later even with hypridle stopped. Do not churn
panel/FTS resets in that state. A normal reboot of the known-good current slot
restored the panel and compositor. The first post-boot ii screenshot still
showed the Jul-06 20:00 clock floor even though NTP had corrected system time;
restarting only Quickshell (qs -c ii kill, then qs -c ii) refreshed it to
the real time. Therefore an old ii clock is not alone evidence of a frozen
scanout. The remaining task is to prevent ii from retaining the pre-NTP clock,
not to reset the panel again.
Cold boot → Hyprland AND power-button sleep/wake visually verified on
kernel g766205b60588. Read this whole file before touching
panel-lg-sw43408.c, the labibb regulator, or the display DT.
The doctrine: WARM-CYCLE. Do not dismantle again.
The working design in drivers/gpu/drm/panel/panel-lg-sw43408.c:
.prepare= regulators + reset pulse only. No DCS..enable= the ENTIRE DCS init (gamma, TE, sleep-out, vendor regs, PPS, compression, display-on) — runs over a fully-up DSI link, onto a still-powered DDIC, on every DPMS-on..disable= display_off + enter_sleep (HS mode). That is ALL DPMS-off does.- No
.unpreparepower-off. The panel keeps vddi/vpnl forever after first boot; reset is never re-asserted at runtime.
Why: upstream's prepare-time cold-cycle design cannot cold-start this panel. Full power-off + reset + re-init produces a green flash (display-on latching onto random GRAM) then permanent black, on every transition. That is the original "screen won't wake without the sdm845-mainline hack" bug (David's report). The warm-cycle shape IS the fix — the panel is re-initialized warm, never cold.
History: the working design was dismantled on 2026-07-09 by ee6611adb ("adopt upstream prepare-time init") and a day of ordering experiments failed to make cold-start work (display-on before PPS, after PPS, downstream power sequencing — all green-flash-black). 766205b60 restored the warm-cycle architecture. Any future "align with upstream" refactor must first prove cold-start on real glass.
Bias rails: LAB/IBB under SWIRE (hardware) control
Matching downstream: the DDIC drives the OLED bias rails over the SWIRE wire, not software.
- DT:
qcom,swire-controlon the pmi8998 labibb node (1b02532a4). - Driver: SWIRE ops are software no-ops (enable/disable/set_voltage return 0);
probe writes IBB
ENABLE_CTL=0x40(SWIRE_RDY, module-enable cleared). LABENABLE_CTL=0x00is CORRECT in SWIRE mode (slaved to IBB in hardware). - Behavior: panel sleep-in → rails physically drop; sleep-out → rails rise. Register-verified live across DPMS cycles: STATUS1 (IBB 0xdc08 / LAB 0xde08 on regmap 0-03) reads 00/00 off → 80/a0 on.
- The panel driver's supplies are vddi + vpnl ONLY. It never touches
LAB/IBB. c789daaa8 fixed the tail end of the old design (unprepare
disabling never-enabled rails → unbalanced-disable →
panel->preparedstuck true → EBUSY zombie); moot under warm-cycle but the lesson stands: an error return from unprepare wedges the prepared flag forever. - Voltage: software set_voltage is a no-op; hardware stays at the bootloader's 5.5V programming.
Userspace wake path
- Hyprland (Lua build) power-button / tap-to-wake toggle:
blueline-screen-toggleon the phone. Wake needs BOTHhl.dsp.dpms("on")ANDhl.dsp.force_renderer_reload()— dpms-on alone can issue a commit with no real CRTC transition (crtc=NULL skips drm_panel_prepare; long-standing compositor-side hole). Gotcha fixed 2026-07-10: the script calledforceRendererReload(), which the Lua Hyprland renamed toforce_renderer_reload()— every power-button wake silently no-op'd. Dispatcher names must be verified against the running Hyprland, errors surface only in the hyprctl reply. - greetd →
start-hyprlandas initial session; the boot chain fbcon → greetd → Hyprland does one panel takeover, warm.
Diagnostic quick kit
- Rails now:
sudo grep -E "^(dc08|de08):" /sys/kernel/debug/regmap/0-03/registers(80/a0 = up, 00/00 = SWIRE-dropped). - Compositor truth:
grimscreenshot — separates "compositor renders" from "glass shows" (they diverged for two days; the screenshot was pixel-perfect while the glass was black). - DPMS from SSH:
HYPRLAND_INSTANCE_SIGNATURE=$(ls /run/user/1000/hypr/) XDG_RUNTIME_DIR=/run/user/1000 hyprctl dispatch 'hl.dsp.dpms("off"|"on")'. - drm.debug=0x1ff wraps the dmesg ring in ~130ms of transition traffic —
use
journalctl -kor a lower mask for transition captures. - Boot-time
DSI PLL lock failed+already disabled/unpreparedclk warnings at ~0.4s: probe-time deferred-probe noise, once per boot, benign-but-ugly (error path double-disables a clk). Not a transition bug.
Known-good fallback
../staging/deploy-139aa/boot-139aa7748181-pmoschain.img — pre-SWIRE-era
kernel (stmfts touch, warm-cycle display of that era). Module tree already
on the phone. Prefer fixing forward on the blueline tip.