Audio: card fixed, needs a UCM for a usable Plasma sink #13

Open
opened 2026-08-21 16:46:17 +00:00 by kit · 3 comments
Owner

Plasma showed no speakers. Root cause was two DT bugs (no sound card at all); those are fixed (kernel bd8570fe7c81). What remains is userspace: the card exists but has no UCM, so PipeWire only offers off/pro-audio and no routed "Speaker" sink.

Fixed (kernel bd8570fe7c81)

  • q6asmdai had no dai@N children → q6asm-dai: No dais found in DT → no card. Added dai@0/dai@1.
  • The four CS35L41 amps had no sound-name-prefix → colliding "Digital PCM Volume" controls → card instantiation failed -EBUSY. Added FL/FR/RL/RR (matching the routing the sound node already references).

Now: card 0 "S6" (Samsung Galaxy Tab S6) instantiates, pcmC0D0p present, PipeWire sees a "Built-in Audio" device.

Remaining — UCM (userspace)

wpctl status: device 43 "Built-in Audio", but the only sink is "Dummy Output". pactl list cards shows only profiles off and pro-audio — no routed analog output. Cause: no UCM config for this card.

  • alsa-ucm-conf is installed but only ships sdm845 (Qualcomm/sdm845/), and our machine driver is snd-sm8150, so it doesn't match.
  • The sdm845 q6 UCM is a reasonable template (same q6afe/q6asm/q6routing), but backend/mixer names differ — ours routes MultiMedia1 → SECONDARY_TDM_RX_0 → quad CS35L41 (prefixes FL/FR/RL/RR), where sdm845 uses different backends.

Plan

  1. Enumerate the card's actual kcontrol names (amixer -c S6 controls / tinymix) — the routing mixer (... Mixer MultiMedia1), the SEC_TDM path, and the CS35L41 PCM Volume/Switch/DSP1 controls per amp. Blocked today: alsa-utils wouldn't install (pacman PGP-signature error on the mirror — keyring refresh needed).
  2. Author a card-specific UCM2 HiFi/Speaker verb: enable MM1→SEC_TDM_RX_0 and the four amp switches, set safe volumes. Drop it in /usr/share/alsa/ucm2/conf.d/ matching the snd-sm8150/"S6" card.
  3. Package the UCM in gts6l-alarm so a fresh rootfs has working audio.

Notes / risks

  • Four CS35L41 smart amps on SECONDARY TDM at 6.144 MHz — the amps and q6 routing both need their DAPM paths enabled or the PCM reaches nothing.
  • Channel geometry (which physical amp is FL vs RR) affects placement, not whether sound plays; verify with a per-channel test tone.
  • Once UCM exists, Plasma should auto-show a "Speaker" sink with no further config.

Kernel side is done; this is a focused userspace-config task.

Plasma showed no speakers. Root cause was two DT bugs (no sound card at all); those are **fixed** (kernel `bd8570fe7c81`). What remains is userspace: the card exists but has no UCM, so PipeWire only offers `off`/`pro-audio` and no routed "Speaker" sink. ## Fixed (kernel `bd8570fe7c81`) - `q6asmdai` had no `dai@N` children → `q6asm-dai: No dais found in DT` → no card. Added `dai@0`/`dai@1`. - The four CS35L41 amps had no `sound-name-prefix` → colliding "Digital PCM Volume" controls → card instantiation failed `-EBUSY`. Added FL/FR/RL/RR (matching the routing the sound node already references). Now: card **0 "S6" (Samsung Galaxy Tab S6)** instantiates, `pcmC0D0p` present, PipeWire sees a "Built-in Audio" device. ## Remaining — UCM (userspace) `wpctl status`: device 43 "Built-in Audio", but the only sink is "Dummy Output". `pactl list cards` shows only profiles `off` and `pro-audio` — no routed analog output. Cause: **no UCM config for this card.** - `alsa-ucm-conf` is installed but only ships **sdm845** (`Qualcomm/sdm845/`), and our machine driver is **`snd-sm8150`**, so it doesn't match. - The sdm845 q6 UCM is a reasonable *template* (same q6afe/q6asm/q6routing), but backend/mixer names differ — ours routes MultiMedia1 → **SECONDARY_TDM_RX_0** → quad CS35L41 (prefixes FL/FR/RL/RR), where sdm845 uses different backends. ## Plan 1. Enumerate the card's actual kcontrol names (`amixer -c S6 controls` / `tinymix`) — the routing mixer (`... Mixer MultiMedia1`), the SEC_TDM path, and the CS35L41 `PCM Volume`/`Switch`/`DSP1` controls per amp. **Blocked today**: `alsa-utils` wouldn't install (pacman PGP-signature error on the mirror — keyring refresh needed). 2. Author a card-specific UCM2 `HiFi`/`Speaker` verb: enable MM1→SEC_TDM_RX_0 and the four amp switches, set safe volumes. Drop it in `/usr/share/alsa/ucm2/conf.d/` matching the `snd-sm8150`/"S6" card. 3. Package the UCM in gts6l-alarm so a fresh rootfs has working audio. ## Notes / risks - Four CS35L41 smart amps on SECONDARY TDM at 6.144 MHz — the amps and q6 routing both need their DAPM paths enabled or the PCM reaches nothing. - Channel geometry (which physical amp is FL vs RR) affects placement, not whether sound plays; verify with a per-channel test tone. - Once UCM exists, Plasma should auto-show a "Speaker" sink with no further config. Kernel side is done; this is a focused userspace-config task.
Author
Owner

