E103-W20添加WM8978声卡
前言
在很久之前我看到MT7628AN有i2s接口,于是买了一块WM8978G模块.但因为某些原因,该功能一直没有实现,在国庆期间闲来无事,进行了一番调试,在此记录.
设备环境
- 模组/开发板:E103-W20路由器,具体参考我的工程:E103-W20路由器
- 音频模组:W8978G模组,淘宝极客科技店铺购买
- 系统:OpenWrt 21.02
硬件连接
WM8978 MT2628
DAT(I2C_SDI/eX_sd) I2C_SDI
MCK(I2S_MCLK) I2S_MCLK(refclk)
SCK(I2S_SCLK/BCLK) I2S_SCK
SDB(I2C_SDO/SD) I2C_SDO
FSA(I2S_LRC/WS) I2S_WS
SCL(I2C_SCL) I2C_SCL
SDA(I2C_SDA) I2C_SDA
请注意,MT7628没有I2S_MCLK引脚,这里用的是MT7628的REF_CLKO引脚来代替MCLK.
MT7628的REF_CLKO引脚默认功能是12Mhz参考时钟输出.
设备树实现
// 请在'/'根节点添加以下内容
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "WM8978-Sound-Card";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&codec_dai>;
simple-audio-card,frame-master = <&codec_dai>;
simple-audio-card,mclk-fs = <256>;
cpu_dai: simple-audio-card,cpu {
sound-dai = <&i2s>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&wm8978>;
};
};
//在根节点外添加或者修改以下内容
&i2c {
status = "okay";
clock-frequency = <400000>;
wm8978: wm8978@1a {
status = "okay";
compatible = "wlf,wm8978";
reg = <0x1a>;
#sound-dai-cells = <0>;
};
};
&i2s {
status = "okay";
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&i2s_pins>, <&refclk_pins>;
};
项目编译
因为Openwrt没有提供kmod-soc-wm8978之类的包,所以需要我们在内核中配置.
使用make kernel_menuconfig打开内核配置
请参考以下配置来打开WM8978支持.在这里,我配置的是把WM8978编译成内核模块方便调试,实际可以编译到内核里.
Device Drivers -> I2C support -> <*>I2C Support
Device Drivers -> <*>Sound Card Support -> <*>Advanced Linux Sound Architecture ->
<*> Sound hardware support
[*] Enable OSS Emulation
[*] MIPS sound devices ----
<*> ALSA for SoC audio support --->
<*> SoC Audio (I2S protocol) for Ralink SoC
<*> ASoC Simple sound card support
CODEC drivers --->
<M> Wolfson Microelectronics WM8978 codec
使用make menuconfig打开Openwrt配置
请参考以下配置,kmod-usb-audio用于外接usb声卡,可以选择不编译.
Kernel modules -> I2C support ->
-*- kmod-i2c-core
<*> kmod-i2c-mt7628
Kernel modules -> Sound Support ->
-*- kmod-sound-core
-*- kmod-ac97
<*> kmod-sound-mt7620
-*- kmod-sound-soc-core
<*> kmod-usb-audio
Sound -> <*> alsa-utils
使用make -j32来编译整个系统.编译完成之后,固件位于以下目录:
Openwrt-21.02/bin/targets/ramips/mt76x8/openwrt-ramips-mt76x8-hilink_hlk-7628n-squashfs-sysupgrade.bin
请在刷写完成新固件之后进行下一步.
调试
如果一切顺利,你可以在dmesg日志里看到以下被标注出来的输出:
root@LAPTOP-BQECF4:~# dmesg | grep -E "(i2s|wm89)"
[ 0.875233] rt2880-pinmux pinctrl: i2s is already enabled
[ 0.898742] rt2880-pinmux pinctrl: i2s is already enabled
[ 4.234765] rt2880-pinmux pinctrl: i2s is already enabled
[ 4.400733] rt2880-pinmux pinctrl: i2s is already enabled
[ 4.576246] rt2880-pinmux pinctrl: i2s is already enabled
[ 4.632818] rt2880-pinmux pinctrl: i2s is already enabled
[ 5.427167] rt2880-pinmux pinctrl: i2s is already enabled
[ 16.204231] rt2880-pinmux pinctrl: i2s is already enabled
*** [ 16.226524] ralink-i2s 10000a00.i2s: mclk 480MHz //这一行
[ 16.311999] i2c i2c-0: of_i2c: register /palmbus@10000000/i2c@900/wm8978@1a
[ 16.312146] i2c i2c-0: client [wm8978] registered with bus id 0-001a
[ 16.352430] i2c-core: driver [wm8960] registered
[ 728.571579] wm8978 0-001a: probe
[ 728.572242] i2c-core: driver [wm8978] registered
*** [ 728.590344] asoc-simple-card sound: wm8978-hifi <-> 10000a00.i2s mapping ok //这一行
使用aplay -l列出声卡来检验是否存在wm8978声卡
root@LAPTOP-BQECF4:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: WM8978SoundCard [WM8978-Sound-Card], device 0: ralink-i2s-wm8978-hifi wm8978-hifi-0 [ralink-i2s-wm8978-hifi wm8978-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
可以看到存在WM8978声卡.
使用alsamixer来进行图形化的音频选项修改.使用F6选择声卡,M改变开关,ESC退出
使用aplay播放测试音频,使用-Dhw:CardID,DeviceID
来选择指定声卡,在上面的log可以看到这块声卡cardID为0,DeviceID为0.
aplay -Dhw:0,0 -vv /tmp/test.wav
,这将会播放/tmp/test.wav,请把这个改成你自己的路径.在耳机或者喇叭处聆听是否有声音输出.
问题
首先是dts的问题,这里折腾了很久,被ralink-i2s 10000a00.i2s: mclk 480MHz
这行日志忽悠了,最后通过示波器检验refclk引脚的时钟输出确认refclk的时钟输出是12Mhz.
第二个就是设备树里的widget和route部件,如果写了就会在日志里报错没有sink和source的问题,最后把这两个去掉,让系统自动配置.
第三个就是在我这块WM8978模块上,只有微弱的声音输出,到现在没有确定是模块的问题还是寄存器数值的问题.
寄存器数值可以通过以下命令查看:cat /sys/kernel/debug/regmap/0-001a/registers
.
请注意,由于WM8978在I2C模式下是只写的,寄存器不能读取,所以这里查看的是regmap的写入缓存
鉴于暂时没有能力换一块wm8978,故目前止步于此.
总结与收获
调试很费时间,但是借助D指导(DeepSeek)和不懈搜索,也是感悟良多.几乎把alsa的框架源码和wm8978的源码分析了一整遍.
也参考wm8978的数据手册分析寄存器.通过alsamixer的混音板来反向分析代码和寄存器,大致了解了工作原理.
等以后有时间争取完工.
补充说明
- 2025.10.05
使用stm32F407 USB to I2S方式测试wm8978,发现声音也是很小。可能是wm8978坏了的问题。