Skip to content

drm: apple: audio: legacy path: 256 KiB audio elements, PM reference held until the DMA stopped - #1697

Open
RyanTheTide wants to merge 4 commits into
integration/aurorafrom
rescue/pr276-dcp-audio-legacy
Open

RyanTheTide wants to merge 4 commits into
integration/aurorafrom
rescue/pr276-dcp-audio-legacy

Conversation

@RyanTheTide

Copy link
Copy Markdown
Contributor

Two DCP audio fixes for the legacy (pre-14.7) audio service on M1 and M2, rebased from #276 by @nekolyanich onto current integration/aurora. The third commit of #276 (a failed START with no sink) is already covered here: a START without a sink now plays into the void and takes no PM reference.

  1. Ask for up to 256 KiB of audio elements. DCP cuts the element catalog off at the end of the buffer and reports 0 bytes used when it does not fit. A Samsung TV behind a USB-C to HDMI adapter has 17312 bytes of elements, so the legacy path's 16 KiB lost the rest. The native 14.7 path already asked for 256 KiB; now both paths use one 256 KiB capacity and one buffer. The buffer and the AFK/osobject call buffers come from kvzalloc(). They are only copied into the DMA buffers.
  2. Put the runtime PM reference only after the DMA terminate. Trigger STOP put the reference right after starting the asynchronous terminate. Without autosuspend the DPA's domain (ps_dpa*) then powered down while SIO could still DMA towards it, SIO crashed with "Shim DMA unavailable", and DP audio stayed down on every output until a reboot. The reference now goes in sync_stop, after snd_dmaengine_pcm_sync_stop(). START takes it once, so a START retried before sync_stop ran does not leak one.
  3. KUnit suite apple-dcpaud-legacy (production trigger and sync_stop, stubbed link calls and DMA channel), plus static stubs for the four audio service calls it needs.

Original authorship and sign-offs are kept on 1 and 2. Thanks to @sithglan for testing #276 natively on a Mac mini M1 (HDMI and USB-C sinks).

Tests

  • KUnit (arm64 qemu, apple-dcpaud*): 23 passed, 1 skipped (unrelated). The new suite passes 5/5. With commits 1 and 2 reverted, all 5 new cases fail: PM usage drops to 0 at STOP before the terminate is waited for, a retried START leaves an extra reference, and the catalog is asked for with 16 KiB.
  • checkpatch.pl --strict: clean apart from the new-file MAINTAINERS note.
  • Hardware rows on M1 Pro and M2: to follow in a comment.

Link: #276

🤖 Generated with Claude Code

nekolyanich and others added 3 commits November 13, 2026 00:41
When the audio elements do not fit the buffer of the get_elements
call, DCP returns them cut off at the buffer's end and reports a used
size of 0. A Samsung TV behind a USB-C to HDMI adapter has 17312 bytes
of elements, so with the 16 KiB the legacy path asked for, everything
past 16 KiB was lost. macOS 13 asks for up to 256 KiB (max_size 0x40000
in the request, 0x43a0 used in the reply for this TV), as the native
14.7 path already does: use that capacity on every firmware. The
native path no longer needs a second buffer of its own.

Allocate the elements buffer and the call buffers with kvzalloc(),
including the ones in afk_service_call_timeout_len() and
afk_service_call_with_reply_len(), which every AFK service call goes
through; they are only copied into the DMA buffers.

Fixes: cb24343 ("gpu: drm: apple: Add DCP audio driver")
Link: #276
Signed-off-by: nekolyanich <me@nekolyanich.com>
Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
…topped

Trigger STOP put the runtime PM reference right after starting the
asynchronous DMA terminate. Without autosuspend that suspends the
device at once and powers its domain (ps_dpa1/ps_dpa2) down while SIO
may still run DMA towards the DPA. SIO then crashed with "Shim DMA
unavailable" and the TERMINATE timed out after it, taking DP audio on
all outputs down until a reboot. On an M2 Pro with two DP sinks an
earlier version of this change on a downstream tree took it from 4 of
4 boots to none in 11.

Put the reference in sync_stop, after snd_dmaengine_pcm_sync_stop()
waited for the terminate. ALSA calls sync_stop at the next hw_params,
prepare or hw_free, at close, at system suspend and at disconnect, not
right after the STOP, so after a drain, an xrun or a stop with the
stream left open the DPA stays powered until then. Waiting inside
trigger would also work (the PCM is nonatomic), but sync_stop is the
hook ALSA has for it, as in the AOP audio driver.

The stream remembers whether it holds the reference. sync_stop runs
outside the stream lock: test and clear it under the lock. START takes
the reference only once, since a START can follow a failed one before
sync_stop ran. A stream that plays into the void without a sink holds
none, as before.

Fixes: f25cb50 ("drm: apple: audio: Implement runtime PM support")
Link: #276
Signed-off-by: nekolyanich <me@nekolyanich.com>
Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
…capacity

KUnit cases for the legacy (pre-14.7) audio service: a stopped or
suspended stream keeps its runtime PM reference until sync_stop has
waited for the DMA terminate, a failed START and a retried one before
sync_stop leave one reference, a stream without a sink takes none, and
the element catalog is asked for with 256 KiB so that a 17312 byte
catalog arrives whole.

The audio service's link and catalog calls get static stubs for this.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
…ll buffers

The AFK service call and audio osobject call buffers now come from
kvzalloc(); give the host harnesses that compile those functions the
same calloc()/free() shims they have for kzalloc().

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
@RyanTheTide

Copy link
Copy Markdown
Contributor Author

M2 MacBook Air (J413) row, one-shot kernel built from d060023 on the fleet config. The M2 has no external display attached, so this covers the sinkless path only.

  • apple_dcp card: 10 of 10 digital-silence streams (S16_LE, 2 ch, 48 kHz, raw zeros to the hw device) reached RUNNING with hw_ptr advancing and closed cleanly afterwards. 8 ran to the end and 2 were stopped with SIGINT.
  • Suspend with a stream open: 3/3 (s2idle rc 0, stream RUNNING again after the wake). s2idle with no stream: 3/3.
  • The audio device stayed runtime-suspended the whole time, which is expected: a stream without a sink takes no PM reference.
  • 0 usage count underflow, 0 Shim DMA unavailable, 0 WARN, 0 element errors, 0 AVC.

The PM change and the 256 KiB element request only run with a sink attached. A row with an HDMI or USB-C display on an M1 or M2 is still to come.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant