On 8/5/26 23:41, Robin Everaars wrote: > The ACP PDM DMIC emits a full-scale burst at the start of every capture stream. > It is loud and it begins at the same frame every time. On a cold start it lasts > long enough that the far end of a call hears a click on join. > > Hardware and software > ===================== > > ASUS ProArt PX13 HN7306EAC, AMD Strix Halo. Card 1 "amdsoundwire", driver > amd-soundwire, longname > ASUSTeKCOMPUTERINC.-ProArtPX13HN7306EAC-1.0-HN7306EAC. The DMIC array is > /proc/asound/card1 pcm4c, id "acp-dmic-codec dmic-hifi-4", reachable as > hw:1,4 or hw:amdsoundwire,4. Native format S32_LE, 48000 Hz, 2 channels, > single rate. Kernel 7.1.5, alsa-lib and alsa-utils 1.2.16, PipeWire 1.6.8, > NixOS. > > What the burst looks like > ========================= > > Capturing 3 s of a quiet room at 48 kHz gives 304 to 310 samples railed to > +32767 or -32768, and every one of them falls inside frames 21 to 177, i.e. > the first 0.44 to 3.65 ms of the stream. After the first 10 ms there are zero > clipped samples. > > The shape > rules out an analog transient. Printing the first 40 frames shows an > exponentially growing alternating pattern that collapses into a rail, that is > a Nyquist-rate oscillation at 0 dBFS: > > (336, 2529) (311, 2454) ... (4765, 1614) (-14926, -7363) (-32768, -32768) > (3598, -3283) (-817, 2296) (-32768, 32767) (32767, -32768) (-32768, 32767) > (32767, -32768) (-32768, 32767) ... > > Left and right are in antiphase. That reads as an unflushed decimator rather > than anything acoustic. > > Reproducible frame for frame across runs, and across every rate, format and > channel count the PCM accepts. > > The cold start is much worse, and it is the common case > ======================================================= > > The 3.6 ms figure above is the WARM case, where the ACP was already awake. On a > cold start, meaning the ACP had runtime-suspended, a second and far larger > excursion follows: it rails from about 15 ms to about 50 ms and only reaches the > noise floor around 250 ms. > > That is the c > ase that matters in practice. Any userspace audio server suspends > an idle capture node after a few seconds (WirePlumber does it after 5 s), so > every real call join is a cold start. > > The driver produces it > ====================== > > Identical through plain arecord with PipeWire out of the picture: > > arecord -D hw:1,4 -f S32_LE -r 48000 -c 2 -d 6 -t wav /tmp/x.wav > > gives 304 railed samples in frames 21 to 177, against 305 to 307 through > PipeWire. Same start frame, same duration, same shape. > > It also survives band-limiting. Low-passing to 8 kHz and to 4 kHz still leaves > an audible click, so a call codec does not remove it. > > Where it comes from > =================== > > sound/soc/amd/acp/acp-pdm.c has no settling delay, no mute and no discard of > the first frames. acp_dmic_dai_trigger() enables the PDM controller and the DMA > in the same breath, so the decimator's first output words go straight to > userspace. A PDM microphone needs time to settle after its clock starts, and a > > CIC or decimation filter chain needs to flush its state, and neither is waited > for here. > > Other ASoC DMIC paths handle this. snd_soc_dmic has a wakeup_delay module > parameter whose msleep runs at DAPM POST_PMU for exactly this reason. > > What would fix it > ================= > > Any of these, in rough order of preference: > > 1. Discard or mute the first N frames after PDM_ENABLE inside acp-pdm.c, where N > covers the decimator's own settling. That is the cheapest fix and it is > invisible to userspace. > 2. Wait for the microphone to settle between enabling the PDM clock and enabling > the DMA, rather than doing both in acp_dmic_dai_trigger(). > 3. Expose a settling delay the way snd_soc_dmic does, so a platform that needs > longer can set it. Could you please try attached patch? > > A separate, smaller thing on the same device > ============================================ > > There is a standing DC offset of about +0.06 FS on channel 0, roughly -24 dBFS, > present with no acoustic input. It is passed through to user > space, so naive > level meters read about -23 dBFS in a silent room and any AGC treats it as > signal. After an 80 Hz high-pass the real floor is peak -45 dBFS rms -62 dBFS. > > If a DC blocker is expected somewhere in this path, it is not running here. Since the ACP PDM driver is a DSP-less solution, it does not have the capability to apply audio processing effects to mitigate DC offset. A similar issue was reported previously, and applying certain effects in PipeWire helped reduce the DC offset. > > Reproducer > ========== > > # cold start: let the ACP runtime-suspend first, then capture > cat /sys/bus/pci/devices/*/power/runtime_status # wait for suspended > arecord -D hw:1,4 -f S32_LE -r 48000 -c 2 -d 3 -t wav /tmp/cold.wav > > Then look at the first 300 ms. Any tool will do; the railed samples are obvious. > Repeating the capture immediately afterwards gives the shorter warm-start > version, which is a convenient way to see both. > > I have no fix to offer, only the measurements. Happy to test a patch on this > hardware.