Hi all,
I’m having trouble using an audio codec board with a custom device tree overlay (see below) with the Beaglebone Black. When exporting the overlay, the codecs seem to register fine:
dmesg
[ 1375.144463] bone_capemgr bone_capemgr: part_number 'BB-BONE-XA-SK-AU', version 'N/A' [ 1375.152305] bone_capemgr bone_capemgr: slot #4: override [ 1375.157799] bone_capemgr bone_capemgr: Using override eeprom data at slot 4 [ 1375.164864] bone_capemgr bone_capemgr: slot #4: 'Override Board Name,00A0,Override Manuf,BB-BONE-XA-SK-AU' [ 1375.206351] bone_capemgr bone_capemgr: slot #4: dtbo 'BB-BONE-XA-SK-AU-00A0.dtbo' loaded; overlay id #0 [ 1375.464260] cs4270 2-0048: found device at i2c address 48 [ 1375.469699] cs4270 2-0048: hardware revision 3 [ 1375.485782] cs4270 2-0049: found device at i2c address 49 [ 1375.491222] cs4270 2-0049: hardware revision 3 [ 1375.504744] (NULL device *): Setting gpio_int_masterclk_enable = 0 [ 1375.513334] asoc-simple-card ocp:sound: cs4270-hifi <-> 48038000.mcasp mapping ok [ 1375.521095] (NULL device *): Setting gpio_int_masterclk_enable = 0 [ 1375.529893] asoc-simple-card ocp:sound: cs4270-hifi <-> 48038000.mcasp mapping ok
aplay -l
`
**** List of PLAYBACK Hardware Devices ****
card 0: XMOSAudioSlice [XMOS-Audio-Slice], device 0: davinci-mcasp.0-cs4270-hifi-a cs4270-hifi-0
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: XMOSAudioSlice [XMOS-Audio-Slice], device 1: davinci-mcasp.0-cs4270-hifi-b cs4270-hifi-1
Subdevices: 1/1
Subdevice #0: subdevice #0
`
lsmod:
`
snd_soc_davinci_mcasp 14391 2
snd_soc_simple_card 8156 0
snd_soc_edma 1150 1 snd_soc_davinci_mcasp
snd_soc_cs4270 6875 2
snd_soc_omap 2573 1 snd_soc_davinci_mcasp
snd_soc_core 156881 5 snd_soc_davinci_mcasp,snd_soc_edma,snd_soc_omap,snd_soc_simple_card,snd_soc_cs4270
snd_compress 11668 1 snd_soc_core
snd_pcm_dmaengine 5061 2 snd_soc_core,snd_soc_omap
snd_pcm 77081 4 snd_soc_davinci_mcasp,snd_soc_core,snd_soc_omap,snd_pcm_dmaengine
snd_timer 16860 1 snd_pcm
snd 56902 4 snd_soc_core,snd_timer,snd_pcm,snd_compress
soundcore 6869 1 snd
pvrsrvkm 147014 0
omap_aes 13089 0
omap_sham 19190 0
tda998x 11683 1
tilcdc 27919 0
omap_rng 4354 0
rng_core 7270 1 omap_rng
drm_kms_helper 106610 3 tda998x,tilcdc
uio_pdrv_genirq 3317 0
leds_gpio 3102 0
uio 8330 1 uio_pdrv_genirq
`
but when I try to play an audio file I get a stream of transmit buffer underflows and no audio:
aplay test128.wav
Playing WAVE 'test128.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo underrun!!! (at least 1.630 ms long) underrun!!! (at least 5.413 ms long) underrun!!! (at least 0.636 ms long) underrun!!! (at least 5.369 ms long) underrun!!! (at least 0.217 ms long) underrun!!! (at least 0.641 ms long) underrun!!! (at least 5.254 ms long)
dmesg
[ 1493.190031] davinci-mcasp 48038000.mcasp: Transmit buffer underflow [ 1493.201647] davinci-mcasp 48038000.mcasp: Transmit buffer underflow [ 1493.218719] davinci-mcasp 48038000.mcasp: Transmit buffer underflow [ 1493.229946] davinci-mcasp 48038000.mcasp: Transmit buffer underflow [ 1493.245328] davinci-mcasp 48038000.mcasp: Transmit buffer underflow [ 1493.259411] davinci-mcasp 48038000.mcasp: Transmit buffer underflow [ 1493.270549] davinci-mcasp 48038000.mcasp: Transmit buffer underflow
Using a software oscilloscope, I can see that the frame clock starts on mcasp0_fsx frame clock line but stops after a few periods. There’s no activity on the on the mcasp0_axr2 audio out line.
This might be related to the problem mentioned here, but I couldn’t see a solution for it. I might also have missed something trivial. Any pointers or help would be much appreciated.
Additional information:
I’m using the v4.1.3-bone15 linux kernel with debian-8.1-minimal-armhf-2015-06-09 compiled as per Robert C Nelsons instructions here.
The board I’m using is an XMOS XA-SK-AUDIO slice and consists of two Cirrus Logic cs4270 codecs and an onboard oscillator generating the master clock. I’ve interfaced the board to a XMOS micro controller to make sure the board is in working order (and it is). When connected to the BBB, reset de-assertion and some initial i2c codec configuration (setting the codecs in software mode) are handled by the same XMOS micro controller.
The overlay I’m using (compiled and installed using bb-overlays) looks like this:
`
/dts-v1/;
/plugin/;
/ {
compatible = “ti,beaglebone”, “ti,beaglebone-black”;
part-number = “BB-BONE-XA-SK-AU”;
version = “00A0”;
exclusive-use =
/* pin header usage /
“P9.25”, / mcasp0_ahclkx ← MCLK /
“P9.31”, / mcasp0_aclkx ↔ BCLK*/
“P9.29”, /* mcasp0_fsx ↔ LRCLK /
“P9.30”, / mcasp0_axr0 ← ADC_DATA0 /
“P9.41”, / mcasp0_axr1 ← ADC_DATA1 /
“P9.28”, / mcasp0_axr2 → DAC_DATA0 /
“P9.27”, / mcasp0_axr3 → DAC_DATA1 /
/ hardware ip usage /
“gpio0_15”, / ext-mclk-sel → MCLK_FSEL /
“gpio0_20”, / CLKOUT2 disabled /
“gpio1_27”, / internal 24.576 MHz oscillator disabled */
“mcasp0”;
fragment@0 {
target = <&am33xx_pinmux>;
overlay {
i2c2_pins: pinmux_i2c2_pins {
pinctrl-single,pins = <
/* Pullup resistors available on codec board /
0x17c 0x2b / i2c2_scl, (PIN_INPUT | MUX_MODE3) /
0x178 0x2b / i2c2_sda, (PIN_INPUT | MUX_MODE3) */
;
};
mcasp0_pins: pinmux_mcasp0_pins {
pinctrl-single,pins = <
0x1ac 0x20 /* mcasp0_ahclkx, (PIN_INPUT_PULLDOWN | MUX_MODE0) /
0x190 0x20 / mcasp0_aclkx, (PIN_INPUT_PULLDOWN | MUX_MODE0) /
0x194 0x20 / mcasp0_fsx, (PIN_INPUT_PULLDOWN | MUX_MODE0) /
0x198 0x20 / mcasp0_axr0, (PIN_INPUT_PULLDOWN | MUX_MODE0) /
0x1a8 0x20 / mcasp0_axr1, (PIN_INPUT_PULLDOWN | MUX_MODE0) /
0x19c 0x02 / mcasp0_axr2, (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /
0x1a4 0x02 / mcasp0_axr3, (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /
/ disable internal 24.576 MHz oscillator /
0x06c 0x07 / gpio1_27, (PIN_OUTPUT_PULLDOWN | MUX_MODE7) */
;
};
gpio_pins: pinmux_gpio_pins {
pinctrl-single,pins = <
/* ext-mclk-sel /
0x184 0x17 / gpio0_15, (PIN_OUTPUT_PULLUP | MUX_MODE7) /
/ disable CLKOUT2 to allow usage of mcasp0_axr1 on P9_41 /
0x1b4 0x2b / gpio0_20, (PIN_INPUT | MUX_MODE3) */
;
};
};
};
fragment@1 {
target = <&i2c2>;
overlay {
pinctrl-names = “default”;
pinctrl-0 = <&i2c2_pins>;
status = “okay”;
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <100000>;
cs4270m: cs4270@48 {
compatible = “cirrus,cs4270”;
status = “okay”;
#sound-dai-cells = <0>;
reg = <0x48>;
name-prefix = “a”;
va-supply = <&ldo4_reg>;
vd-supply = <&ldo4_reg>;
vlc-supply = <&ldo4_reg>;
};
cs4270s: cs4270@49 {
compatible = “cirrus,cs4270”;
status = “okay”;
#sound-dai-cells = <0>;
reg = <0x49>;
name-prefix = “b”;
va-supply = <&ldo4_reg>;
vd-supply = <&ldo4_reg>;
vlc-supply = <&ldo4_reg>;
};
};
};
fragment@2 {
target = <&mcasp0>;
overlay {
pinctrl-names = “default”;
pinctrl-0 = <&mcasp0_pins>;
status = “okay”;
#sound-dai-cells = <0>;
op-mode = <0>; // MCASP_IIS_MODE
tdm-slots = <2>;
num-serializer = <4>;
serial-dir = < // 0: INACTIVE, 1: TX, 2: RX
2 2 1 1
;
tx-num-evt = <1>;
rx-num-evt = <1>;
};
};
fragment@3 {
target = <&ocp>;
overlay {
sound {
compatible = “simple-audio-card”;
simple-audio-card,name = “XMOS-Audio-Slice”;
simple-audio-card,widgets =
“Line”, “Line In 1”,
“Line”, “Line Out 1”,
“Line”, “Line In 2”,
“Line”, “Line Out 2”
;
simple-audio-card,routing =
“a AINA”, “Line In 1”,
“a AINB”, “Line In 1”,
“Line Out 1”, “a AOUTA”,
“Line Out 1”, “a AOUTB”,
“b AINA”, “Line In 2”,
“b AINB”, “Line In 2”,
“Line Out 2”, “b AOUTA”,
“Line Out 2”, “b AOUTB”
;
simple-audio-card,int-masterclk-enable = <&gpio1 27 0>;
simple-audio-card,dai-link@1 {
format = “i2s”;
frame-master = <&cpu_node1>;
bitclock-master = <&cpu_node1>;
cpu_node1: cpu {
sound-dai = <&mcasp0>;
system-clock-frequency = <24576000>;
};
codec_node1: codec {
sound-dai = <&cs4270s>;
system-clock-frequency = <24576000>;
};
};
simple-audio-card,dai-link@0 {
format = “i2s”;
frame-master = <&cpu_node0>;
bitclock-master = <&cpu_node0>;
cpu_node0: cpu {
sound-dai = <&mcasp0>;
system-clock-frequency = <24576000>;
};
codec_node0: codec {
sound-dai = <&cs4270m>;
system-clock-frequency = <24576000>;
};
};
};
};
};
};
`
I’ve also made the following modifications to cs4270.c, simple-card.c, and soc-core.c to add a mechanism to disable the internal BBB master clock, as well as to fix issues with missing source/sink widgets,
[ 137.408549] cs4270 2-0048: ASoC: no source widget found for AINA [ 137.414737] cs4270 2-0048: ASoC: Failed to add route AINA -> direct -> Capture [ 137.422016] cs4270 2-0048: ASoC: no source widget found for AINB [ 137.428137] cs4270 2-0048: ASoC: Failed to add route AINB -> direct -> Capture [ 137.435477] cs4270 2-0048: ASoC: no sink widget found for AOUTA [ 137.441445] cs4270 2-0048: ASoC: Failed to add route Playback -> direct -> AOUTA [ 137.448928] cs4270 2-0048: ASoC: no sink widget found for AOUTB [ 137.454922] cs4270 2-0048: ASoC: Failed to add route Playback -> direct -> AOUTB
and name collisions:
[ 51.364492] asoc-simple-card ocp:sound: control 2:0:0:Master Playback Volume:0 is already present [ 51.373469] cs4270 2-0049: ASoC: Failed to add Master Playback Volume: -16 ... [ 51.393905] ------------[ cut here ]------------ [ 51.398561] WARNING: CPU: 0 PID: 44 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x51/0x5c() [ 51.406281] sysfs: cannot create duplicate filename '/devices/platform/ocp/ocp:sound/davinci-mcasp.0-cs4270-hifi'
`
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index e6d4ff9…4805747 100644
— a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -140,11 +140,11 @@ struct cs4270_private {
};
static const struct snd_soc_dapm_widget cs4270_dapm_widgets = {
-SND_SOC_DAPM_INPUT(“AINL”),
-SND_SOC_DAPM_INPUT(“AINR”),
+SND_SOC_DAPM_INPUT(“AINA”),
+SND_SOC_DAPM_INPUT(“AINB”),
-SND_SOC_DAPM_OUTPUT(“AOUTL”),
-SND_SOC_DAPM_OUTPUT(“AOUTR”),
+SND_SOC_DAPM_OUTPUT(“AOUTA”),
+SND_SOC_DAPM_OUTPUT(“AOUTB”),
};
static const struct snd_soc_dapm_route cs4270_dapm_routes = {
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 33feee9…1383b0f 100644
— a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -28,6 +28,7 @@ struct simple_card_data {
struct asoc_simple_dai codec_dai;
} *dai_props;
unsigned int mclk_fs;
- int gpio_int_masterclk_enable;
int gpio_hp_det;
int gpio_hp_det_invert;
int gpio_mic_det;
@@ -50,7 +51,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
ret = clk_prepare_enable(dai_props->cpu_dai.clk);
if (ret)
return ret;