Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/saf/device/touch.md
Fimeg bde961c6f2 saf: one spine — device, state, and work under the index
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
2026-08-18 09:47:30 -04:00

7.6 KiB

PAF · Touch — ST FTS, reset polarity, GPI-DMA, tap-to-wake

Current glass result — 2026-07-11

On kernel 7.1.1-sdm845-g56b0a053bef8, daytime touch works and the FTS recognizes DBLTAP. The current defect is downstream of gesture recognition: the first double tap can prepare the panel and then immediately unprepare it (green flash then black); a second double tap wakes the display. The first half-wake is kernel-trace confirmed. Treat DT2W as detected but unreliable until the screen-toggle/DPMS prepare-unprepare ping-pong is fixed. This is not the old IRQ/FIFO bug.

Status 2026-07-10 (morning): TAP-TO-WAKE WORKS, verified on glass by Casey on kernel d7a8f7dc9. FTS probes clean, gesture mask armed at boot, double-tap wakes from armed sleep, touch alive after wake, hypridle 60s idle screen-off enabled. The one remaining suspend-path defect was the IRQ handler, not the controller — see the closed item below.

Suspend-path doctrine (2026-07-10, learned the hard way)

  • gesture_enabled MUST be 1 before any DPMS-off. Unarmed suspend takes the SLPI-handoff branch (fts_suspend_work): controller handed to the PARKED sensor island + IRQ disabled → resume races → level IRQ storm (millions on IRQ 148) → kernel kills the IRQ → touch dead until driver rebind or reboot. With SLPI's sar.cc wall unfixed, the handoff target is unavailable — gesture-armed suspend (AP keeps the bus) is the only safe mode.
  • The compiled gesture_mask sysfs is the STASH-THEN-APPLY variant: echo "01 20" > stages only; the following cat applies (updateGestureMask) and sets gesture_enabled=1. blueline-dt2w.sh does both since de4fe40.
  • Live recovery from a dead touch IRQ, no reboot: echo 2-0049 > /sys/bus/i2c/drivers/fts/unbind && echo 2-0049 > .../bind — but Hyprland then holds stale input handles (taps flow at evdev level, UI ignores them); a session restart or reboot is needed after rebind.
  • VERIFIED 2026-07-10 (clean boot-time arm, Casey on glass): daytime touch works, and touch SURVIVES a full sleep/wake cycle — the regression is closed. Wake was power-button; double-tap did NOT wake.
  • CLOSED 2026-07-10 (kernel d7a8f7dc9) — tap-to-wake works on glass. The "controller never enters gesture scan" theory was WRONG: enterGestureMode runs and succeeds at every armed suspend (Sense OFF → gesture mode → enableGesture DONE in dmesg). The real defect was fts_interrupt_handler: during armed sleep bus_refmask==0, so the bus-ref gate refused every IRQ and returned WITHOUT reading the FIFO. Level IRQ line stayed asserted → refired forever (the "582k IRQs" were the unserviced line, not full-rate scanning), gesture events were dropped unread (why double-tap never woke), and a bogus release call in the refusal branch logged one pr_err per IRQ — 85k lines in one screen-off window, enough printk to freeze the phone on long sleeps (2026-07-10 morning freezes). Fix: service the FIFO without taking a bus ref when gesture_enabled && sensor_sleep (taking one would queue a resume per IRQ), drop the bogus release, ratelimit the bus-ref pr_err. The port's 30177cb7e (AP keeps bus in gesture mode) had changed the ownership model without teaching the IRQ path — classic lost-handler.

The hardware truth (settled — do not re-litigate)

  • This unit is the LG panel + ST FTS variant: FTS controller at 0x49 on i2c-2 (888000 geni SE). Settled from per-unit persist calibration + LOS init.blueline.rc.
  • The Samsung sec_ts@48 nodes in the downstream DTBO (fragment@81, sec,reset_gpio, …) belong to the OTHER hardware variant. Never cite fragment@81 as evidence for our touch config — that mistake shipped ba0620d5c and killed touch for a day.
  • Pins: reset tlmm 99 (active-low RESETB), IRQ tlmm 125 (level low), AP↔SLPI bus switch tlmm 136.