2026-08-21 (cont.): card + routing work; remaining blocker is the q6 TDM port not starting

Got much further than "no card". Progress and the precise remaining failure:

Done

  • Card instantiates (bd8570fe).
  • Enumerated the routing (clock had to be fixed first — the pacman PGP error was the 1970 clock; date -s then alsa-utils installed). Key controls:
    • q6 route: SEC_TDM_RX_0 Audio Mixer MultiMedia1 (BOOLEAN, was off)
    • per amp: <FL/FR/RL/RR> PCM Source = {ASP, DSP} — ASP bypasses the DSP (no firmware needed), <pfx> Digital PCM Volume 0–913.
  • Added the missing SECONDARY_TDM_RX framing (91cee1ce): our q6afedai had no TDM slot/sync config at all (nabu has 6 qcom,tdm-* props on its quaternary port); added them for port 40.

Remaining blocker — the AFE port won't start

Even with routing set (SEC_TDM_RX_0 Audio Mixer MultiMedia1=1, amps on ASP) and the TDM framing added, a test tone fails at stream prepare:

qcom-q6afe: AFE enable for port 0x9010 failed -110
q6afe-dai: fail to start AFE port 28
ASoC error (-110): at snd_soc_dai_prepare() on SECONDARY_TDM_RX_0
cs35l41 0-004{0..3}: Enable(1) failed: -110   # downstream: no clock

-110 = the ADSP not ACKing the AFE port-enable within the 1 s command timeout. The cs35l41 failures are secondary (no ASP clock because the port never started). So this is q6/ADSP-side TDM port bring-up, not the DT structure or the codec.

