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
109 lines
5.9 KiB
Markdown
109 lines
5.9 KiB
Markdown
# 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 `.unprepare` power-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-control` on 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).
|
|
LAB `ENABLE_CTL=0x00` is 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->prepared`
|
|
stuck 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-toggle` on the phone. Wake needs BOTH
|
|
`hl.dsp.dpms("on")` AND `hl.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 called `forceRendererReload()`,
|
|
which the Lua Hyprland renamed to `force_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-hyprland` as 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: `grim` screenshot — 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 -k` or a lower mask for transition captures.
|
|
- Boot-time `DSI PLL lock failed` + `already disabled/unprepared` clk
|
|
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.
|