Skip to content

bcm2835-i2s: slave-mode capture free-runs and stays poisoned when BCLK is absent at open (FIFO clear needs clock; SYNC timeout is ignored) #7585

Description

@gifflet

Describe the bug

On a Raspberry Pi 4B using an I2S sound card in clock-consumer (slave) mode — a HiFiBerry Digi+ I/O, whose WM8804 S/PDIF receiver provides BCLK/LRCLK recovered from the optical input — opening a capture stream while the external bit clock is absent (source off/unplugged, or the receiver not locked yet) silently corrupts the RX path instead of failing:

  • arecord "completes" absurdly fast (a 10 s capture returns in ~20 ms) with a file of the correct size filled with one repeated DC value;
  • once this happens, the state persists across later, correctly-clocked opens — subsequent captures keep free-running even with the receiver locked and clocks present. Occasionally a later open recovers it (timing-dependent); a reboot always does.

Root cause (from sound/soc/bcm/bcm2835-i2s.c):

  • the FIFO clear (BCM2835_I2S_RXCLR) needs at least 2 PCM clock cycles to take effect — with no external BCLK it silently never completes;
  • the SYNC round-trip wait carries a literal FIXME: This does not seem to work for slave mode! and, on timeout, only logs "I2S SYNC error!" and continues;
  • with stale data at/above the RX DREQ threshold left in the FIFO, DREQ sticks asserted and the DMA re-reads the same dead word at bus speed (tens of MB/s observed) — hence the instant "successful" capture full of garbage;
  • hw_params returns early when TXON/RXON is set and prepare only clears a FIFO it can clock, so the poisoned state survives stream cycles.

Steps to reproduce the behaviour

  1. Raspberry Pi 4B + HiFiBerry Digi+ I/O (dtoverlay=hifiberry-digi), dtparam=audio=on disabled; no signal connected to the S/PDIF input (or source powered off);
  2. arecord -D hw:CARD=sndrpihifiberry -f S16_LE -r 48000 -c 2 -d 10 test.wav
  3. Observe it return in tens of milliseconds with a full-size file containing a single repeated value (instead of blocking or failing);
  4. Connect a valid PCM source and confirm the WM8804 locks (SPDSTAT via i2c);
  5. Repeat the arecord: on most attempts it still free-runs despite the receiver being locked — the FIFO poison from step 2 persists. A reboot restores normal behaviour.

Also reproducible the other way around: with everything healthy, unplugging the source while capture cycles run eventually leaves the same stuck state.

Device (s)

Raspberry Pi 4 Mod. B

System

  • cat /etc/os-release: Debian GNU/Linux 13 (trixie) — Raspberry Pi OS 64-bit
  • uname -a: Linux pi 6.18.34+rpt-rpi-v8 var->green.length may be left uninitialized #1 SMP PREEMPT Debian 1:6.18.34-1+rpt1 (2026-06-09) aarch64
  • vcgencmd version: May 21 2026 11:20:25

Logs

On each affected open:

bcm2835-i2s fe203000.i2s: I2S SYNC error!

Measured free-run signature: 10 s capture returning in 0.02 s wall-clock; continuous capture producing ~40–80 MB/s of a single repeated 16-bit value; /proc/asound/.../status cycling through XRUN.

Additional context

  • Interplay warning: pigpiod's default DMA timing source is also the PCM peripheral; with pigpiod running under default flags this race is lost on virtually every first open (moving pigpiod to -t 0/PWM restores normal behaviour). Users combining pigpio with I2S capture likely hit this and misattribute it.
  • A second, separate problem found while attempting recovery: modprobe -r snd_soc_rpi_wm8804_soundcard snd_soc_wm8804_i2c snd_soc_bcm2835_i2s oopsed in wm8804_i2c_driver_exit on this kernel, so module-reload recovery is not viable (trace available on request).
  • I have a patch validated on this hardware: make bcm2835_i2s_clear_fifos() return an error on SYNC timeout and propagate it in .prepare for the capture-with-stale-RX-data branch, while keeping the hw_params-time clear tolerant (it legitimately runs before a clock consumer's provider is up). Results on the rig: source unplugged + capture open → clean -EIO in ~0.6 s with zero bogus data; source reconnected → very next capture healthy (no reboot); no regressions observed on normal boots/playback. PR to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions