作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生在读,研究方向无线联邦学习
擅长领域:驱动开发,嵌入式软件开发,BSP开发
作者主页:一个平凡而乐于分享的小比特的个人主页
文章收录专栏:RK3568驱动开发,本专栏为rk3568驱动开发学习记录
欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

RK3568 音频驱动实验

1. 音频接口简介

1.1 为何需要音频编解码芯片?

​ 处理器要想“听到”外界的声音必须要把外界的声音转化为自己能够理解的“语言”,处理器能理解的就是0和1,也就是二进制数据。所以我们需要先把外界的声音转换为处理器能理解的 0和1,在信号处理领域,外界的声音是模拟信号,处理器能理解的是数字信号,因此这里就涉及到一个模拟信号转换为数字信号的过程,而完成这个功能的就是 ADC 芯片。同理,如果处理器要向外界传达自己的“心声”,也就是放音,那么就涉及到将处理器能理解的 0 和1转化为外界能理解的连续变化的声音,这个过程就是将数字信号转化为模拟信号而完成这个功能的是 DAC 芯片。

​ 音频不单单是能出声、能听到就行。我们往往需要听到的声音动听、录进去的语音贴近真实、可以调节音效、对声音能够进行一些处理(需要 DSP 单元)、拥有
统一的标准接口,方便开发等等。将这些针对声音的各种要求全部叠加到 DAC 和 ADC 芯片上,那么就会得到一个专门用于音频的芯片,也就是音频编解码芯片,英文名字就是 Audio CODEC,所以我们在手机或者电脑的介绍中看到“CODEC”这个词语,一般说的都是音频编解码。
​ 既然音频 CODEC 的本质是 ADC 和 DAC,那么采样率和采样位数就是衡量一款音频CODEC 最重要的指标。比如常见音频采样率有 8K、44.1K、48K、192K甚至 384K 和 768K采样位数常见的有 8 位、16 位、24 位、32 位。采样率和采样位数越高,那么音频 CODEC越能真实的还原声音,也就是大家说的 HIFI。因此大家会看到高端的音频播放器都会有很高的采样率和采样位数,同样的价格也会越高。当然了,实际的效果还与其他部分有关,采样率和采样位数只是其中重要的指标之一。

1.2 RK809 Codec简介

RK809 集成了高性能 24 位 ADC 和高性能 24 位 DAC。录音路径由 MIC PGA 和音频 ADC组成。DAC 将数字信号转换为模拟信号,ab 类驱动器采用实地结构,用于耳机应用,THD 非常低(-90dB @1KHz@-3dBFS 源)。同时,集成了用于扬声器应用的d类驱动程序。扬声器和耳机可以同时使用。集成 I2S 接口,与处理器通信。
RK809音频系统框图 :
在这里插入图片描述

1.3 I2S总线接口

​ I2S(1nter-IC Sound)总线有时候也写作 IS,I2S 是飞利浦公司提出的一种用于数字音频设备之间进行音频数据传输的总线。和 I2C、SPI 这些常见的通信协议一样,I2S 总线用于主控制器和音频 CODEC 芯片之间传输音频数据。因此,要想使用 I2S 协议,主控制器和音频CODEC 都得支持 I2S 协议,RK3568 支持 I2S 协议,RK809 同样也支持 I2S,所以本章实验就是使用 I2S 协议来完成的。I2S 接口需要 3 根信号线(如果需要实现收和发,那么就要 4根信号线,收和发分别使用一根信号线):
SCK:串行时钟信号,也叫做位时钟(BCLK),音频数据的每一位数据都对应一个 SCK,立体声都是双声道的,因此 SCK=2X采样率X采样位数。比如采样率为 44.1KHz、16 位的立体声音频,那么 SCK=2x44100x16=1411200Hz=1.4112MHz。
WS:字段(声道)选择信号,也叫做 LRCK,也叫做帧时钟,用于切换左右声道数据,WS为“1”表示正在传输左声道的数据,WS 为“0”表示正在传输右声道的数据。WS 的频率等于采样率,比如采样率为 44.1KHz 的音频,WS=44.1KHz。
SD:串行数据信号,也就是我们实际的音频数据,如果要同时实现放音和录音,那么就需要 2根数据线,比如 RK809的 SDI和 SDO,就是分别用于录音和放音。不管音频数据是多少位的,数据的最高位都是最先传输的。数据的最高位总是出现在一帧开始后(LRCK 变化)的第2 个 SCK 脉冲处。另外,有时候为了使音频 CODEC 芯片与主控制器之间能够更好的同步,会引入另外一个叫做 MCLK 的信号,也叫做主时钟或系统时钟,一般是采样率的 256 倍或384 倍。下图就是一帧立体声音频时序图:

在这里插入图片描述

2. 硬件原理图

在这里插入图片描述

在这里插入图片描述

J5950端子上部为音频功放输出端口

我们将喇叭接到上面,实物图连接:

在这里插入图片描述

3. 音频驱动使能

​ RK 官方已经写好了 RK809 CODEC 驱动,因此我们直接配置内核使能 RK809 CODEC 驱动即可,按照如下所示步骤使能 RK809 CODEC 驱动。
瑞芯微提供的 RK3568 1inux SDK 默认配置了 RK809 CODEC 驱动,所以我们不用配置了,不过我们需要知道,打开 kermellarch/arm64/configsrockchip linux defconfig 文件,看到以下内容。

3698 # CONFIG_SND_SOC_RK3228 is not set
3699 # CONFIG_SND_SOC_RK3308 is not set
3700 CONFIG_SND_SOC_RK3328=y
3701 # CONFIG_SND_SOC_RK630 is not set
3702 CONFIG_SND_SOC_RK817=y
3703 CONFIG_SND_SOC_RK_CODEC_DIGITAL=y
3704 CONFIG_SND_SOC_RL6231=y
3705 CONFIG_SND_SOC_RT5616=y

第3702行,配置了 RK809 CODEC 驱动,你没有看错,这个就是 RK809 CODEC 驱动,只是写了 RK817,说明 RK809与RK817 CODEC 部分驱动代码做了兼容!
RK809 CODEC 源码路径为 kernel/sound/soc/codecshk817 codec.c。这里我们就不去分析这部分代码了,有兴趣的可以自行去分析,结合RK809的寄存器手册。

3.1 配置电源管理芯片RK809

在使用 RK809 CODEC 之前要使能 RK809,因为音频只属于这个电源管理芯片的一部分而详细请参考kerel/Documentation/devicetree/bindings/mfd/rk809.txt 文档。打开 arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi,找到以下内容。

1088 &i2c0 {
1089     status = "okay";
1090
......
1109     rk809: pmic@20 {
1110         compatible = "rockchip,rk809";
1111         reg = <0x20>;
1112         interrupt-parent = <&gpio0>;
1113         interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
1114
1115         pinctrl-names = "default", "pmic-sleep",
1116                 "pmic-power-off", "pmic-reset";
1117         pinctrl-0 = <&pmic_int>;
1118         pinctrl-1 = <&soc_slppin_slp>, <&rk817_slppin_slp>;
1119         pinctrl-2 = <&soc_slppin_gpio>, <&rk817_slppin_pwrdn>;
1120         pinctrl-3 = <&soc_slppin_gpio>, <&rk817_slppin_rst>;
1121
1122         rockchip,system-power-controller;
1123         wakeup-source;
......
1356         rk809_codec: codec {
1357             #sound-dai-cells = <0>;
1358             compatible = "rockchip,rk809-codec", "rockchip,rk817-codec";
1359             clocks = <&cru I2S1_MCLKOUT>;
1360             clock-names = "mclk";
1361             assigned-clocks = <&cru I2S1_MCLKOUT>, <&cru I2S1_MCLK_TX_IOE>;
1362             assigned-clock-rates = <12288000>;
1363             assigned-clock-parents = <&cru I2S1_MCLKOUT_TX>, <&cru I2S1_MCLKOUT_TX>;
1364             pinctrl-names = "default";
1365             pinctrl-0 = <&i2s1m0_mclk>;
1366             hp-volume = <20>;
1367             spk-volume = <3>;
1368             mic-in-differential;
1369             status = "okay";
1370         };
1371     };

第 1109 行,可以看出 RK809 是挂载在 I2C0 上。上面的配置都是 RK 官方配置好的,或者需要参考配置文档,可以看上面说的Documentation/devicetree/bindings/mfdhk809.txt.第 1356-1370 行,这部分是 RK809 CODEC 音频驱动设备树配置,可以看到 compatible 属性为"rockchip,rk809-codec".“rockchip,rk817-codec”,可以查看 kemel/sound/soc/codecs/rk817 codec.c是否也有类似的字符串,有的话说明就匹配上了,后面代码看到我们是用了 I2S1,mclk 为12288000 Hz。

打开kemel/sound/soc/codecs/rk817 codec.c文件

1346 static const struct of_device_id rk817_codec_dt_ids[] = {
1347     { .compatible = "rockchip,rk817-codec" },
1348     {},
1349 };
1350 MODULE_DEVICE_TABLE(of, rk817_codec_dt_ids);
1351
1352 static struct platform_driver rk817_codec_driver = {
1353     .driver = {
1354            .name = "rk817-codec",
1355            .of_match_table = rk817_codec_dt_ids,
1356            },
1357     .probe = rk817_platform_probe,
1358     .remove = rk817_platform_remove,
1359     .shutdown = rk817_platform_shutdown,
1360 };

可以看到第1347行compatible属性与RK809 CODEC 音频驱动设备树compatible匹配

3.2 声卡设备数配置

​ 上面配置的是音频驱动,现在我们来看看声卡。SimpleCard 是 ASoC(Advanced LinuxSound Architecture,高级 Linux 音频架构) 通用的声卡驱动,可支持大部分标准声卡的添加。RK809也是使用了这个通用的声卡。现在我们来看看这个声卡是如何将 RK809 驱动关联起来的。声卡驱动文件路径sound/soc/generic/simmple-card.c。

打开/kernel/arch/arm64/boot/dts/rockchip/rk3568-linux.dtsi

 41     rk809_sound: rk809-sound {
 42         status = "okay";
 43         compatible = "simple-audio-card";
 44         simple-audio-card,format = "i2s";
 45         simple-audio-card,hp-det-gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
 46         simple-audio-card,name = "rockchip,rk809-codec";
 47         simple-audio-card,widgets = "Headphones", "Headphones Jack";
 48         simple-audio-card,mclk-fs = <256>;
 49         simple-audio-card,cpu {
 50             sound-dai = <&i2s1_8ch>;
 51         };
 52         simple-audio-card,codec {
 53             sound-dai = <&rk809_codec>;
 54         };

第 43行,配置兼容属性为 simple-audio-card,匹配的就是 sound/soc/generic/simple-card.c驱动。
第44行,设置声卡协议格式为 i2s 标准格式。
第46行,”设置声卡的名字为“rockchip,rk809-codec’。
第 48行,默认情况下,mclk 为采样率的 256 倍。
第 49-51 行,这里连接硬件,也就是连接I2S。
第 52-54 行,设置 CODEC 为rk809 codec,也就是我们前面的 RK809 CODEC 音频驱
动。

4. wav格式文件下载

请自行下载qq音乐客户端,再通过qq音乐把歌曲以MP3格式下载到本地,请参考:qq音乐怎么转换mp3格式?两种直接下载MP3格式的方法,各大平台有效

最后通过野葱视频转换器将MP3格式音乐转换成wav格式,请参考:哪里能下载wav格式的音乐?

以下是笔者下载音乐文件格式:

在这里插入图片描述

将.wav格式音乐拷贝到开发板/usr/share/sounds目录下,如图:
在这里插入图片描述

5. GPIO管脚设置

在这里插入图片描述

从原理图可以看出,GPIO3_C3管脚默认值是1,即关闭状态,我们要将其值设置为0

输入命令:

root@RK356X:/usr/share/sounds# gpioset 3 19=0

再输入命令,进行查看确认:

root@RK356X:/usr/share/sounds# gpioget 3 19
0

6. 声卡设置与测试

6.1 amixer使用方法

6.1.1 查看帮助信息

声卡相关选型默认都是关闭的,比如耳机和喇叭的左右声道输出等。因此我们在使用之前一定要先设置好声卡,alsa-utils 自带了 amixer这个声卡设置工具。输入如下命令即可査看 amixer的帮助信息:

amixer --help        //查看帮助信息
root@RK356X:/usr/share/sounds# amixer --help
Usage: amixer <options> [command]

Available options:
  -h,--help       this help
  -c,--card N     select the card
  -D,--device N   select the device, default 'default'
  -d,--debug      debug mode
  -n,--nocheck    do not perform range checking
  -v,--version    print version of this program
  -q,--quiet      be quiet
  -i,--inactive   show also inactive controls
  -a,--abstract L select abstraction level (none or basic)
  -s,--stdin      Read and execute commands from stdin sequentially
  -R,--raw-volume Use the raw value (default)
  -M,--mapped-volume Use the mapped volume

Available commands:
  scontrols       show all mixer simple controls
  scontents       show contents of all mixer simple controls (default command)
  sset sID P      set contents for one mixer simple control
  sget sID        gete mixer simple control
  controls        show all controls for all controls for given card
  cset cID P      set control conteone control

从图 可以看出,amixer 软件命令分为两组,scontrols、scontents、sset 和 sget 为一组。controls、contents、cset 和 cget 为另一组。这两组的基本功能都是一样的,只不过“s“开头的是 simple(简单)组,这一组命令是简化版,本教程最终使用“s”开头的命令设置声卡,因为少输入很多字符。

6.1.2 查看设置项
amixer scontrols       //查看所有设置项
root@RK356X:/usr/share/sounds# amixer scontrols
Simple mixer control 'Playback Path',0
Simple mixer control 'Capture MIC Path',0
6.1.3 查看设置值
amixer scontents    //查看设置值
root@RK356X:/usr/share/sounds# amixer scontents
Simple mixer control 'Playback Path',0
  Capabilities: enum
  Items: 'OFF' 'RCV' 'SPK' 'HP' 'HP_NO_MIC' 'BT' 'SPK_HP' 'RING_SPK' 'RING_HP' 'RING_HP_NO_MIC' 'RING_SPK_HP'
  Item0: 'OFF'
Simple mixer control 'Capture MIC Path',0
  Capabilities: enum
  Items: 'MIC OFF' 'Main Mic' 'Hands Free Mic' 'BT Sco Mic'
  Item0: 'MIC OFF'
6.1.4 设置声卡

知道了设置项和设置值,那么设置声卡就很简单了,直接使用下面命令即可:

amixer sset 设置项目 设置值

或:

amixer cset 设置项目 设置值
6.1.5 获取声卡设置值

如果要读取当前声卡某项设置值的话使用如下命令:

amixer sget 设置项目

amixer cget 设置项目

6.2 音乐播放设置

6.2.1 使用amixer设置声卡

第一次使用声卡之前一定要先使用 amixer 设置声卡,打开耳机或者喇叭,并且设置喇叭或者耳机音量,还有就是开启左右声道,输入如下命令:

amixer cset name='Master Playback Volume' 'on','on'
amixer cset name='Master Playback Volume' '30','30'
6.2.2 使用aplay播放WAV格式音乐

声卡设置好以后就可以使用 aplay 软件播放 wav 格式的音乐测试一下,aplay 也是 alsa-utils提供的。默认已经在/usr/share/sounds 路径下存放了一个音频了,我们可以直接拿来测试,测试命令如下:

aplay /usr/share/sounds/C400004a29p81sntRV.wav

如果一切设置正常的话就会开始播放音乐。

RK3568S声卡测试

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