环境:
硬件:realtek alc5651
内核:Linux4.4
播放器:aplay
原理图
接口解析:
1. #HPO_L/R:耳机孔的左右声道
2.PHE_DET:检查耳机插入
3.MIC_IN2P/N:mic输入
4.i2c:音频控制线
5.i2s:有5根线:两根音频数据线、三根时钟线
其中:
i2s_lrck是指示当前数据线传输的是左声道还是右声道
i2s_bclk是协调数据线上的数据传输(一个时钟周期,主控、音频编解码芯片从音频线取一bit音频数据)
i2s_mclk是主控供给音频编解码芯片保持正常工作用的时钟
我们看看I2S的官方解释
I2S(Inter IC Sound)总线, 又称集成
电路内置音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准。
该总线专责于音频设备之间的数据传输,广泛应用于各种多媒体系统。
它采用了沿独立的导线传输时钟与数据信号的设计,通过将数据和时钟信号分离,避免了因时差诱发的失真。
一般来说,调试音频需要注意几个参数:
采样率、采样位数、采样通道。
如果用播放器来测试音频的话这三个参数也不需要关注。
下面我们看下如何在rk3399平台下驱动alc5651音频芯片
一个声卡包含cpu_dai, codec_dai, 以及dai_link组成,
cpu dai dirver:I²S driver, spdif driver;
codec driver:rt5640 codec driver;
dai_link driver,也就是machine driver:sound/soc/rockchip/rockchip_rt5640.c。
4.4的内核中支持两种方式创建声卡,一种是通用的simple-card framework,一种是传统的编写自定义的machine driver来创建。”
有两种方法构建声卡,不管哪一种我们都需要符合asoc框架:
至于simple-card framework在 kernelDocumenta
tiondevicetreebindingssoundsimple-card.txt有描述
其源码位于 kernel/sound/soc/generic/simple-card.c
下面我们实践操作,驱动alc5651音频芯片
1.设备树配置
rt5651-sound { //machine 匹配层的驱动节点。
status = "okay"; //默认打开
compatible = "simple-audio-card"; //simple-card framework框架
simple-audio-card,format = "i2s";
simple-audio-card,name = "realtek,rt5651-codec";
simple-audio-card,mclk-fs = <256>; //主控供给编解码芯片用的时钟
simple-audio-card,widgets = //指定相关组件
"Microphone", "Mic Jack", //mic
"Headphone", "Headphone Jack"; //耳机
simple-audio-card,routing = //音频路径,如mic输入、耳机输出走那些通路。
"Mic Jack", "MICBIAS1",
"IN1P", "Mic Jack",
"Headphone Jack", "HPOL",
"Headphone Jack", "HPOR";
simple-audio-card,cpu {
sound-dai = <&i2s0>; //指定cpu接入音频编解码的dai(数字化接口)
};
simple-audio-card,codec {
sound-dai = <&rt5651>; //指定编解码音频接入cpu的dai(数字化接口)
};
};
rt5651: rt5651
@1a {
#sound-dai-cells = <0>;
compatible = "rockchip,rt5651";
reg = <0x1a>;
clocks = <&cru SCLK_I2S_8CH_OUT>;
clock-names = "mclk";
pinctrl-names = "default";
pinctrl-0 = <&i2s_8ch_mclk>;
spk-con-gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>;
hp-det-gpio = <&gpio4 28 GPIO_ACTIVE_LOW>;
};
2.内核配置
CONFIG_SND_SEQUENCER=y
CONFIG_SND_SEQ_DUMMY=y
CONFIG_SND_HRTIMER=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_ROCKCHIP=y
CONFIG_SND_SOC_ROCKCHIP_I2S=y
CONFIG_SND_SOC_RT5651=y //对应于 rt5651.c
CONFIG_SND_SIMPLE_CARD=y //对应于simple-card.c
3.编译并烧写内核
确认下声卡是否注册成功
#cat /proc/asound/cards
0 [realtekrt5651co]: realtek_rt5651- - realtek,rt5651-codec
realtek,rt5651-codec
#ls -l /dev/snd/
drwxr-xr-x 2 root root 60 Jan 18 10:27 by-path
crw-rw---- 1 root audio 116, 2 Jan 18 10:27 controlC0
crw-rw---- 1 root audio 116, 4 Jan 18 10:27 pcmC0D0c
crw-rw---- 1 root audio 116, 3 Jan 18 10:27 pcmC0D0p
crw-rw---- 1 root audio 116, 1 Jan 18 10:27 seq
crw-rw---- 1 root audio 116, 33 Jan 18 10:27 timer
通过命令行播放一个wav文件
#aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: realtekrt5651co [realtek,rt5651-codec], device 0: ff880000.i2s-rt5651-aif1 rt5651-aif1-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
#aplay file.wav -Dplug:default
Playing WAVE 'file.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono
推荐一个Android下一个好用的app"文字装语音",通过它可以将文字生成wav语音放到板子上播放,
用aplay播放wav音频文件时,它会读取wav音频文件的文件头信息来确定pcm格式、采样率、通道数。
一般来说,配置设备树、编译驱动声卡就能起来了(不需要改代码)。
如果读者的驱动没有起来的话,确定三点
1.音频芯片对应的驱动是否参加编译
2.音频芯片对应的设备树节点是否正确并状态为okay、驱动的probe函数是否执行(建议在板端/sys/firmware/devicetree/base/查找你的节点)
3.驱动的控制信号-i2c信号是否正确。
如果实在不行就只能看官方提供的音频硬件电路图、数据手册。看是否是卡在开机时许、电路走线上。
原作者:jin-fa