Reset polarity — the post-mortem

The ported vendor driver (drivers/input/touchscreen/stm/) uses gpiod logical assert semantics: acquires reset GPIOD_OUT_HIGH ("asserted"), pulse is set(1) → 20ms → set(0) → 50ms, and its own comment says "active-low reset" (fts.c ~4320). Therefore the DT flag must be GPIO_ACTIVE_LOW, so logical assert = physical LOW.

With GPIO_ACTIVE_HIGH (ba0620d5c, 2026-07-09 14:02) deassert drives the pin physically LOW → RESETB held forever → controller NACKs every I2C access → probe fails after 3 reset attempts. Signature in dmesg: gpi ... Error in Transaction: code=0x10 status=0x40 on EVERY read (including the first 8-byte poll), fts_system_reset: ERROR 80000002, Probe Failed!. Nobody noticed for a day because every boot in that window had a black display. f3c5f5a11 reverts to ACTIVE_LOW.

Triage rule: all-reads-fail = controller not out of reset / not powered / bus switch wrong — a dead chip, not a DMA problem. Large-read-only failure = the (historic) GPI-DMA wall below.

GPI-DMA wall (historic — status needs one clean-boot check)

The 888000 SE is GPI-mode-only (its SE firmware has FIFO disabled — no FIFO fallback exists; verified in i2c-qcom-geni probe). Historically small reads worked and the first large read (209-byte readSysInfo) died with MSM_GPI_TCE_UNEXP_ERR. Instrumentation ff6e6e2e8 logs completion status + error-log register on any recurrence. ANSWERED 2026-07-10, first clean f3c5f5a11 boot: the wall is GONE. Zero gpi ... Error in Transaction lines in dmesg; the driver read the 105,140-byte firmware file and ran CX/Panel CRC verification over the bus (Fw Update Finished! error = 00000000), FTS input device registered. Large GPI-DMA transfers on the 888000 SE work. Whatever ate the 209-byte read in the 2026-07-08 era was fixed by the intervening driver/power work or was reset-state fallout all along; if it ever recurs, the ff6e6e2e8 telemetry will say why. Deep diagnosis archive: ../CLAUDE.md "Touch / FTS-on-mainline key facts".

Gesture / suspend design (in-tree, working as of 07-09 morning)

  • 08687bec9 power+reset sequencing, e31aa9da7 prototype fix, 30177cb7e keep AP bus ownership during gesture mode, 3d9eb1028 sensor_sleep bookkeeping in gesture-mode suspend.
  • Gesture mode: on suspend the driver keeps the controller alive for double-tap; XF86WakeUp → Hyprland bind → blueline-screen-toggle (see display.md). dt2w service wiring: blueline-dt2w.service in rootfs-overlay (uncommitted edits pending as of 2026-07-10).
  • Proximity gate (2026-07-20): blueline-screen-toggle checks net.hadess.SensorProxy ProximityNear over D-Bus before dispatching DPMS on; if blocked (phone in pocket) the wake is suppressed and logged, the FTS gesture still fires XF86WakeUp either way. Fails open if the D-Bus query errors, so a dead sensor proxy never permanently blocks wake. Requires iio-sensor-proxy running, which is now always-on (see slpi.md). This closes half the "hot pocket" problem; the other half (screen already on + locked, phone pocketed) is blueline-proximity-lock (overlays/systemd-user/), a monitor-sensor --proximity watcher that blanks via the same blueline-screen-toggle off path when locked.

THE GOAL (unchanged): one FTS driver = daytime touch + tap-to-wake

Like LOS: FTS drives the controller when awake; on suspend it hands the controller to the SLPI over the tlmm 136 switch, where the sns_touch_gesture nanoapp (SLPI's own i2c bus 5) watches for double-tap and wakes the AP. stmfts (mainline driver) can never do this — no switch, no handoff; it is fallback-only. Two tracks converge:

  1. FTS daytime path — WORKING modulo the polarity fix verify.
  2. SLPI-side tap-to-wake — unblocked by the sar.cc fix (see slpi.md), but not required for the current AP-side gesture design.