Subject: RPi CM4 (BCM2711) TDM Master Mode Clock Issue with PCM1865 Slave (4ch Capture)
Hi all,
Goal:
Capture: 4 simultaneous channels from the PCM1865 ADC (slave).
Playback: 2 simultaneous channels to the PCM5122 DAC (slave).
Clocking: CM4 (BCM2711 I2S peripheral) is the TDM master, providing BCLK and LRCK/FSYNC.
Format: 48kHz, TDM DSP_B (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS), 4 slots total, 32-bit slot width.
Hardware:
Raspberry Pi Compute Module 4 Rev 1.1 (BCM2711)
Custom PCB with PCM5242 DAC and PCM1865 ADC
The Problem: ADC Clock Error 0x57
The PCM1865 ADC consistently reports clock errors. Reading its Clock Status register (0x75) always returns 0x57, indicating errors/halts detected on its LRCK, BCK, and SCK inputs. This happens during driver initialization and persists during any audio operation attempts.
As a result:
No audio input is captured from the ADC.
The DAC is also silent (potentially due to shared clocks or initial power/mute state issues addressed in the driver).
Configuration & Modifications Summary:
We've made several modifications across the DTS, machine driver, and CPU DAI driver:
1. Modified DTS Overlay ("arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts"):
Configured the "&i2s" node for TDM master mode ("frame-master", "bitclock-master"), DSP_B format ("format = \"dsp_b\""), 4 slots ("dai-tdm-slot-num = <4>"), and 32-bit width ("dai-tdm-slot-width = <32>").
Removed the unused external oscillator definition ("dacpro_osc").
Full overlay content:
2. Machine Driver ("sound/soc/bcm/hifiberry_dacplusadcpro.c"):
Set correct format (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS) in ".init" using "snd_soc_dai_set_fmt".
Override ADC capture capabilities in ".init" to report "channels_min=4", "channels_max=4".
Explicitly manage power/mute states in ".startup" for both ADC (PCM1865) and DAC (PCM5122).
Set BCLK ratio for all DAIs (CPU, DAC, ADC) in ".hw_params" using "snd_soc_dai_set_bclk_ratio".
Explicitly write key PCM1865 registers ("CLK_CTRL=0x0f", "PCM_CFG=0x13", "TDM_TX_SEL=0x01", etc.) in ".hw_params" after calling the core codec "hw_params" to ensure slave mode and TDM configuration.
Removed direct stream capability definitions from "snd_soc_dai_link" due to kernel version struct differences.
3. CPU DAI Driver ("sound/soc/bcm/bcm2835-i2s.c"):
Applied a polling patch ("regmap_read_poll_timeout" in "bcm2835_i2s_startup") to fix "devmem2" bus errors when accessing I2S registers after enabling the peripheral.
Removed the 2-channel TDM limit check in "bcm2835_i2s_set_dai_tdm_slot".
Assumed the base 6.6 kernel includes the necessary TDM framework support (e.g., "set_tdm_slot").
Diagnostics Summary:
dmesg: Persistently shows "CustomCard: [0x75] Clock Status: 0x57 (LRCK/BCK/SCK HLT/ERR)" for the PCM186x. Also shows "pcm512x 1-004d: No SCLK, using BCLK: -2". Confirms explicit register writes are happening.
clk_summary: Shows "pcm" clock enabled and running at the expected 6.144 MHz (48kHz * 4ch * 32 bits).
devmem2: I2S registers ("CS_A", "MODE_A", "RXC_A", "TXC_A", "DREQ_A") are now accessible (no bus errors after polling patch). Values change during operation, but exact correctness for DSP_B TDM master mode isn't fully verified.
pi@raspberrypi:~ $ sudo devmem2 0xfe203000 w # CS_A (Offset 0x00)
sudo devmem2 0xfe203008 w # MODE_A (Offset 0x08)
sudo devmem2 0xfe20300c w # RXC_A (Offset 0x0C)
sudo devmem2 0xfe203010 w # TXC_A (Offset 0x10)
sudo devmem2 0xfe203014 w # DREQ_A (Offset 0x14)
sudo devmem2 0xfe20301c w # INTSTC_A (Offset 0x1C)
/dev/mem opened.
Memory mapped at address 0x7fb3268000.
Value at address 0xFE203000 (0x7fb3268000): 0x31C02A7
/dev/mem opened.
Memory mapped at address 0x7f9d486000.
Value at address 0xFE203008 (0x7f9d486008): 0x41FC01
/dev/mem opened.
Memory mapped at address 0x7f86cb2000.
Erro no barramento
/dev/mem opened.
Memory mapped at address 0x7f9225a000.
Value at address 0xFE203010 (0x7f9225a010): 0xC018C418
/dev/mem opened.
Memory mapped at address 0x7fb58e7000.
Erro no barramento
/dev/mem opened.
Memory mapped at address 0x7fb6a3e000.
Erro no barramento
arecord: Lists the card ("CustomCard") correctly. "arecord --dump-hw-params" shows 4 channels / S32_LE / 48000 Hz support. Attempting capture ("arecord -D hw:CustomCard,0 -c 4 -f S32_LE -r 48000 test.wav") runs but produces only silence, and the 0x57 error continues in dmesg.
Despite configuration attempts, the BCM2711 I2S peripheral, when acting as a TDM master in DSP_B mode, is likely failing to generate BCLK and/or LRCK signals that meet the PCM1865 slave's requirements. This mismatch causes the PCM1865 to detect clock errors and halt (0x57).
Questions:
1. Has anyone successfully used the "bcm2835-i2s" driver in TDM master mode (DSP_B format) with more than 2 channels on a BCM2711 (Pi 4 / CM4)?
2. Are there known BCM2711 I2S hardware limitations or driver quirks related to TDM master clock generation, especially for >2 channels or DSP_B format?
3. Is there any specific bit manipulation needed in the BCM2835 I2S registers ("MODE_A", "RXC_A", "TXC_A") for DSP_B TDM master mode that the standard driver might be missing?
4. Besides checking dmesg and devmem2, what other debugging steps could help pinpoint the clock signal issue? (e.g., specific "MODE_A" bits to verify? Is an oscilloscope the next logical step?)
5. Is it possible the "pcm186x.c" codec driver is somehow interfering or resetting clock configurations despite the machine driver's explicit overrides?
Any insights, suggestions, or pointers would be greatly appreciated!
Thanks,
nonino
Hi all,
Goal:
Capture: 4 simultaneous channels from the PCM1865 ADC (slave).
Playback: 2 simultaneous channels to the PCM5122 DAC (slave).
Clocking: CM4 (BCM2711 I2S peripheral) is the TDM master, providing BCLK and LRCK/FSYNC.
Format: 48kHz, TDM DSP_B (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS), 4 slots total, 32-bit slot width.
Hardware:
Raspberry Pi Compute Module 4 Rev 1.1 (BCM2711)
Custom PCB with PCM5242 DAC and PCM1865 ADC
The Problem: ADC Clock Error 0x57
The PCM1865 ADC consistently reports clock errors. Reading its Clock Status register (0x75) always returns 0x57, indicating errors/halts detected on its LRCK, BCK, and SCK inputs. This happens during driver initialization and persists during any audio operation attempts.
As a result:
No audio input is captured from the ADC.
The DAC is also silent (potentially due to shared clocks or initial power/mute state issues addressed in the driver).
Configuration & Modifications Summary:
We've made several modifications across the DTS, machine driver, and CPU DAI driver:
1. Modified DTS Overlay ("arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts"):
Configured the "&i2s" node for TDM master mode ("frame-master", "bitclock-master"), DSP_B format ("format = \"dsp_b\""), 4 slots ("dai-tdm-slot-num = <4>"), and 32-bit width ("dai-tdm-slot-width = <32>").
Removed the unused external oscillator definition ("dacpro_osc").
Full overlay content:
Code:
// Definitions for HiFiBerry DAC+ADC PRO/dts-v1/;/plugin/;/ {compatible = "brcm,bcm2835";fragment@0 {target-path = "/";/* REMOVED dacpro_osc definition *//* __overlay__ {dacpro_osc: dacpro_osc {compatible = "hifiberry,dacpro-clk";#clock-cells = <0>;};}; */};frag1: fragment@1 {// Target the actual I2S controllertarget = <&i2s>; // Changed from &i2s_clk_consumer__overlay__ {status = "okay";frame-master; // CPU Frame Masterbitclock-master; // CPU Bit Clock Masterdai-tdm-slot-num = <4>;dai-tdm-slot-width = <32>;format = "dsp_b"; // Specify TDM format (DSP_B for PCM186x slave)};};fragment@2 {target = <&i2c1>;__overlay__ {#address-cells = <1>;#size-cells = <0>;status = "okay";// Codec nodes don't usually need the TDM slot config directlyhb_dac: pcm5122@4d {#sound-dai-cells = <0>;compatible = "ti,pcm5122";reg = <0x4d>;status = "okay"; /* REMOVED clocks property referencing dacpro_osc *//* clocks = <&dacpro_osc>; */};hb_adc: pcm186x@4a {#sound-dai-cells = <0>;compatible = "ti,pcm1865";reg = <0x4a>;status = "okay";};hpamp: hpamp@60 {compatible = "ti,tpa6130a2";reg = <0x60>;status = "disabled";};};};fragment@3 {target = <&sound>;hifiberry_dacplusadcpro: __overlay__ {compatible = "hifiberry,hifiberry-dacplusadcpro";// Reverse order to match C code expectations (DAC=0, ADC=1)audio-codec = <&hb_dac &hb_adc>;i2s-controller = <&i2s>; // Match target in frag1, Changed from &i2s_clk_consumerstatus = "okay";// These properties are currently NOT read by the C driver:// hifiberry-dacplusadcpro,tdm_mode;// hifiberry-dacplusadcpro,channels = <4>;};};__overrides__ {24db_digital_gain =<&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,24db_digital_gain?";slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?",<&frag1>,"target:0=",<&i2s>, // Use &i2s here too if needed<&hifiberry_dacplusadcpro>,"i2s-controller:0=",<&i2s>; // Use &i2s here too if neededleds_off = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,leds_off?";/* Add TDM overrides back if needed */tdm_mode = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,tdm_mode?";channels = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,channels:0";/* debug_level = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,debug_level:0"; */};};2. Machine Driver ("sound/soc/bcm/hifiberry_dacplusadcpro.c"):
Set correct format (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS) in ".init" using "snd_soc_dai_set_fmt".
Override ADC capture capabilities in ".init" to report "channels_min=4", "channels_max=4".
Explicitly manage power/mute states in ".startup" for both ADC (PCM1865) and DAC (PCM5122).
Set BCLK ratio for all DAIs (CPU, DAC, ADC) in ".hw_params" using "snd_soc_dai_set_bclk_ratio".
Explicitly write key PCM1865 registers ("CLK_CTRL=0x0f", "PCM_CFG=0x13", "TDM_TX_SEL=0x01", etc.) in ".hw_params" after calling the core codec "hw_params" to ensure slave mode and TDM configuration.
Removed direct stream capability definitions from "snd_soc_dai_link" due to kernel version struct differences.
3. CPU DAI Driver ("sound/soc/bcm/bcm2835-i2s.c"):
Applied a polling patch ("regmap_read_poll_timeout" in "bcm2835_i2s_startup") to fix "devmem2" bus errors when accessing I2S registers after enabling the peripheral.
Removed the 2-channel TDM limit check in "bcm2835_i2s_set_dai_tdm_slot".
Assumed the base 6.6 kernel includes the necessary TDM framework support (e.g., "set_tdm_slot").
Diagnostics Summary:
dmesg: Persistently shows "CustomCard: [0x75] Clock Status: 0x57 (LRCK/BCK/SCK HLT/ERR)" for the PCM186x. Also shows "pcm512x 1-004d: No SCLK, using BCLK: -2". Confirms explicit register writes are happening.
clk_summary: Shows "pcm" clock enabled and running at the expected 6.144 MHz (48kHz * 4ch * 32 bits).
devmem2: I2S registers ("CS_A", "MODE_A", "RXC_A", "TXC_A", "DREQ_A") are now accessible (no bus errors after polling patch). Values change during operation, but exact correctness for DSP_B TDM master mode isn't fully verified.
pi@raspberrypi:~ $ sudo devmem2 0xfe203000 w # CS_A (Offset 0x00)
sudo devmem2 0xfe203008 w # MODE_A (Offset 0x08)
sudo devmem2 0xfe20300c w # RXC_A (Offset 0x0C)
sudo devmem2 0xfe203010 w # TXC_A (Offset 0x10)
sudo devmem2 0xfe203014 w # DREQ_A (Offset 0x14)
sudo devmem2 0xfe20301c w # INTSTC_A (Offset 0x1C)
/dev/mem opened.
Memory mapped at address 0x7fb3268000.
Value at address 0xFE203000 (0x7fb3268000): 0x31C02A7
/dev/mem opened.
Memory mapped at address 0x7f9d486000.
Value at address 0xFE203008 (0x7f9d486008): 0x41FC01
/dev/mem opened.
Memory mapped at address 0x7f86cb2000.
Erro no barramento
/dev/mem opened.
Memory mapped at address 0x7f9225a000.
Value at address 0xFE203010 (0x7f9225a010): 0xC018C418
/dev/mem opened.
Memory mapped at address 0x7fb58e7000.
Erro no barramento
/dev/mem opened.
Memory mapped at address 0x7fb6a3e000.
Erro no barramento
arecord: Lists the card ("CustomCard") correctly. "arecord --dump-hw-params" shows 4 channels / S32_LE / 48000 Hz support. Attempting capture ("arecord -D hw:CustomCard,0 -c 4 -f S32_LE -r 48000 test.wav") runs but produces only silence, and the 0x57 error continues in dmesg.
Despite configuration attempts, the BCM2711 I2S peripheral, when acting as a TDM master in DSP_B mode, is likely failing to generate BCLK and/or LRCK signals that meet the PCM1865 slave's requirements. This mismatch causes the PCM1865 to detect clock errors and halt (0x57).
Questions:
1. Has anyone successfully used the "bcm2835-i2s" driver in TDM master mode (DSP_B format) with more than 2 channels on a BCM2711 (Pi 4 / CM4)?
2. Are there known BCM2711 I2S hardware limitations or driver quirks related to TDM master clock generation, especially for >2 channels or DSP_B format?
3. Is there any specific bit manipulation needed in the BCM2835 I2S registers ("MODE_A", "RXC_A", "TXC_A") for DSP_B TDM master mode that the standard driver might be missing?
4. Besides checking dmesg and devmem2, what other debugging steps could help pinpoint the clock signal issue? (e.g., specific "MODE_A" bits to verify? Is an oscilloscope the next logical step?)
5. Is it possible the "pcm186x.c" codec driver is somehow interfering or resetting clock configurations despite the machine driver's explicit overrides?
Any insights, suggestions, or pointers would be greatly appreciated!
Thanks,
nonino
Statistics: Posted by nonino — Sat May 03, 2025 9:01 pm