After a looong night of tinkering and digging I finally got it working
TL;DR: you can find under [1] a patch or diff file which will make it work. It basically performs three important steps:
- add the sound device to the device tree along with a codec, which is basically the HW device to play it back
- enable I2S (see pinctrl), gdma and configure I2S
- add the driver for the MAX98357A "codec" or hardware playback device to the kernel
FYI: the last point was the step I was missing and in this case it does not work or it seems that nothing is happening
The "MAX98357A" coded or I2S DAC IC is a generic one which accepts standard I2S audio and therefore others should work like PCM5102A etc. with this driver.
Please note: currently the driver outputs on GPIO18 (<&gpio0 18 GPIO_ACTIVE_HIGH>
) the SDMODE signal (active low) which indicates if sound is currently playing. So you cannot use this pin for another peripheral (it is PWM0). However I changed it to 19
(PWM1), because I'm using PWM0 already. I tested both 18/19 and they worked fine for me.
The next thing is now to setup software volume control since we don't want to playback everything at full volume For this you create a file /etc/asound.conf
with the following contents:
pcm.!default {
type plug
slave.pcm "softvol"
}
pcm.softvol {
type softvol
slave {
pcm "hw:0"
}
control {
name "Master"
card 0
}
min_dB -57.2
max_dB -6.2
}
ctl.!default {
type hw
card 0
}
ctl.softvol {
type hw
card 0
}
This will then enable software volume control which can be utilized by the alsa tools. To "activate" this config you need to play a "file"; I'm just doing cat /dev/urandom | aplay
and pressing CTRL+C after 1 sec or so. Then, when running amixer controls
you get:
root@Omega-C8DC:/mnt/sda1# amixer controls
numid=1,iface=MIXER,name='Master'
root@Omega-C8DC:/mnt/sda1#
and now you can control the volume e.g. with: amixer sset 'Master' 50%
I didn't yet figure out why you also need to "activate" the config after reboot and how to configure it "properly" so that it works automatically.
References: (further links which helped me):
- the commit e7d598f from the OnionIoT source repo for the working b177 firmware containing essentially the source for my patch [1]
- a community post which also references two patches with a very close similarity
- yet another side-stream where chaps are trying to get it working
- a discussion to get sound working on OpenWRT (not Omega specific)
- a topic to make SDMODE GPIOs optional
I hope that this explanation/question/how-to is helpful for somebody else, saving time in debugging
Have fun!
[1] Patch file to apply on branch openwrt-18.06
of https://github.com/OnionIoT/source
diff --git a/target/linux/ramips/dts/OMEGA2.dtsi b/target/linux/ramips/dts/OMEGA2.dtsi
index 67910b4ce0..0fdffc9067 100644
--- a/target/linux/ramips/dts/OMEGA2.dtsi
+++ b/target/linux/ramips/dts/OMEGA2.dtsi
@@ -30,6 +30,33 @@
linux,code = <KEY_RESTART>;
};
};
+
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "Audio-I2S";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&cpu_dai_master>;
+ simple-audio-card,frame-master = <&cpu_dai_master>;
+ simple-audio-card,widgets =
+ "Speaker", "External Speaker";
+
+ cpu_dai_master: simple-audio-card,cpu {
+ sound-dai = <&i2s>;
+ };
+
+ dailink0_master: simple-audio-card,codec {
+ sound-dai = <&codec>;
+ };
+ };
+
+ codec: max98357a {
+ #sound-dai-cells = <0>;
+ compatible = "maxim,max98357a";
+ sdmode-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
+ };
+
+
};
&pinctrl {
@@ -51,7 +78,7 @@
i2s {
ralink,group = "i2s";
- ralink,function = "gpio";
+ ralink,function = "i2s";
};
spis {
@@ -164,6 +191,16 @@
status = "okay";
};
+&gdma {
+ status = "okay";
+};
+
+&i2s {
+ #sound-dai-cells = <0>;
+ status = "okay";
+};
+
+
&pwm {
status = "okay";
};
diff --git a/target/linux/ramips/modules.mk b/target/linux/ramips/modules.mk
index 88e83a487f..d9206c1c23 100644
--- a/target/linux/ramips/modules.mk
+++ b/target/linux/ramips/modules.mk
@@ -121,13 +121,15 @@ define KernelPackage/sound-mt7620
CONFIG_SND_RALINK_SOC_I2S \
CONFIG_SND_SIMPLE_CARD \
CONFIG_SND_SIMPLE_CARD_UTILS \
- CONFIG_SND_SOC_WM8960
+ CONFIG_SND_SOC_WM8960 \
+ CONFIG_SND_SOC_MAX98357A
FILES:= \
$(LINUX_DIR)/sound/soc/ralink/snd-soc-ralink-i2s.ko \
$(LINUX_DIR)/sound/soc/generic/snd-soc-simple-card.ko \
$(LINUX_DIR)/sound/soc/generic/snd-soc-simple-card-utils.ko \
- $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8960.ko
- AUTOLOAD:=$(call AutoLoad,90,snd-soc-wm8960 snd-soc-ralink-i2s snd-soc-simple-card)
+ $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8960.ko \
+ $(LINUX_DIR)/sound/soc/codecs/snd-soc-max98357a.ko
+ AUTOLOAD:=$(call AutoLoad,90,snd-soc-wm8960 snd-soc-max98357a snd-soc-ralink-i2s snd-soc-simple-card)
$(call AddDepends/sound)
endef
You should be able to run git apply the-patch.diff
on the current branch if you put the patch into the file the-patch.diff
.