Suspects (in order)

  1. LPASS TDM clock for the SECONDARY interface not configured — q6afe may need a clock setup the mainline path isn't doing for this port.
  2. TDM slot width/count defaults wrong (we set sync/delay like nabu but not slot-width/num; nabu didn't either, but Samsung framing may differ).
  3. Samsung ADSP firmware vs mainline q6afe protocol mismatch — we load Samsung's signed ADSP fw via the link-farm; if its AFE port-config ABI differs from what mainline q6afe sends, the port enable would time out regardless of DT. This is the worrying one and would need confirming (e.g. does any other q6 port — a non-TDM one — start?).

Next steps

  • Test whether a non-TDM q6 path starts (e.g. a HDMI/DISPLAY_PORT or SLIMBUS route) to isolate "TDM-specific" vs "all q6afe ports time out" — that single test distinguishes suspect 3 from 1/2.
  • If TDM-specific: compare LPASS clock setup vs a working mainline sm8150/sm8250 TDM device; check whether the machine driver needs snd_soc_dai_set_tdm_slot.
  • UCM authoring is downstream of this — no point until a tone plays.

Card and routing structure are solid; the fight is now the ADSP TDM port.

## 2026-08-21 (cont.): card + routing work; remaining blocker is the q6 TDM port not starting Got much further than "no card". Progress and the precise remaining failure: ### Done - Card instantiates (`bd8570fe`). - Enumerated the routing (clock had to be fixed first — the pacman PGP error was the 1970 clock; `date -s` then `alsa-utils` installed). Key controls: - q6 route: `SEC_TDM_RX_0 Audio Mixer MultiMedia1` (BOOLEAN, was off) - per amp: `<FL/FR/RL/RR> PCM Source` = {ASP, DSP} — **ASP** bypasses the DSP (no firmware needed), `<pfx> Digital PCM Volume` 0–913. - Added the missing **SECONDARY_TDM_RX framing** (`91cee1ce`): our `q6afedai` had no TDM slot/sync config at all (nabu has 6 `qcom,tdm-*` props on its quaternary port); added them for port 40. ### Remaining blocker — the AFE port won't start Even with routing set (`SEC_TDM_RX_0 Audio Mixer MultiMedia1=1`, amps on ASP) and the TDM framing added, a test tone fails at stream prepare: ``` qcom-q6afe: AFE enable for port 0x9010 failed -110 q6afe-dai: fail to start AFE port 28 ASoC error (-110): at snd_soc_dai_prepare() on SECONDARY_TDM_RX_0 cs35l41 0-004{0..3}: Enable(1) failed: -110 # downstream: no clock ``` `-110` = the ADSP not ACKing the AFE port-enable within the 1 s command timeout. The cs35l41 failures are secondary (no ASP clock because the port never started). So this is **q6/ADSP-side TDM port bring-up**, not the DT structure or the codec. ### Suspects (in order) 1. **LPASS TDM clock** for the SECONDARY interface not configured — q6afe may need a clock setup the mainline path isn't doing for this port. 2. TDM slot **width/count** defaults wrong (we set sync/delay like nabu but not slot-width/num; nabu didn't either, but Samsung framing may differ). 3. **Samsung ADSP firmware vs mainline q6afe protocol** mismatch — we load Samsung's signed ADSP fw via the link-farm; if its AFE port-config ABI differs from what mainline q6afe sends, the port enable would time out regardless of DT. This is the worrying one and would need confirming (e.g. does any other q6 port — a non-TDM one — start?). ### Next steps - Test whether a **non-TDM q6 path** starts (e.g. a HDMI/DISPLAY_PORT or SLIMBUS route) to isolate "TDM-specific" vs "all q6afe ports time out" — that single test distinguishes suspect 3 from 1/2. - If TDM-specific: compare LPASS clock setup vs a working mainline sm8150/sm8250 TDM device; check whether the machine driver needs `snd_soc_dai_set_tdm_slot`. - UCM authoring is downstream of this — no point until a tone plays. Card and routing structure are solid; the fight is now the ADSP TDM port.
Author
Owner

2026-08-22: ROOT CAUSE FOUND — the sm8150 machine driver only supports QUATERNARY TDM

The AFE timeout is not our DT and not the codec. sound/soc/qcom/sm8150.c was written for sm8150-xiaomi-nabu, which hangs its CS35L41 amps off QUATERNARY TDM. Ours are on SECONDARY TDM (cpu_dai->id = 0x28 = 40 = SECONDARY_TDM_RX_0), and the driver has three switch (cpu_dai->id) statements that only case on quaternary:

  • sm8150_snd_startup() — sets the LPASS bit clock (Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT, 12288000) and the DAI format
  • sm8150_snd_hw_params() — dispatches to sm8150_tdm_snd_hw_params() (slots, slot width, channel map)
  • sm8150_snd_shutdown() — tears the clock back down

Everything else falls through to default: pr_err("%s: invalid dai id 0x%x"). That message was in our logs the whole time:

sm8150_snd_hw_params: invalid dai id 0x28
sm8150_snd_shutdown: invalid dai id 0x28

So for our port no LPASS bit clock is ever started and no DAI format is set → the ADSP never brings the port up → AFE enable for port 0x9010 failed -110 → the four amps then fail with -110 downstream (no ASP clock). That fully explains the symptom, including why the DT TDM framing (91cee1ce) was necessary but not sufficient.

Fix (in progress)

Patch all three switches to handle SECONDARY_TDM_RX_0 / SECONDARY_TDM_TX_0 alongside quaternary, using Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT (0x202) and a separate sec_tdm_clk_count. This generalises the driver rather than special-casing gts6l, so it should be upstreamable — any sm8150 board with amps on a non-quaternary TDM port hits this.

Note for testing

CONFIG_MODVERSIONS and module signing are both off, so a rebuilt snd-soc-sm8150.ko can be dropped in without a full kernel flash. But make sound/soc/qcom/snd-soc-sm8150.ko fails at modpost (missing Module.symvers in a single-module build) and leaves the old .ko in place — I deployed a stale Aug-19 module on the first attempt and briefly mistook it for the patch not working. Check the .ko mtime against sm8150.o, or just run a full make modules.

Once a tone plays, the remaining work is the UCM profile (original scope of this issue) so PipeWire exposes a real Speaker sink instead of "Dummy Output".

## 2026-08-22: ROOT CAUSE FOUND — the sm8150 machine driver only supports QUATERNARY TDM The AFE timeout is not our DT and not the codec. `sound/soc/qcom/sm8150.c` was written for `sm8150-xiaomi-nabu`, which hangs its CS35L41 amps off **QUATERNARY** TDM. Ours are on **SECONDARY** TDM (`cpu_dai->id` = `0x28` = 40 = `SECONDARY_TDM_RX_0`), and the driver has **three** `switch (cpu_dai->id)` statements that only case on quaternary: - `sm8150_snd_startup()` — sets the LPASS bit clock (`Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT`, 12288000) and the DAI format - `sm8150_snd_hw_params()` — dispatches to `sm8150_tdm_snd_hw_params()` (slots, slot width, channel map) - `sm8150_snd_shutdown()` — tears the clock back down Everything else falls through to `default: pr_err("%s: invalid dai id 0x%x")`. That message was in our logs the whole time: ``` sm8150_snd_hw_params: invalid dai id 0x28 sm8150_snd_shutdown: invalid dai id 0x28 ``` So for our port **no LPASS bit clock is ever started and no DAI format is set** → the ADSP never brings the port up → `AFE enable for port 0x9010 failed -110` → the four amps then fail with `-110` downstream (no ASP clock). That fully explains the symptom, including why the DT TDM framing (`91cee1ce`) was necessary but not sufficient. ### Fix (in progress) Patch all three switches to handle `SECONDARY_TDM_RX_0` / `SECONDARY_TDM_TX_0` alongside quaternary, using `Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT` (0x202) and a separate `sec_tdm_clk_count`. This generalises the driver rather than special-casing gts6l, so it should be upstreamable — any sm8150 board with amps on a non-quaternary TDM port hits this. ### Note for testing `CONFIG_MODVERSIONS` and module signing are both off, so a rebuilt `snd-soc-sm8150.ko` can be dropped in without a full kernel flash. **But** `make sound/soc/qcom/snd-soc-sm8150.ko` fails at modpost (missing `Module.symvers` in a single-module build) and leaves the *old* `.ko` in place — I deployed a stale Aug-19 module on the first attempt and briefly mistook it for the patch not working. Check the `.ko` mtime against `sm8150.o`, or just run a full `make modules`. Once a tone plays, the remaining work is the UCM profile (original scope of this issue) so PipeWire exposes a real Speaker sink instead of "Dummy Output".
Author
Owner

2026-08-22 (cont.): driver gap fixed and confirmed; failure moved deeper into the ADSP

Kernel commit 5a461189af56ASoC: qcom: sm8150: handle secondary TDM as well as quaternary. Patched all three cpu_dai->id switches (startup, hw_params, shutdown) to handle SECONDARY_TDM_RX_0/TX_0 with Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT and its own refcount.

Confirmed effect

invalid dai id count is now 0 (was firing from both hw_params and shutdown on every attempt). The driver now genuinely drives our port instead of ignoring it, so this was a real bug and the patch is right — it generalises the driver rather than special-casing gts6l, and should be upstreamable on its own merits.

New failure point — deeper than the machine driver

qcom-q6afe: AFE enable for port 0x9010 failed -110
qcom-q6afe: AFE set params failed -110
q6afe-dai: ASoC error (-110): at snd_soc_dai_set_sysclk() on SECONDARY_TDM_RX_0

The clock request itself now reaches q6afe and the ADSP does not ack it (-110 = timeout, not a rejection). So this is no longer "the driver ignores our port"; it is "the ADSP will not service AFE commands for the secondary TDM interface".

Hypotheses for whoever picks this up, roughly in order

  1. Clock rate mismatch. The driver hardcodes 12288000 (8 slots x 32-bit x 48 kHz, from sm8150_tdm_snd_hw_params forcing slot_width = 32 for S24_LE). Samsung's downstream runs sec-tdm at 6.144 MHz (8 x 16-bit x 48 kHz). A rate the ADSP does not support could plausibly go unanswered. Testing this means 16-bit slots and 6144000 together — they must be consistent.
  2. Missing pinctrl for the secondary TDM pins. Our DT has no pinmux for the sec-TDM data/bclk/ws lines; downstream does. Would not usually cause an APR timeout, but it is cheap to check.
  3. Samsung ADSP firmware vs mainline q6afe. We load Samsung's signed ADSP image; if its AFE port/clock ABI differs from what mainline sends for TDM, commands would time out regardless of DT. A useful discriminator: does any non-TDM q6afe port (e.g. DisplayPort audio) start? If nothing q6afe-side works, suspect this.

Practical notes

  • CONFIG_MODVERSIONS and module signing are off, so snd-soc-sm8150.ko can be swapped without reflashing — but make sound/soc/qcom/snd-soc-sm8150.ko fails at modpost and silently leaves the old .ko in place. Always check the .ko mtime against sm8150.o, or run a full make modules.
  • PipeWire holds the PCM; stop sddm (or kill pipewire) before speaker-test, or you get Device or resource busy.
  • UCM authoring remains downstream of all this — pointless until a tone actually plays.
## 2026-08-22 (cont.): driver gap fixed and confirmed; failure moved deeper into the ADSP Kernel commit **`5a461189af56`** — `ASoC: qcom: sm8150: handle secondary TDM as well as quaternary`. Patched all three `cpu_dai->id` switches (`startup`, `hw_params`, `shutdown`) to handle `SECONDARY_TDM_RX_0/TX_0` with `Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT` and its own refcount. ### Confirmed effect `invalid dai id` count is now **0** (was firing from both `hw_params` and `shutdown` on every attempt). The driver now genuinely drives our port instead of ignoring it, so this was a real bug and the patch is right — it generalises the driver rather than special-casing gts6l, and should be upstreamable on its own merits. ### New failure point — deeper than the machine driver ``` qcom-q6afe: AFE enable for port 0x9010 failed -110 qcom-q6afe: AFE set params failed -110 q6afe-dai: ASoC error (-110): at snd_soc_dai_set_sysclk() on SECONDARY_TDM_RX_0 ``` The clock request itself now reaches q6afe and **the ADSP does not ack it** (`-110` = timeout, not a rejection). So this is no longer "the driver ignores our port"; it is "the ADSP will not service AFE commands for the secondary TDM interface". ### Hypotheses for whoever picks this up, roughly in order 1. **Clock rate mismatch.** The driver hardcodes 12288000 (8 slots x 32-bit x 48 kHz, from `sm8150_tdm_snd_hw_params` forcing `slot_width = 32` for S24_LE). Samsung's downstream runs sec-tdm at **6.144 MHz** (8 x 16-bit x 48 kHz). A rate the ADSP does not support could plausibly go unanswered. Testing this means 16-bit slots *and* 6144000 together — they must be consistent. 2. **Missing pinctrl for the secondary TDM pins.** Our DT has no pinmux for the sec-TDM data/bclk/ws lines; downstream does. Would not usually cause an APR timeout, but it is cheap to check. 3. **Samsung ADSP firmware vs mainline q6afe.** We load Samsung's signed ADSP image; if its AFE port/clock ABI differs from what mainline sends for TDM, commands would time out regardless of DT. A useful discriminator: does *any* non-TDM q6afe port (e.g. DisplayPort audio) start? If nothing q6afe-side works, suspect this. ### Practical notes - `CONFIG_MODVERSIONS` and module signing are off, so `snd-soc-sm8150.ko` can be swapped without reflashing — but `make sound/soc/qcom/snd-soc-sm8150.ko` fails at modpost and **silently leaves the old .ko in place**. Always check the `.ko` mtime against `sm8150.o`, or run a full `make modules`. - PipeWire holds the PCM; stop `sddm` (or kill pipewire) before `speaker-test`, or you get `Device or resource busy`. - UCM authoring remains downstream of all this — pointless until a tone actually plays.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kit/linux-gts6l#13
No description provided.