I’m following some guidelines (Audio) Linux to play music over the SAI interface (pcm, spdif, tdm).
When building the TorizonOS. it seems that the command
more /proc/asound/cards
outputs – no soundcards –
How to proceed?
Software summary
------------------------------------------------------------
Bootloader: U-Boot
Kernel version: 6.1.80+git.a3eb3a74aa8c #1-TorizonCore Tue Jan 16 14:35:15 UTC 2024
Kernel command line: user_debug=30 root=LABEL=otaroot rootfstype=ext4 quiet logo.nologo vt.global_cursor_default=0 plymouth.ignore-serial-consoles splash fbcon=map:3 ostree=/ostree/boot.1/torizon/acef2d15e42510588a1cf8e5dcaa419052475ca11b03c298cf41ffa123716146/0
Distro name: NAME="TorizonCore Upstream"
Distro version: VERSION_ID=6.6.0-devel-20240328135229-build.0
Distro variant: VARIANT="Minimal"
Hostname: colibri-imx6ull-emmc-15264448
------------------------------------------------------------
Hardware info
------------------------------------------------------------
HW model: Toradex Colibri iMX6ULL 1GB (eMMC) on Colibri Evaluation Board V3
Toradex version: 0062 V1.1A
Serial number: 15264448
Processor arch: armv7l
Dear @bkennis,
Thank you for contacting us. Unfortunately there is no codec on the Colibri iMX6ULL as can be seen in this documentation. For your audio to work you would thusly need a codec to be connected to the SAI/I2S interface and enabled via a device tree or device tree overlay.
Best regards
Collin
Hi collin.tx, thanks for the information. Is there some example of how to create a specific overlay for audio (I2S)?
Bram
Dear Bram,
Since you are using a Colibri iMX6ULL 1GB it has an eMMC and can thusly make use of overlays. At this link you will find a community thread about somebody using a sgtl5000 and SAI for audio as an example. You might get some inspiration from it.
Best regards
Collin
Hi collin.tx,
I also noticed that the Torizon-core doesn’t have “aplay” or “amixer” installed. So i pulled the torizon/weston container and added alsa-utils and libasound2-dev to my Dockerfile. After building the docker image (pushing to my account and pulling it back on the imx6ull). It still doens’t find the aplay binary.
How to troubleshoot this?
Bram
Dear @bkennis,
Have you implemented an external codec on your hardware? If so, which one have you chosen?
If you implemented this hardware you will have to alter the device tree on the carrier board level accordingly.
Following this you will have to create your docker file similar to what is written in this article. You will however need to change the platform from linux/arm64 to your specification (linux/armv7) as well as specifying the correct audio codec you will have chosen.
This should work for what you are trying to implement.
Best regards
Collin
Hi @collin.tx ,
I have an MAX98357a audio codec connected to the SAI3 interface of the Colibri-imx6ULL-eval kit.
It uses pins:
- SODIMM_54 => I2S (BLCK)
- SODIMM_52 => I2S (LRC)
- SODIMM_64 => I2S (DIN)
So i added a custom overlay, in my tcbuild.yaml file.
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2022 Toradex
*/
// Enable I2S on SAI interface
/dts-v1/;
/plugin/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/imx6ul-clock.h>
#include <dt-bindings/pinctrl/imx6ul-pinfunc.h>
/ {
compatible = "toradex,colibri-imx6ull-emmc";
codec_ext: max98357a@0 {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
};
sound {
compatible = "toradex,colibri-imx6ull-emmc",
"simple-audio-card";
simple-audio-card,name = "max98357a";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&dailink_master_cpu>;
simple-audio-card,frame-master = <&dailink_master_cpu>;
simple-audio-card,codec {
sound-dai = <&codec_ext>;
};
dailink_master_cpu: simple-audio-card,cpu {
sound-dai = <&sai3>;
};
};
};
&sai3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
assigned-clocks = <&clks IMX6UL_CLK_SAI3_SEL>,
<&clks IMX6UL_CLK_SAI3>, <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-rates = <2>, <24576000>, <786432000>;
fsl,sai-asynchronous;
//fsl,sai-mclk-direction-output;
status = "okay";
};
&iomuxc {
pinctrl_sai3: sai3grp {
fsl,pins = <
MX6UL_PAD_LCD_DATA13__SAI3_TX_BCLK 0x1F089
MX6UL_PAD_LCD_DATA12__SAI3_TX_SYNC 0x17088
MX6UL_PAD_LCD_DATA15__SAI3_TX_DATA 0x11088
MX6UL_PAD_LCD_DATA14__SAI3_RX_DATA 0x11088
//MX6UL_PAD_LCD_DATA09__SAI3_MCLK 0x17088
>;
};
pinctrl_sai3_mclk: sai3grp_mclk {
fsl,pins = <
MX6UL_PAD_LCD_DATA09__SAI3_MCLK 0x17088
>;
};
};
I think i’m missing the kernel option to enable the MAX98357a.
torizon@colibri-imx6ull-emmc-15264448:~$ zcat /proc/config.gz | grep MAX98357
# CONFIG_SND_SOC_MAX98357A is not set
torizon@colibri-imx6ull-emmc-15264448:~$
I use the following source file for the “torizoncore-builder build” command.
torizon-core-docker-colibri-imx6ull-emmc-Tezi_6.7.0+build.18.tar
dmesg doesn’t show anything about the max98357.
What is the easiest way to enable: CONFIG_SND_SOC_MAX98357A=y
Thanks!
Bram
Dear @bkennis,
Sorry for the massive delay in replying. I am currently checking this out internally.
Best regards
Collin
Hi @collin.tx ,
I’m able to see the max98357a on my system.
torizon@colibri-imx6ull-emmc-15264448:~$ zcat /proc/config.gz | grep MAX98357
CONFIG_SND_SOC_MAX98357A=m
torizon@colibri-imx6ull-emmc-15264448:~$ lsmod
Module Size Used by
cfg80211 819200 0
mcp251x 24576 0
can_dev 40960 1 mcp251x
joydev 20480 0
vf610_adc 16384 0
industrialio_triggered_buffer 16384 1 vf610_adc
kfifo_buf 16384 1 industrialio_triggered_buffer
industrialio 90112 3 vf610_adc,industrialio_triggered_buffer,kfifo_buf
imx_sdma 24576 4
snd_soc_max98357a 16384 1
uio_pdrv_genirq 16384 0
uio 24576 1 uio_pdrv_genirq
libcomposite 65536 0
fuse 122880 1
torizon@colibri-imx6ull-emmc-15264448:~$
i’m now trying the play some wav file with aplay but i get the following error.
torizon@colibri-imx6ull-emmc-15264448:~$ aplay -D hw:0,0 pedro.wav
Playing WAVE 'pedro.wav' : [ 1761.498699] fsl-sai 2030000.sai: failed to derive required Tx rate: 1411200
Signed 16 bit Little Endian, Rate[ 1761.507319] fsl-sai 2030000.sai: ASoC: error at snd_soc_dai_hw_params on 2030000.sai: -22
44100 Hz, Stereo
[ 1761.518349] 2030000.sai-HiFi: ASoC: error at __soc_pcm_hw_params on 2030000.sai-HiFi: -22
aplay: set_params:1416: Unable to install hw params:
ACCESS: RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: 44100
PERIOD_TIME: (125011 125012)
PERIOD_SIZE: 5513
PERIOD_BYTES: 22052
PERIODS: 4
BUFFER_TIME: (500045 500046)
BUFFER_SIZE: 22052
BUFFER_BYTES: 88208
TICK_TIME: 0
torizon@colibri-imx6ull-emmc-15264448:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: max98357a [max98357a], device 0: 2030000.sai-HiFi HiFi-0 [2030000.sai-HiFi HiFi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
torizon@colibri-imx6ull-emmc-15264448:~$
Hi @collin.tx ,
i’m able to play music with the MAX98357A connected to the SAI3 interface.
Using the following changed devicetree:
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2022 Toradex
*/
/dts-v1/;
// Adding extra protocols
#include "imx6ull-colibri-emmc-eval-v3.dts"
/ {
compatible = "toradex,colibri-imx6ull-emmc";
codec_ext: max98357a@0 {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
};
sound {
compatible = "simple-audio-card";
status = "okay";
simple-audio-card,name = "max98357a";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&dailink_master_cpu>;
simple-audio-card,frame-master = <&dailink_master_cpu>;
simple-audio-card,codec {
sound-dai = <&codec_ext>;
};
dailink_master_cpu: simple-audio-card,cpu {
sound-dai = <&sai3>;
};
};
};
&sai3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
assigned-clocks = <&clks IMX6UL_CLK_SAI3_SEL>,
<&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-rates = <2>, <196608000>;
fsl,sai-asynchronous;
status = "okay";
};
&iomuxc {
pinctrl_sai3: sai3grp {
fsl,pins = <
MX6UL_PAD_LCD_DATA13__SAI3_TX_BCLK 0x1F089 // SODIMM_54
MX6UL_PAD_LCD_DATA12__SAI3_TX_SYNC 0x17088 // SODIMM_52
MX6UL_PAD_LCD_DATA15__SAI3_TX_DATA 0x11088 // SODIMM_64
//MX6UL_PAD_SD1_DATA2__CCM_CLKO1 0x17088 // SODIMM_51
MX6UL_PAD_LCD_DATA09__SAI3_MCLK 0x17088 // SODIMM_48
>;
};
};
Below: the I2S output in logic analyzer:
Dear @bkennis,
Thank you very much for sharing your results! I am glad you were able to make it work. Would you mind, if we make this thread public, in case another user is experiencing the same issues?
Best regards
Collin
Hi @collin.tx ,
Yes you can make this thread public.
Best regards
Bram