LAG
May 7, 2025, 9:21am
1
With device: AML-S905X-CC-V2 throught I2S port, I just connected a DFR0954 device with following scheme:
Ref alias
Ref functions
DFR0954
I2SOUT-CH01
I2SOUT_CH01
DIN
I2S-LR-CLK
I2S_LR_CLK_OUT
LRC
I2S-AM-CLK
I2S_AM_CLK
BCLK
GND
GND
GND
VDDIO_AO3.3V
3.3V
VIN
For enable DFR0954 device, inside my dts I added new node.
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2020 BayLibre, SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*/
/dts-v1/;
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/sound/meson-aiu.h>
#include "meson-gxl-s905x.dtsi"
/ {
compatible = "libretech,aml-s905x-cc-v2", "amlogic,s905x",
"amlogic,meson-gxl";
model = "Libre Computer AML-S905X-CC V2";
aliases {
serial0 = &uart_AO;
ethernet0 = ðmac;
spi0 = &spifc;
};
chosen {
stdout-path = "serial0:115200n8";
};
emmc_pwrseq: emmc-pwrseq {
compatible = "mmc-pwrseq-emmc";
reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
};
hdmi-connector {
compatible = "hdmi-connector";
type = "a";
port {
hdmi_connector_in: endpoint {
remote-endpoint = <&hdmi_tx_tmds_out>;
};
};
};
leds {
compatible = "gpio-leds";
led-blue {
color = <LED_COLOR_ID_BLUE>;
function = LED_FUNCTION_STATUS;
gpios = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
panic-indicator;
};
led-green {
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_DISK_ACTIVITY;
gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "disk-activity";
};
};
memory@0 {
device_type = "memory";
reg = <0x0 0x0 0x0 0x80000000>;
};
ao_5v: regulator-ao_5v {
compatible = "regulator-fixed";
regulator-name = "AO_5V";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
vin-supply = <&dc_in>;
regulator-always-on;
};
dc_in: regulator-dc_in {
compatible = "regulator-fixed";
regulator-name = "DC_IN";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
vcck: regulator-vcck {
compatible = "regulator-fixed";
regulator-name = "VCCK";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
vin-supply = <&ao_5v>;
regulator-always-on;
};
vcc_card: regulator-vcc_card {
compatible = "regulator-fixed";
regulator-name = "VCC_CARD";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
vin-supply = <&vddio_ao3v3>;
gpio = <&gpio GPIOCLK_1 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
vcc5v: regulator-vcc5v {
compatible = "regulator-fixed";
regulator-name = "VCC5V";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
vin-supply = <&ao_5v>;
gpio = <&gpio GPIOH_3 GPIO_OPEN_DRAIN>;
};
vddio_ao3v3: regulator-vddio_ao3v3 {
compatible = "regulator-fixed";
regulator-name = "VDDIO_AO3V3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
vin-supply = <&ao_5v>;
regulator-always-on;
};
vddio_card: regulator-vddio-card {
compatible = "regulator-gpio";
regulator-name = "VDDIO_CARD";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
gpios-states = <0>;
states = <3300000 0>,
<1800000 1>;
regulator-settling-time-up-us = <200>;
regulator-settling-time-down-us = <50000>;
};
vddio_ao18: regulator-vddio_ao18 {
compatible = "regulator-fixed";
regulator-name = "VDDIO_AO18";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
vin-supply = <&vddio_ao3v3>;
regulator-always-on;
};
vcc_1v8: regulator-vcc_1v8 {
compatible = "regulator-fixed";
regulator-name = "VCC 1V8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
vin-supply = <&vddio_ao3v3>;
regulator-always-on;
};
max98357a: audio-codec {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
status = "okay";
};
sound {
compatible = "amlogic,gx-sound-card";
model = "LIBRETECH-CC-V2";
assigned-clocks = <&clkc CLKID_MPLL0>,
<&clkc CLKID_MPLL1>,
<&clkc CLKID_MPLL2>;
assigned-clock-parents = <0>, <0>, <0>;
assigned-clock-rates = <294912000>,
<270950400>,
<393216000>;
status = "okay";
dai-link-0 {
sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
};
dai-link-1 {
sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
dai-format = "i2s";
mclk-fs = <256>;
codec-0 {
sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
};
};
dai-link-2 {
sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
codec-0 {
sound-dai = <&hdmi_tx>;
};
};
dai-link-3 {
sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
dai-format = "i2s";
mclk-fs = <256>;
pinctrl-0 = <&i2s_out_lr_clk_pins>, <&i2s_out_ch01_pins>, <&i2s_am_clk_pins>;
pinctrl-names = "default";
codec-0 {
sound-dai = <&max98357a>;
};
};
};
};
&max98357a {
status = "okay";
};
&i2c_A {
status = "okay";
pinctrl-0 = <&i2c_a_pins>;
pinctrl-names = "default";
};
&i2c_B {
status = "okay";
pinctrl-0 = <&i2c_b_pins>;
pinctrl-names = "default";
};
&i2c_C {
status = "okay";
pinctrl-0 = <&i2c_c_pins>;
pinctrl-names = "default";
};
&i2c_AO {
status = "okay";
pinctrl-0 = <&i2c_ao_pins>;
pinctrl-names = "default";
};
&aiu {
status = "okay";
};
&cec_AO {
status = "okay";
pinctrl-0 = <&ao_cec_pins>;
pinctrl-names = "default";
hdmi-phandle = <&hdmi_tx>;
};
ðmac {
status = "okay";
};
&internal_phy {
pinctrl-0 = <ð_link_led_pins>, <ð_act_led_pins>;
pinctrl-names = "default";
};
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
pinctrl-names = "default";
};
&hdmi_tx {
status = "okay";
pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
hdmi-supply = <&vcc5v>;
pinctrl-names = "default";
};
&hdmi_tx_tmds_port {
hdmi_tx_tmds_out: endpoint {
remote-endpoint = <&hdmi_connector_in>;
};
};
&saradc {
status = "okay";
vref-supply = <&vddio_ao18>;
};
/* SD card */
&sd_emmc_b {
pinctrl-0 = <&sdcard_pins>;
pinctrl-1 = <&sdcard_clk_gate_pins>;
pinctrl-names = "default", "clk-gate";
bus-width = <4>;
cap-sd-highspeed;
sd-uhs-sdr12;
sd-uhs-sdr25;
sd-uhs-sdr50;
sd-uhs-ddr50;
max-frequency = <100000000>;
disable-wp;
cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
vmmc-supply = <&vcc_card>;
vqmmc-supply = <&vddio_card>;
status = "okay";
};
/* eMMC */
&sd_emmc_c {
pinctrl-0 = <&emmc_pins>;
pinctrl-1 = <&emmc_clk_gate_pins>;
pinctrl-names = "default", "clk-gate";
bus-width = <8>;
cap-mmc-highspeed;
mmc-hs200-1_8v;
max-frequency = <200000000>;
disable-wp;
mmc-pwrseq = <&emmc_pwrseq>;
vmmc-supply = <&vddio_ao3v3>;
vqmmc-supply = <&vcc_1v8>;
status = "okay";
};
&spifc {
status = "okay";
pinctrl-0 = <&nor_pins>;
pinctrl-names = "default";
nor_4u1: flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <3000000>;
};
};
&uart_AO {
status = "okay";
pinctrl-0 = <&uart_ao_a_pins>;
pinctrl-names = "default";
};
&usb {
status = "okay";
dr_mode = "host";
};
&usb2_phy0 {
phy-supply = <&vcc5v>;
};
&usb2_phy1 {
phy-supply = <&vcc5v>;
};
aplay list is:
root@libre:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: LIBRETECHCCV2 [LIBRETECH-CC-V2], device 0: fe.dai-link-0 (*) []
Subdevices: 1/1
Subdevice #0: subdevice #0
root@libre:~#
but when I launch: speaker-test -D hw:0,0 -c 2 -f 48000 -t wav
the speaker connected to DFR0954 not produce any sound.
What am I doing wrong?
Using I2S is not trivial. It’s a combination of hardware and software. You need to write an overlay and merge it. The merging might also need manual editing. Then you need to configure alsamixer to enable the interface. Drivers/devicet-tree interactions also need to be checked.
LAG
June 18, 2025, 8:05am
3
Do you have a snippet for configure right node inside DTS for expose i2s port? (I’m fine with an example that works with other drivers as long as it’s a track to start from)
I suspect only DTS node is relevant for fix issue.
We do not have examples for I2S currently. Did you set the I2S fields in alsamixer?
LAG
June 19, 2025, 9:54am
5
I’m new to i2s in general and alsamixer. so I don’t think I’ve done it.
LAG
June 23, 2025, 6:20pm
6
I solved it by setting the dts in this way (only relevant part):
.......
dfr0954_codec: dfr0954@0 {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
sound-name-prefix = "AIU";
status = "okay";
};
sound {
compatible = "amlogic,gx-sound-card";
model = "LIBRETECH-CC-V2";
audio-aux-devs = <&dfr0954_codec>;
audio-widgets = "Line", "Lineout";
clocks = <&clkc CLKID_MPLL0>,
<&clkc CLKID_MPLL1>,
<&clkc CLKID_MPLL2>;
assigned-clocks = <&clkc CLKID_MPLL0>,
<&clkc CLKID_MPLL1>,
<&clkc CLKID_MPLL2>;
assigned-clock-parents = <0>, <0>, <0>;
assigned-clock-rates = <294912000>,
<270950400>,
<393216000>;
dai-link-0 {
sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
};
dai-link-1 {
sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
dai-format = "i2s";
mclk-fs = <256>;
codec-0 {
sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
};
codec-1 {
sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
};
codec-2 {
sound-dai = <&dfr0954_codec>;
};
};
dai-link-2 {
sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
codec-0 {
sound-dai = <&hdmi_tx>;
};
};
dai-link-3 {
sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
codec-0 {
sound-dai = <&acodec>;
};
};
};
.......
&acodec {
AVDD-supply = <&vddio_ao18>;
status = "okay";
};
&aiu {
status = "okay";
#sound-dai-cells = <2>;
pinctrl-names = "default";
pinctrl-0 = <&i2s_out_ao_clk_pins>, <&i2s_out_lr_clk_pins>, <&i2s_out_ch01_pins>;
};
.......
I hope it can help someone who like me needs to use an i2s amplifier to play audio
1 Like
Thanks for the contribution. We will integrate it into the wiring tool.
LAG
August 5, 2025, 2:14pm
8
For solve issue about cracle and pops with MAX98357A I edited a little bit DTS file (final version). Please keep in mind because amlogic I2S port start with bitclock in wrong polarity (by standard I2S protocol).
The magic line is: bitclock-inversion = <1>;
so biclock polarity is right according with I2S standard protocol rules.
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2020 BayLibre, SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*/
/dts-v1/;
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/sound/meson-aiu.h>
#include "meson-gxl-s905x.dtsi"
/ {
compatible = "libretech,aml-s905x-cc-v2", "amlogic,s905x",
"amlogic,meson-gxl";
model = "Libre Computer AML-S905X-CC V2";
aliases {
serial0 = &uart_AO;
ethernet0 = ðmac;
spi0 = &spifc;
};
chosen {
stdout-path = "serial0:115200n8";
};
emmc_pwrseq: emmc-pwrseq {
compatible = "mmc-pwrseq-emmc";
reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
};
hdmi-connector {
compatible = "hdmi-connector";
type = "a";
port {
hdmi_connector_in: endpoint {
remote-endpoint = <&hdmi_tx_tmds_out>;
};
};
};
leds {
compatible = "gpio-leds";
led-blue {
color = <LED_COLOR_ID_BLUE>;
function = LED_FUNCTION_STATUS;
gpios = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
panic-indicator;
};
led-green {
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_DISK_ACTIVITY;
gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "disk-activity";
};
};
memory@0 {
device_type = "memory";
reg = <0x0 0x0 0x0 0x80000000>;
};
ao_5v: regulator-ao-5v {
compatible = "regulator-fixed";
regulator-name = "AO_5V";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
vin-supply = <&dc_in>;
regulator-always-on;
};
dc_in: regulator-dc-in {
compatible = "regulator-fixed";
regulator-name = "DC_IN";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
vcck: regulator-vcck {
compatible = "regulator-fixed";
regulator-name = "VCCK";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
vin-supply = <&ao_5v>;
regulator-always-on;
};
vcc_card: regulator-vcc-card {
compatible = "regulator-fixed";
regulator-name = "VCC_CARD";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
vin-supply = <&vddio_ao3v3>;
gpio = <&gpio GPIOCLK_1 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
vcc5v: regulator-vcc5v {
compatible = "regulator-fixed";
regulator-name = "VCC5V";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
vin-supply = <&ao_5v>;
gpio = <&gpio GPIOH_3 GPIO_OPEN_DRAIN>;
};
vddio_ao3v3: regulator-vddio-ao3v3 {
compatible = "regulator-fixed";
regulator-name = "VDDIO_AO3V3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
vin-supply = <&ao_5v>;
regulator-always-on;
};
vddio_card: regulator-vddio-card {
compatible = "regulator-gpio";
regulator-name = "VDDIO_CARD";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
gpios-states = <0>;
states = <3300000 0>,
<1800000 1>;
regulator-settling-time-up-us = <200>;
regulator-settling-time-down-us = <50000>;
};
vddio_ao18: regulator-vddio-ao18 {
compatible = "regulator-fixed";
regulator-name = "VDDIO_AO18";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
vin-supply = <&vddio_ao3v3>;
regulator-always-on;
};
vcc_1v8: regulator-vcc-1v8 {
compatible = "regulator-fixed";
regulator-name = "VCC 1V8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
vin-supply = <&vddio_ao3v3>;
regulator-always-on;
};
max98357a: max98357a@0 {
compatible = "maxim,max98357a";
#sound-dai-cells = <0>;
status = "okay";
};
sound {
compatible = "amlogic,gx-sound-card";
model = "LIBRETECH-CC-V2";
clocks = <&clkc CLKID_MPLL0>,
<&clkc CLKID_MPLL1>,
<&clkc CLKID_MPLL2>;
assigned-clocks = <&clkc CLKID_MPLL0>,
<&clkc CLKID_MPLL1>,
<&clkc CLKID_MPLL2>;
assigned-clock-parents = <0>, <0>, <0>;
assigned-clock-rates = <294912000>,
<270950400>,
<393216000>;
dai-link-0 {
sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
};
dai-link-1 {
sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
dai-format = "i2s";
bitclock-inversion = <1>;
mclk-fs = <256>;
codec-0 {
sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
};
codec-1 {
sound-dai = <&max98357a>;
};
};
dai-link-2 {
sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
codec-0 {
sound-dai = <&hdmi_tx>;
};
};
};
};
&aiu {
status = "okay";
#sound-dai-cells = <2>;
pinctrl-names = "default";
pinctrl-0 = <&i2s_out_ao_clk_pins>, <&i2s_out_lr_clk_pins>, <&i2s_out_ch01_pins>;
};
&cec_AO {
status = "okay";
pinctrl-0 = <&ao_cec_pins>;
pinctrl-names = "default";
hdmi-phandle = <&hdmi_tx>;
};
ðmac {
status = "okay";
};
&internal_phy {
pinctrl-0 = <ð_link_led_pins>, <ð_act_led_pins>;
pinctrl-names = "default";
};
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
pinctrl-names = "default";
};
&hdmi_tx {
status = "okay";
pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
hdmi-supply = <&vcc5v>;
pinctrl-names = "default";
};
&hdmi_tx_tmds_port {
hdmi_tx_tmds_out: endpoint {
remote-endpoint = <&hdmi_connector_in>;
};
};
&saradc {
status = "okay";
vref-supply = <&vddio_ao18>;
};
/* SD card */
&sd_emmc_b {
pinctrl-0 = <&sdcard_pins>;
pinctrl-1 = <&sdcard_clk_gate_pins>;
pinctrl-names = "default", "clk-gate";
bus-width = <4>;
cap-sd-highspeed;
sd-uhs-sdr12;
sd-uhs-sdr25;
sd-uhs-sdr50;
sd-uhs-ddr50;
max-frequency = <100000000>;
disable-wp;
cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
vmmc-supply = <&vcc_card>;
vqmmc-supply = <&vddio_card>;
status = "okay";
};
/* eMMC */
&sd_emmc_c {
pinctrl-0 = <&emmc_pins>;
pinctrl-1 = <&emmc_clk_gate_pins>;
pinctrl-names = "default", "clk-gate";
bus-width = <8>;
cap-mmc-highspeed;
mmc-hs200-1_8v;
max-frequency = <200000000>;
disable-wp;
mmc-pwrseq = <&emmc_pwrseq>;
vmmc-supply = <&vddio_ao3v3>;
vqmmc-supply = <&vcc_1v8>;
status = "okay";
};
&spifc {
status = "okay";
pinctrl-0 = <&nor_pins>;
pinctrl-names = "default";
nor_4u1: flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <3000000>;
};
};
&uart_AO {
status = "okay";
pinctrl-0 = <&uart_ao_a_pins>;
pinctrl-names = "default";
};
&usb {
status = "okay";
dr_mode = "host";
};
&usb2_phy0 {
phy-supply = <&vcc5v>;
};
&usb2_phy1 {
phy-supply = <&vcc5v>;
};
1 Like
Thanks so much for reporting this! We will apply this change to the base DT because a lot of users have been complaining about the sound issue.
Please note that there’s a fix upstream for Linux: ASoC: meson: aiu-encoder-i2s: fix bit clock polarity | Patchew
We will have to revert the bootloader patches.