Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/saf/device/evidence/audio/HANDOFF-audio-finish-20260719-evening.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

225 lines
12 KiB
Markdown
Raw 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 — Put the Pixel 3 audio to bed (Fable, evening 2026-07-19)
> Historical handoff. The current contract is `../../audio.md`; this file is
> retained as dated evidence and may describe work that was later completed.
We are *this close*. Mic captures nonzero on every boot now, both loudspeakers
fire, modem connects. What's left: reinstate PipeWire (the reason it was banned
is gone), keep the mic/speaker gains, and make the phone **call-ready**
(two-way call audio). This doc is your orders, not a draft to critique.
---
## ⚠️ READ THIS FIRST — the references are ALL local, and they are VAST
Casey's #1 instruction for this handoff: **stop and internalize that nearly
every fact you could want is already on this drive** — every bring-up attempt,
every Android LIVE capture, every modem trace, every regmap dump, the full
Android vendor mixer map, the pmOS known-good config, the raw partition images.
Even the outgoing session (me) *barely* knew this reference surface existed and
wasted hours re-deriving things that were sitting in a file. **Do not repeat
that.** Before you form any theory or run any experiment, grep/read the local
references. If you catch yourself reverse-engineering ALSA/UCM/modem internals
from scratch, you have already failed — go find the file.
### The reference surface (4 repos, ~70 GB, all local)
**1. `~/Projects/Pixel3Arch/PAF/` — the then-current base of truth.** Doctrine + current state.
- `audio.md` — the entire audio saga. THE ALTERNATION LAW, THE BOOT RACE,
speaker routing provenance, mic transport. Read top-to-bottom.
- `audio-2026-07-19-LIVE-reconciliation.md` — **supersedes the top of
audio.md.** LIVE Android register captures (recorder vs voice call),
the ADM-usecase hypothesis, and the **airplane/radio-mode wedge warning**
(some historical "wedges" were mode toggles, not driver faults — rule
mode out before logging any wedge).
- `HANDOFF-mic-unpin.md` — the un-pin experiment (corrected header; read
audio.md "THE BOOT RACE" first).
- `modem.md`, `pmos_fix_plan.md`, `qcril_*_capture.md`,
`modem_dt_rf_analysis_*.md`, `tz_listener_archaeology.md`,
`secure_load_tz_frontier.md`, `qrtr_tools_reference.md`,
`tier1_los_vs_mainline_diff.md` — the **modem bring-up archaeology**.
Deep. Detailed. Read before touching the modem.
- `evidence/`, `captures/` — raw traces (e.g. glink).
**2. `~/Projects/PostMarketOS-Blueline/` — the pmOS port + all Android captures.**
- `android-reference/`**the gold.** `mixer_paths_tavil_b1.xml` (the FULL
Android vendor route map — every named route: `handset`, `speaker`,
`voice-handset`, `voice-speaker`, all mics), CS35L36 regmaps
(idle/playing), tavil PGD dumps, `wcd9xxx_core-android-LIVE-*.txt`
(recording AND voicecall, captured 2026-07-19), `wcd934x-android-ground-truth.md`.
- `android-capture-2026*` — nine per-day Android trace dirs.
- `PAF/` — a second full modem-trace tree (`android_modem_bringup_capture.md`,
`qcril_full_provisioning.md`, `qcril_online_sequence.md`,
`modem_consumer_chain_*.md`, `los-mss-translated.c`).
- `HANDOFF.md` (80 KB), `PROGRESS.md`, `START-HERE.md`, `README.md`.
**3. `~/Projects/pixel3-downstream-audio/` — the Android HAL source.**
`techpack/audio/` — downstream `q6adm.c`, `q6voice*.c`, ASoC machine driver.
This is what the working Android side actually runs; diff mainline behavior
against it when a route/topology question comes up.
**4. `~/pixel3-backup/` (in $HOME, not Projects) — raw partition dumps + pmOS config.**
`modem_a.img`, `persist.img`, `vendor_a.img`, `system_a.img` (raw Android),
plus `pmos-20260703/`**the known-good pmOS config backup** the speaker
routing was lifted from (see the memory note: this is the source of truth for
working modem/cellular + speaker config; restore from here, never guess).
If a route value, a mixer control, a modem sequence, or a UCM verb is in
question — it is decoded in one of the above. Cite `file:line`. Do not invent.
---
## CURRENT STATE (verified live this session, phone at WiFi `10.10.20.234`, USB `172.16.42.1`)
**Kernel:** `7.1.1-sdm845-gcd7758eaeca1` (mic-race-fix, HEAD). Boot-race fix
LIVE and working — `MICDBG boot sysclk hold armed` fires in dmesg, capture open
joins a live codec (`users=2 skip`) instead of racing bring-up.
**Mic — WORKING.** `parecord --device=blueline_mic` yields nonzero PCM every
boot. Deterministic now (kernel sysclk hold from `wcd934x_comp_probe`).
**Speakers — WORKING.** Both CS35L36 amps armed, correct route (measured live):
`Left/Right AMP Enable = on`, `BOOST = on`, `PCM Volume = 700`,
`Left Channel Mux = RX1` (top), `Right Channel Mux = RX2` (bottom). Matches the
07-12/07-13 known-good. The `handset` (earpiece) vs `speaker` distinction is a
**single control**: `Right AMP Enable` — Android's `handset` route runs the top
amp only (`R AMP Enable=0`, low gain); `speaker` runs both. Decoded from
`mixer_paths_tavil_b1.xml`.
**Modem — connects.** Registered (Fido, MNC 720). Call *signaling* works. Note:
saw a transient roaming reject (MNC 490, `roaming-not-allowed`) mid-session —
that's network, not us, and consistent with the reconciliation doc's mode/radio
caveat. Rule mode out before chasing modem "faults."
**Calls — NO AUDIO yet.** `q6voiced` is now `enabled + running` holding
`hw:0,2` (the live VoiceMMode1 PCM — NOT device 5 as the staged conf wrongly
said; fixed this session in both `/etc/q6voiced.conf` on-device and
`pkgs/q6voiced/q6voiced.conf`). But it logs `Failed to open tx/rx: Invalid
argument` on call-start because nothing applies the VoiceCall route. See below.
---
## THE TWO HOLDS ON THE MIC (know the difference)
1. **PA loopback pin** (`90-blueline-alsa.pa`, modules 20/21): null-sink +
`module-loopback source=blueline_mic ... source_dont_move sink_dont_move`.
Holds the mic open from boot. **Nobody else does this** — verified via GitHub
code search: no working sdm845 phone (OnePlus 6 enchilada/fajita, holioka)
pins the mic. It's a boot-race workaround.
2. **Kernel sysclk hold** (today's fix, in `wcd934x_comp_probe`): permanent
sysclk ref + MICB2 bias from probe. Honest hack — pins the winning-boot
state so every boot wins.
**With the kernel hold in place, the PA pin is very likely now redundant.** The
un-pin test was never run on a race-won boot. Running it de-hacks the daily
driver. See `HANDOFF-mic-unpin.md` for the exact procedure (unload loopback,
same-map reopen ×2, watch for `CHAN_CTRL remove ret=0` + fresh `DEF_ACT_CHAN`).
If reopen is nonzero → delete the PA pin, keep the kernel hold. If zero → keep
both, root-cause stays open.
---
## PIPEWIRE — the ban is lifted; bring it back
**Why it was removed (`da53133`):** the *only* documented reason was the
**premature capture source** — wireplumber published the mic before ALSA
capture was nonzero (the boot race). PAF audio.md:516/590. PipeWire *playback*
was never the problem — `8920c3c` had PW playing on glass fine once the sink
was pinned S16LE + RW + no-mmap (the DSP lies about S24/mmap; both play silent).
**Why it's safe now:** the boot race is fixed in-kernel — **capture is nonzero
from boot, deterministically.** The precondition PipeWire failed on is
satisfied. Casey has explicitly cleared reinstating it.
### PipeWire task
- Reinstall the full PipeWire + WirePlumber stack. Note the current shims:
`pkgs/pipewire-abi-provider`, `pkgs/pulse-native-provider` (they provide the
PW ABI *without* a server — you're replacing that arrangement with a real
server, so reconcile/remove the shims cleanly, don't leave a half state).
- **Re-apply the S16LE playback rule** (the wireplumber
`51-blueline-audio-s16.conf` that `8920c3c` created and `da53133` deleted —
recover it from git: `git show 8920c3c`). Without it, playback is silent.
- Verify on the fixed kernel, in this order, and DO NOT proceed past a failure:
1. mic still nonzero via PW (`pw-record`) — this is the thing PW broke before;
2. speakers play via PW (`pw-play` a chime) — both top+bottom;
3. the mic source is NOT published dead at boot (the old failure mode).
- Keep the new features intact: the QS audio service fix
(`Audio.qml``blueline_mic` description matcher), the mic/speaker gains,
the speaker Channel Mux routing.
**Ponytail guard:** PipeWire is the bigger hammer. Its payoff is that
**callaudiod can then route calls via UCM** — which is the whole reason we want
it back. If PW re-breaks the mic despite the race fix, fall back to the raw-PA
call hook (below) rather than fighting it — the mic is non-negotiable.
---
## MAKE IT CALL-READY (the actual finish line)
The working sdm845 reference (OnePlus 6, `chayleaf/dotfiles`
`system/hardware/oneplus-enchilada/default.nix`, and `syntheit/nix`
`hosts/fajita`) routes call audio through **UCM (consumed by PipeWire) +
callaudiod + q6voiced tied to ModemManager**. Key facts pulled from it:
- `q6voiced hw:0,6` there (per-board PCM number; **ours is `hw:0,2`** — always
read `/proc/asound/pcm`, never copy the number).
- q6voiced is `After=`/`wantedBy=ModemManager.service`.
- `alsa-ucm-conf` is shipped and `alsa-ucm-meld = true` — **UCM is the routing
layer.** callaudiod flips the verb on call state; q6voiced carries the audio.
### The call chain we need
`gnome-calls → callaudiod → UCM VoiceCall verb → q6voiced carries modem audio`
Both middle links are currently broken/absent on our raw-PA setup:
- **callaudiod** is installed and running but has zero log activity — it routes
via PipeWire ports/profiles, which don't exist under raw-PA. **PipeWire back
gives callaudiod something to route with.** This is the clean path and the
reason PipeWire is worth the risk.
- **UCM VoiceCall verb** exists (`Google/blueline/VoiceCall.conf`) but has the
**same `hw:0,5` bug** (`PlaybackPCM/CapturePCM "hw:${CardId},5"`) — fix to
`,2`. Its EnableSequence is the real voice route:
`SLIMBUS_0_RX Voice Mixer VoiceMMode1=1`,
`VoiceMMode1 Capture Mixer SLIMBUS_0_TX=1`. Cross-check the RX/TX and DMIC/DEC
selections against `mixer_paths_tavil_b1.xml` `voice-handset`/`voice-speaker`
and the downstream `q6voice*.c` before trusting them.
- **UCM currently fails to load via `alsaucm -c G3`** (`-2`). Under raw-PA this
is moot (PA doesn't consume UCM). Once PipeWire+wireplumber drive UCM this
must actually resolve — verify wireplumber opens the card's UCM cleanly.
(The card driver/id: `id=G3`, longname `Google Pixel 3`, ASoC machine
`msm-snd-sdm845`; conf.d lives in `conf.d/sdm845/`. If UCM won't match, this
driver-name-vs-dir mapping is the first suspect — but let a real UCM client,
not the bare CLI, be your test.)
### Definition of done — ALL MET 2026-07-29
1. PipeWire back, mic + both speakers verified on the fixed kernel. **Done
2026-07-19.**
2. Place a real call (Casey → his wife). **Two-way audio.** Downlink out the
speaker, uplink from the mic, on the call. **Done 2026-07-29** — incoming
call answered, both directions confirmed by ear at both ends. Five defects
had to fall first; see `PAF/audio.md`, 2026-07-29.
3. On hangup, audio reverts to normal HiFi (no stuck voice route). **Done**
and note the reverse was silently broken: the mic read exact zeros after
*every* call until the outgoing capture leg was unmapped explicitly.
4. q6voiced device number correct (`hw:0,2`) in every place it's written.
**Done.**
5. New features + gains preserved. Mic still nonzero every boot. **Done**
~90k nonzero frames verified repeatedly across the session.
Not in the original list, completed 2026-08-02: the earpiece/speaker executor
(`blueline-callaudio-hook speaker on|off`) is driven by the patched
`souveraine-callaudiod`; see `../../audio.md` and TASK-39.
### Fallback (if PipeWire re-breaks the mic)
Raw-PA call hook: a small ModemManager call-state trigger that applies the
VoiceCall mixer controls directly via `amixer`/`alsaucm cset` on call-start and
reverts on hangup. ~15 lines. No server swap, zero risk to the working mic.
Smaller diff, fewer niceties. Only take this if PipeWire loses the mic.
---
## RULES OF ENGAGEMENT
- Base of truth = PAF. Every reference is local (the 4 repos above). **Read
before theorizing.** Cite `file:line` or say "not in the code."
- Rule out airplane/radio mode before logging any modem/audio "wedge."
- The mic is the crown jewel. Never trade it away for a nicety.
- Verify claims live on the phone; don't assert kernel/route state from memory.
- The doctrine holds: build the finished thing, not a v1. This is the last mile.