设备树
6.6.52版本Kernel中NXP已经默认在imx6ul-14x14-evk.dtsi中配置好了wm8960的节点,但是是配置在i2c2下,而正点原子阿尔法开发板中wm8960接在i2c1下,所以要把节点从i2c2移到i2c1:
&i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; status = "okay";
/* 省略其他节点 */
codec: wm8960@1a { #sound-dai-cells = <0>; compatible = "wlf,wm8960"; reg = <0x1a>; wlf,shared-lrclk; wlf,hp-cfg = <3 2 3>; wlf,gpio-cfg = <1 3>; clocks = <&clks IMX6UL_CLK_SAI2>; clock-names = "mclk"; };};根节点下还需要创建一个sound节点,NXP默认也已经配置好了:
/ { /* 省略其他节点 */
sound-wm8960 { compatible = "fsl,imx-audio-wm8960"; model = "wm8960-audio"; audio-cpu = <&sai2>; audio-codec = <&codec>; audio-asrc = <&asrc>; hp-det-gpio = <&gpio5 4 0>; audio-routing = "Headphone Jack", "HP_L", "Headphone Jack", "HP_R", "Ext Spk", "SPK_LP", "Ext Spk", "SPK_LN", "Ext Spk", "SPK_RP", "Ext Spk", "SPK_RN", "LINPUT2", "Mic Jack", "LINPUT3", "Mic Jack", "RINPUT1", "AMIC", "RINPUT2", "AMIC", "Mic Jack", "MICB", "AMIC", "MICB"; status = "okay"; /* must add this */ };}注意最后的status = "okay"必须要加,不然ALSA识别不到。
Menuconfig里默认已经启用了wm8960在imx系列board上的区别,ALSA模拟OSS的API也已经关闭,保持默认即可。
alsa-lib & alsa-utils
照着教程来做就可以,不一样的地方在于,65.4.2节移植alsa-utils时,makefile可能会报错:
mv: 无法获取”t-ja.gmo” 的文件状态(stat): 没有那个文件或目录 make[2]: *** [ja.gmo] 错误 1
而且报错不止一个文件,都位于alsaconf/po/下,解决办法是自己创建一个空文件 ~/alsa-utils-xxx/alsaconf/po/t-ja.gmo,缺什么就添加什么,反正alsaconf这个功能暂时用不到。
aplay报错
按照教程执行aplay后kernel报错:
Playing WAVE ‘RWR.wav’ : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
imx-sdma 20ec000.dma-controller: sdma or sdma firmware not ready!
fsl-sai 202c000.sai: ASoC: error at soc_component_trigger on 202c000.sai: -12
aplay: pcm_write:2178: write error: Input/output error
考虑到这四条消息是一起跳出来的,上网查了一圈ASoC错误很少有人提及,一般都是时钟配置有问题,要么就是硬件设计时的错误,但考虑到我直接用的是NXP原厂的设备树,并且板子是现成的开发板,基本可以排除硬件设计原因。因此我猜测问题是由sdma没初始化引起的,因为alsa会调用sdma来进行音频流的传输。
参考这篇文章进行sdma的配置:正点原子I.MAX6ULL kernel6.6移植遇到的问题
配置完成后,重新编译kernel,下载,再调用aplay,就能够成功播放了。
alsactl 提示no such file or directory
参考文章
制作根文件系统的时候没有/var/lock的目录,alsactl默认会在/var/lock目录操作,所以就会失败。解决办法是mkdir -p /var/lock