Rockchip 音频常见问题排查指南 电子说
|
音频问题是嵌入式开发中最让人头疼的一类:现象五花八门(没声音、杂音、变调、断音),根因可能藏在硬件、驱动、DTS、Android HAL 任何一个环节。 这篇文章整理了 Rockchip 平台最常见的音频问题,每个问题都给出现象、排查步骤和解决方案。建议收藏,出问题时直接按图索骥。 |
一、声卡根本没注册出来
现象
cat /proc/asound/cards 为空,或者没有你期望的声卡。
排查步骤
第 1 步:检查 DTS 配置
# 确认设备树里 sound 节点存在且格式正确dtc -I dtb -O dts /boot/dtbs/rockchip/rk3576-evb.dtb | grep -A 20 "simple-audio-card"
重点检查:
•sound-dai 的 phandle 是否指向了正确的节点
•子 DAI 节点(如 i2s0、sai1)的status 是否为"okay"
•CODEC 节点是否存在
第 2 步:检查驱动是否加载
dmesg | grep -E 'simple-card|snd_soc|ASoC|audio'
第 3 步:检查 I2C 设备(外部 CODEC)
i2cdetect -y 0
如果 CODEC 的 I2C 地址没扫出来,先查硬件:上拉电阻、电源、地址引脚电平。

