前言
??????? 本文介绍如何添加 Audio 模块到我们的系统中。在实际的项目中,我们使用的 Audio 模块是 ALC5651。
一、硬件原理图
??????? ALC5651 的硬件原理图如下:
??????? ALC5651 的接口解析:
- #HPO_L/#HPO_R:耳机孔的左右声道;
- MIC1P/MIC1N:mic 输入;
- I2C:音频控制接口;
- I2S:总共有5根线(这里不是指 i2s 标准接口):两根音频数据线(输入/输出)、三根时钟线
??????? 其中:
??????? I2S_LRCK 是指示当前数据线传输的是左声道还是右声道;
??????? I2S_BCLK 是协调数据线上的数据传输(一个时钟周期,主控、音频编解码芯片从音频线上获取一个 Bit 音频数据);
??????? I2S_MCLK 是主控供给音频编解码芯片保持正常工作用的时钟;
一般来说,调试音频需要注意几个参数:采样率、采样位数、采样通道。
二、Audio 相关概念
- CPU DAI:主控端的 Audio Data Interface,比如 I2S,Spdif,Pdm,Tdm;
- CODEC DAI:即 Codec;
- DAI_LINK:绑定 Cpu_Dai 和 Codec_Dai 为一个声卡,等同于 Machine Driver;
- DMAENGINE:用于 CPU 和 I2S/Spdif 等 Dai 之间的 DMA 传输引擎,实际上通过 DMA 来进行数据的搬运。
- DAPM:动态音频电源管理,用于动态管理 Codec 等的电源管理,根据通路的开启配置开关,以达到保证功能的前提下功耗尽量小。
- JACK:耳机的接口检测,大部分使用 Codec 自身的检测机制,小部分使用 IO 来进行模拟。
??????? 代码结构目录如下表:
???????? 一个声卡包含 cpu_dai,codec_dai,以及 dai_link,分别对应 :
- cpu dai driver:比如 I2S driver,spdif driver;
- codec driver:比如 rt5640 codec driver;
- dai_link driver:也就是 machine driver,比如 sound/soc/rockchip/rockchip_rt5640.c。
??????? 4.4 的内核支持两种方式来创建声卡,一种是通用的 simple-card frmakework,一种是传统的编写自定义的 machine driver 来创建。
???????? 有两种方法构建声卡,不管哪一种我们都需要符合 asoc 框架:
???????? Simple card 即简单通用的 machine driver,如果 simple-card 框架足够满足需求,建议优先使用 simple card 框架,简单,方便,且易用。
三、具体实现
3.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>;
};
3.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.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
四、驱动失败
-
音频芯片对应的驱动是否参加编译; -
音频芯片对应的设备树节点是否正确并状态为 okay,驱动的 probe 函数是否执行; 建议在板端 /sys/firmware/devicetree/base/ 查找你的节点 -
驱动的控制信号 -- i2c 信号是否正确。
??????? 本文参考以下文章:
|