音频驱动
本文档介绍 RK3588 音频子系统(I2S + ALSA SoC)在 Linux 6.1 内核中的驱动配置、设备树绑定和用户态调试。
适用范围: RK3588 Linux 6.1 Debian 12 / Ubuntu 22.04 系统,C-3588LQ V1.0 + SHIMETAPI-M5-R2A V1.0 底板。
1. 概念基础
1.1 RK3588 音频架构
先认识几个后面反复出现的词。ALSA(Advanced Linux Sound Architecture)是 Linux 内核的音频框架,声卡、音量、播放录音都归它管;I2S 是一种专门传输数字音频的串行总线,CPU 里的 I2S 控制器就是音频数据的出入口;Codec(编解码器)是一颗外接芯片,负责数字音频与模拟声音之间的转换,耳机、喇叭、麦克风都得经过它。
RK3588 的音频方案由下面几部分组成:
- CPU 侧:I2S / TDM / PCM 控制器(多个实例)
- Codec 侧:外接音频编解码器芯片(如 ES8388、ES8323)
- 总线:I2C(控制 Codec 寄存器)+ I2S(音频数据)
- 接口:HDMI 也能输出音频
1.2 常见 Codec / 接口
| Codec | 接口 | 备注 |
|---|---|---|
| ES8388 | I2S + I2C | 通用,低功耗 |
| ES8326 | I2S + I2C | 替代 ES8388 |
| HDMI | 内置 codec | HDMI 输出音频 |
1.3 控制器基地址
| 控制器 | 基地址 |
|---|---|
| I2S0 | 0xfe4b0000 |
| I2S1 | 0xfe510000 |
| I2S2 | 0xfe520000 |
I2S 控制器自己不会发声,它通常经 ASoC(ALSA System on Chip,ALSA 面向嵌入式 SoC 的扩展)与 Codec 绑定,最终在系统里呈现为一张完整的声卡。
2. 准备工作
2.1 硬件清单
| 组件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | C-3588LQ 核心板 + SHIMETAPI-M5-R2A 底板 | 1 | |
| 调试串口线 | USB 转 TTL(3.3V) | 1 | 波特率 1500000 |
| 音频 Codec | ES8388 / ES8326 / HDMI | 1 | I2C + I2S 接口 |
| 扬声器/耳机 | 8 Ω 0.5 W 小喇叭 / 3.5 mm 耳机 | 1 | 用于音频输出测试 |
| 麦克风(可选) | 驻极体麦克风 | 1 | 用于录制测试 |
2.2 引脚连接示例(ES8388)
如果需要自己接转接板或飞线,可按下表把 Codec 的信号接到主控引脚上:
| 主控板引脚 | Codec 引脚 | 功能说明 |
|---|---|---|
| I2S1_SCK | SCLK | I2S 时钟 |
| I2S1_LRCK | WS | I2S 字选择 |
| I2S1_SDO | DSDOUT | I2S 数据输出 |
| I2S1_SDI | DSDIN | I2S 数据输入 |
| I2C1_SDA | SDA | I2C 数据(配置 Codec) |
| I2C1_SCL | SCL | I2C 时钟 |
| 3.3V | VCC | Codec 电源 |
| GND | GND | 共地 |
3. 软件准备
3.1 内核配置
要让内核认识这块声卡,先确认下面这些配置已打开(以 ES8388 为例,具体以底板 Codec 选型为准):
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_ROCKCHIP=y
CONFIG_SND_SOC_ROCKCHIP_I2S=y
CONFIG_SND_SOC_ES8388=y /* 具体以底板 Codec 选型为准 */
CONFIG_SND_SOC_HDMI_CODEC=y
CONFIG_SND_PCM=y
CONFIG_OF=y3.2 设备树(ASoC)
设备树里需要三样东西:i2s1 控制器节点、Codec 节点,再加一个 sound 声卡节点把两者绑在一起。dai-link(数字音频接口链路)描述的就是「哪个 I2S 接哪个 Codec」这条通路:
i2s1: i2s@fe510000 {
compatible = "rockchip,rk3588-i2s", "rockchip,rk3066-i2s";
reg = <0x0 0xfe510000 0x0 0x1000>;
interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru MCLK_I2S1>, <&cru HCLK_I2S1>;
clock-names = "mclk", "hclk";
dmas = <&dmac1 4>, <&dmac1 5>;
dma-names = "tx", "rx";
rockchip,grf = <&sys_grf>;
#sound-dai-cells = <0>;
status = "okay";
};
/* ASoC 声音节点:把 I2S 和 Codec 绑在一起 */
sound: sound {
compatible = "simple-audio-card";
simple-audio-card,name = "rockchip-es8388";
simple-audio-card,dai-link@0 {
format = "i2s";
cpu {
sound-dai = <&i2s1>;
};
codec {
sound-dai = <&es8388>;
};
};
};
es8388: es8388@10 {
compatible = "everest,es8388";
reg = <0x10>; /* I2C 地址 0x10 */
clocks = <&cru MCLK_I2S1>;
clock-names = "mclk";
pinctrl-0 = <&spk_ctl &hp_ctl>;
pinctrl-names = "default";
spk-ctl-gpio = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>;
hp-ctl-gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
status = "okay";
};4. 设备端音频
下面的命令都在板子的串口终端里执行,目的是确认声卡已就位、播放录音链路能跑通。
4.1 查看 ALSA 声卡
cat /proc/asound/cards实机输出:
0 [rockchipes8388 ]: rockchip-es8388 - rockchip-es8388
rockchip-es8388
1 [rockchiphdmi1 ]: rockchip-hdmi1 - rockchip-hdmi1
rockchip-hdmi1这台板子识别出 2 张声卡:
- Card 0:ES8388 Codec(3.5mm 耳机或板载喇叭走此)
- Card 1:HDMI 音频(HDMI 输出设备)
4.2 播放 / 录音
# 列出播放设备
aplay -l实机输出:
**** List of PLAYBACK Hardware Devices ****
card 0: rockchipes8388 [rockchip-es8388], device 0: dailink-multicodecs ES8323 HiFi-0
card 1: rockchiphdmi1 [rockchip-hdmi1], device 0: rockchip-hdmi1 i2s-hifi-0# 列出录音设备
arecord -l实机输出:
**** List of CAPTURE Hardware Devices ****
card 0: rockchipes8388 [rockchip-es8388], device 0: dailink-multicodecs ES8323 HiFi-0这台板子只有 ES8388 支持录音,HDMI 仅播放。
4.3 播放/录制
# 播放 wav
aplay /usr/share/sounds/alsa/Front_Center.wav
# 录音 5 秒 S16_LE 44.1kHz 立体声
arecord -f S16_LE -r 44100 -c 2 -d 5 /tmp/record.wav播放能听到声音、录出来的文件能用 aplay /tmp/record.wav 回放出声音,就说明整条链路都通了。
4.4 音量与控制
没声音时先别急着查驱动,多半是音量或静音的问题:
# 列出可用控件
amixer scontents
# 设置主音量 80%
amixer set 'Master' 80%
# 解除静音
amixer set 'Master' unmute4.5 speaker-test 自检
apt install -y alsa-utils
speaker-test -c 2 -t wav -l 1正常时应能听到左右声道交替响起的测试音。
5. 高级:ALSA SoC 配置(PC 端)
[电脑端] 编辑板级 .dts,确保 ASoC sound 节点绑定正确的 I2S 和 Codec:
&i2s1 {
status = "okay";
pinctrl-0 = <&i2s1_lrck &i2s1_sclk &i2s1_sdi &i2s1_sdo>;
pinctrl-names = "default";
};
&es8388 {
status = "okay";
};电脑端 重新编译烧录:
./build.sh kernel
./mkfirmware.sh烧录重启后,回到板子上再执行一次 4.1 的 cat /proc/asound/cards,能看到声卡就说明配置生效了。
6. 代码解读
6.1 内核驱动注册
I2S 控制器驱动是一个标准的 platform driver,内核靠 compatible 字符串把它和设备树节点对应起来:
// sound/soc/rockchip/rockchip_i2s.c(简化)
static struct platform_driver rockchip_i2s_driver = {
.probe = rockchip_i2s_probe,
.remove = rockchip_i2s_remove,
.driver = {
.name = "rockchip-i2s",
.of_match_table = rockchip_i2s_match,
},
};
static const struct of_device_id rockchip_i2s_match[] = {
{ .compatible = "rockchip,rk3588-i2s" },
{ /* sentinel */ }
};6.2 ALSA 调用链
从敲下 aplay 到喇叭出声,中间经过这几层:
用户空间: aplay Front_Center.wav
→ snd_pcm_open() /* ALSA lib */
→ snd_pcm_hw_params()
→ snd_pcm_start()
→ rockchip_i2s_trigger() /* ASoC I2S driver */
→ 启动 DMA 传输
→ 数据写入 I2S FIFO → 通过 I2S 总线 → Codec7. 故障排除
7.1 声卡未识别
dmesg | grep -i snd
cat /proc/device-tree/soc/i2s@fe510000/status # 应 "okay"如果查不到声卡,常见原因是设备树没使能、Codec 驱动模块未加载,或 I2C 通信失败,可以按这个顺序排查。
7.2 无声
amixer scontents # 看控件
amixer set 'Master' unmute
amixer set 'Master' 80%
speaker-test -c 2另外,输出端没选对也会无声,可以用 aplay -D plughw:0,0 ... 强制选择 Card 0。
7.3 杂音 / 卡顿
cat /sys/kernel/debug/clk/clk_mclk_i2s/clk_rate # 检查 MCLK常见原因:MCLK 频率不匹配(应为 44.1 kHz 的 256 / 384 / 512 倍)、DMA buffer 配置不当、I2C 配置 Codec 寄存器出错。