常见错误速查
| 内核日志 | 根因 | 解决 |
| ASoC: no CODEC DAI found | CODEC 节点未定义或 status 不为 okay | 检查 DTS 中的 codec 节点 |
| ASoC: failed to instantiate card -19 | CPU DAI 驱动未加载 | 确认 I2S/SAI 驱动编译进内核 |
| snd_soc_register_card failed | dai_link 配置错误 | 检查 sound-dai phandle 是否有效 |
| failed to get clock | 时钟未在 DTS 中定义 | 补充 clocks /clock-names 属性 |
二、播放完全没声音
这是最高频的问题。按这个流程排查,不要跳步:
流程图
播放无声 │ ├── ① 声卡存在? → cat /proc/asound/cards │ │否 → 回到"声卡未注册"排查 │ │是 │ ▼ ├── ② 设备节点存在? → ls /dev/snd/ │ │否 → 检查 udev / SELinux │ │是 │ ▼ ├── ③ PCM 状态 RUNNING? → cat /proc/asound/card0/pcm0p/sub0/status │ │否 → 检查 hw_params 失败原因 │ │是 │ ▼ ├── ④ 时钟正常? → clk_summary | grep i2s │ │否 → 检查 mclk-fs / PLL 配置 │ │是 │ ▼ ├── ⑤ 输出路径正确? → tinymix | grep path │ │否 → 设置 Playback Path │ │是 │ ▼ ├── ⑥ 增益不为 0? → tinymix | grep volume │ │否 → 设置 DAC Volume │ │是 │ ▼ ├── ⑦ 有数据波形? → 示波器看 SDO │ │否 → 检查 DAI 寄存器配置 │ │是 │ ▼ └── ⑧ 扬声器/耳机正常? │否 → 硬件故障 │是 → 可能是 Android AudioFlinger 层问题
每一步的具体操作
步骤③:确认 PCM 状态
cat /proc/asound/card0/pcm0p/sub0/status# 应该显示 state: RUNNING
如果状态不是 RUNNING,检查 hw_params 是否成功:
cat /proc/asound/card0/pcm0p/sub0/hw_params
步骤⑤:检查播放路径
# Androidtinymix | grep -i "path|output|speaker|headphone"# 设置扬声器输出tinymix "Playback Path" SPK# 或设置耳机输出tinymix "Playback Path" HP
步骤⑥:检查增益
# 确认 DAC Volume 不为 0tinymix | grep -i "volume|gain|dac"# 设置音量(以 ES8388 为例,范围 0-192)tinymix "DAC Volume" 175
步骤⑦:DAPM 电源状态
cat /sys/kernel/debug/asoc/*/dapm/widget | grep -E "Headphone|Speaker|DAC"# 确认相关 widget 的状态是 On
三、录制完全没声音
排查步骤
第 1 步:检查录制路径
tinymix | grep -i "mic|capture|input|record"tinymix "Capture Path" "Main Mic" # 选择主麦克风
第 2 步:检查 MICBIAS
电容麦克风需要偏置电压才能工作:
tinymix | grep -i "micbias"tinymix "MICBIAS" 1 # 开启偏置电压
第 3 步:检查 ADC 增益
tinymix "ADC Volume" 175
第 4 步:检查 CODEC 寄存器
cat /sys/kernel/debug/regmap/0-001c/registers | grep -i "adc|capture"
常见原因速查
| 原因 | 解决 |
| MICBIAS 未开启 | 设置 MICBIAS 控件 |
| 录制路径未选择 | 设置 Capture Path |
| ADC 增益为 0 | 设置 ADC Volume |
| PDM 时钟未配置 | 检查 PDM 驱动和 DTS |
四、播放失真 / 有杂音
先判断失真类型
| 失真表现 | 可能原因 |
| 大音量时破音 | 削波失真:DAC 增益过大,超过量程 |
| 小音量时粗糙 | 量化失真:位深不足 |
| 音调异常 / 速度异常 | 时钟失真:BCLK/LRCK 频率错误 |
| 规律性断音 | 断续失真:XRUN、时钟不同步 |
排查步骤
第 1 步:降低音量测试
# 把 DAC 增益降到一半,看是否还破音tinymix "DAC Volume" 100
如果降低音量后破音消失,说明是削波失真。调小增益,或检查 CODEC 的满量程输出是否和负载匹配。
第 2 步:检查时钟频率
cat /sys/kernel/debug/clk/clk_summary | grep -E 'bclk|lrck'# BCLK 应该 = 采样率 × 位深 × 通道数
第 3 步:检查数据格式
cat /proc/asound/card0/pcm0p/sub0/hw_params | grep format# 确认格式(S16_LE / S24_LE)和 CODEC 支持的一致
五、播放速度过快或过慢
这是时钟问题的典型症状。
根因分析
| 表现 | 原因 | 解决 |
| 播放过快 | BCLK 频率过高 | 检查 mclk-fs 配置 |
| 播放过慢 | BCLK 频率过低 | 检查 PLL 配置 |
| 音调变化 | 采样率设置错误 | 确认 hw_params 中的 rate |
验证方法
# 1. 检查实际时钟频率cat /sys/kernel/debug/clk/clk_summary | grep mclk# 2. 检查播放参数cat /proc/asound/card0/pcm0p/sub0/hw_params | grep rate# 3. 手动计算预期 BCLK# BCLK = rate × width × channels# 例:48000 × 16 × 2 = 1,536,000 Hz
如果mclk-fs 配成了 128 但 CODEC 需要 256,MCLK 就会差一倍,所有下游时钟(BCLK、LRCK)都跟着错,最终表现为播放速度快一倍或慢一倍。
六、规律性断音(咔嗒咔嗒)
可能原因
| 原因 | 说明 | 排查 |
| XRUN | 缓冲区溢出 / 下溢 | echo 7 > /proc/asound/card0/pcm0p/xrun_debug |
| 时钟中断 | PM 休眠导致时钟被切 | 检查电源管理配置 |
| period_size 不匹配 | period 和 buffer 比例不当 | 调整 period/buffer 大小 |
解决 XRUN
# 增大 period 和 bufferaplay -D hw:0,0 --period-size=2048 --buffer-size=8192 test.wav# 或使用 ALSA 插件提供缓冲aplay -D plug:dmix test.wav
如果增大 buffer 后仍频繁 XRUN,检查 CPU 负载:
top# 看是否有进程占用了大量 CPU,导致来不及填充音频 buffer
七、I/O Error
现象
tinyplay: error: pcm_write failed: I/O errortinycap: error: pcm_read failed: I/O error
排查步骤
第 1 步:检查声卡是否被占用
cat /proc/asound/card0/pcm0p/sub0/status# 如果 state: RUNNING 且有 owner_pid,说明被其他进程占用
第 2 步:检查 CODEC 是否掉线
i2cget -f -y 0 0x1c 0x00 b# 如果返回 I/O error,说明 I2C 通信失败
I2C 通信失败常见原因:
•CODEC 复位脚没拉高
•CODEC 电源没起来
•I2C 地址错了
•I2C 总线上拉电阻缺失
第 3 步:检查 DAI 状态
cat /sys/kernel/debug/regmap/ff800000.i2s/registers# 检查 DAI 控制寄存器是否被意外复位
八、HDMI 音频没声音
排查步骤
# 1. 确认 HDMI 声卡存在cat /proc/asound/cards | grep hdmi# 2. 检查 HDMI codec 驱动dmesg | grep hdmi-codec# 3. 检查 DRM 状态(HDMI 音频依赖 DRM 框架)cat /sys/class/drm/card*/status# 4. 检查 HDMI MCLK(通常用 128 倍频)cat /sys/kernel/debug/clk/clk_summary | grep hdmi
注意:HDMI 音频需要显示器 / 电视正确识别到 HDMI 信号后才会初始化。如果显示器没点亮,先解决显示问题。
九、排查思路总结
遇到任何音频问题,记住这个优先级:
1.先软后硬:先确认软件配置正确,再上示波器
2.从外到内:声卡注册→ PCM 设备 → 时钟 → 寄存器 → 硬件信号
3.对比验证:用已知正常的配置做对照,缩小变量范围
4.分段隔离:逐步排除可能原因,不要同时改多处
快速决策树
问题现象 │ ├── 声卡不存在? → 查 DTS / 驱动加载 / I2C │ ├── 播放/录制无声? → 查路径 / 增益 / 时钟 / 路由 │ ├── 声音异常(快/慢/变调)? → 查时钟频率 / mclk-fs │ ├── 杂音/破音? → 查增益 / 格式 / XRUN │ ├── 规律性断音? → 查 XRUN / buffer / CPU 负载 │ └── I/O Error? → 查声卡占用 / I2C 通信 / CODEC 状态
十、还有什么没覆盖到?
这篇文章整理了最常见的问题,但实际项目中总会遇到一些 "奇葩" 情况:
•特定 CODEC 的电源上电时序问题
•多声道数据排列顺序错误
•Android HAL 层路由配置和 DTS 不匹配
•热插拔(耳机插入 / 拔出)时的状态同步问题
你在项目中还遇到过什么奇怪的音频 Bug?欢迎在评论区补充,一起完善这份排查清单。
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !