当前位置:首页>Linux>RockChip Linux SDK ALSA 配置实战 — RK730+ES7210

RockChip Linux SDK ALSA 配置实战 — RK730+ES7210

  • 2026-09-07 20:16:31
RockChip Linux SDK ALSA 配置实战 — RK730+ES7210

Android 通过 HAL 管理音频通路,Linux 则通过 ALSA Config(Rockchip 的 alsa-config 仓库)实现,其核心是 UCM2(ALSA Use Case Manager 2)。插拔耳机自动切换输出设备、不同场景应用不同的 mixer 设置——这些逻辑都在 HiFi.conf 中配置。本文以 RK730+ES7210 为例,介绍 ALSA 配置的写法和调试方法。

项目的完整结构如下:

alsa-config/                    ← Rockchip ALSA 配置仓库└── alsa/    ├── cards/                  ← 声卡级别配置    ├── init/                   ← 初始化配置    ├── ucm/                    ← 旧版 UCM    └── ucm2/                   ← UCM2(本文重点)        └── conf.d/rk730-es7210/            ├── rk730-es7210.conf            └── HiFi.conf

安装后会被复制到 /usr/share/alsa/,因此设备上看到的路径为 /usr/share/alsa/ucm2/conf.d/rk730-es7210/。


本文要点:

  1. UCM2 是 Linux 用户空间的音频场景管理器,通过 cset 命令操作内核 mixer 控件
  2. HiFi.conf 定义了全局初始化(SectionVerb)+ 设备切换逻辑(SectionDevice)
  3. RK730+ES7210 的特殊之处:切换设备时需要同时切换 SAI 的 SDI 数据源映射(ES7210 是多通道 ADC)

一、UCM2 在 Linux 音频栈中的位置

应用层:     PulseAudio / PipeWire / aplay               │               ▼UCM2 层:   alsaucm → HiFi.conf → cset 命令               │               ▼内核层:    /dev/snd/controlC0 → mixer 控件 (OUT1 Switch, OUT2 Switch...)

Android 用 HAL (AIDL/tinyalsa) 管理通路,Linux 用 UCM2。两者最终操作的是同一套内核 mixer 控件,只是配置格式和组织方式不同。


二、架构:三层配置

RK730 的 ALSA 配置分为三层(源码位于 SDK 的 external/alsa-config/ 目录),从系统启动到运行时逐层生效:

启动阶段 (boot)  alsactl init → alsa/init/rk730   ← 硬件 mixer 默认值运行阶段 (runtime)  alsa-lib → alsa/cards/rk730-es7210.conf  ← "default" PCM 映射音频服务 (runtime)  PipeWire → alsa/ucm2/conf.d/rk730-es7210/  ← Jack 感知 + 设备切换

2.1 Init 层:开机初始化 mixer

alsa/init/rk730 — 系统启动时由 alsactl init 执行,设置 mixer 安全默认值:

CTL{reset}="mixer"# 重置所有 mixer 控件到默认CTL{name}="OUT1 Switch" CTL{value}="on"CTL{name}="OUT2 Switch" CTL{value}="on"CTL{name}="MIC1 Boost Volume" CTL{value}="2"CTL{name}="MIC2 Boost Volume" CTL{value}="2"RESULT="true"

入口:alsa/init/rockchip 是调度器,根据内核驱动名匹配:

CARDINFO{driver}=="rockchip-rk730", INCLUDE="rk730", GOTO="init_end"

当内核 ALSA 驱动上报名称为 rockchip-rk730 时,自动包含 rk730 脚本。

Init 层的作用是开机后立即设置硬件到已知状态,防止上次关机遗留的异常值导致无声或杂音。

2.2 Cards 层:定义默认 PCM 设备

alsa/cards/rk730-es7210.conf — 为应用提供 "default" 设备别名:

rk730-es7210.pcm.default {type hooks    slave.pcm {type hw        card $CARD# 指向真实硬件 card    }}

任何 ALSA 应用均可通过 "default:CARD=rk730-es7210" 访问声卡,无需关心底层卡号。hooks 插件预留了自动路由逻辑的扩展点(当前为空)。

Cards 层使应用无需关心卡号,直接通过声卡名访问。卡片名由 cards 目录下的 .conf 文件名决定。

2.3 UCM2 层:场景切换(核心)

主配置:rk730-es7210.conf

Syntax 3SectionUseCase."HiFi" {    File "HiFi.conf"    Comment "Rockchip HiFi Codec RK730/ES7210."}

主配置文件声明 HiFi UseCase,具体配置指向 HiFi.conf。


三、HiFi.conf 详解

3.1 全局初始化:SectionVerb

SectionVerb {    EnableSequence [        # 设置 SDI 映射顺序(Speaker/Default 模式)        cset "name='SAI1 Receive PATH0 Source Select' From SDI1"        cset "name='SAI1 Receive PATH1 Source Select' From SDI2"        cset "name='SAI1 Receive PATH2 Source Select' From SDI0"        # 默认:打开扬声器,关闭耳机        cset "name='OUT2 Switch' on"        cset "name='OUT1 Switch' off"        # 恢复硬件回环增益到 0dB(ES7210 ADC 的 PGA 设置)        cset "name='PGA3_setting' 0"        cset "name='PGA4_setting' 0"    ]    DisableSequence [    ]}

SectionVerb 在声卡打开时执行一次,设置初始状态:

  1. SDI 映射 — SAI1 Receive PATHx Source Select 是 SoC SAI 驱动注册的控件,控制 I2S/TDM 接收通道的数据源映射。PATH0←SDI1、PATH1←SDI2、PATH2←SDI0 是"扬声器模式"的映射顺序
  2. 输出路由 — 打开 OUT2(扬声器),关闭 OUT1(耳机)——这是开机默认状态
  3. PGA 恢复 — PGA3/4_setting 是 ES7210 ADC 的数字 PGA 增益,0 表示 0dB

SDI 映射说明:ES7210 是 4 通道 ADC,通过 I2S 多条 SDI 线传输数据。切换麦克风时需要重新映射 SDI 数据源,使正确的麦克风通道映射到对应的 ALSA 捕获通道。

3.2 扬声器设备

SectionDevice."Speaker" {    Comment "Speaker Output"    Value {        PlaybackPriority 100       # 优先级:数字越大越优先    }    EnableSequence [        # 关闭耳麦麦克风        cset "name='Headset Mic Switch' off"        # 恢复 SDI 映射(Speaker 模式)        cset "name='SAI1 Receive PATH0 Source Select' From SDI1"        cset "name='SAI1 Receive PATH1 Source Select' From SDI2"        cset "name='SAI1 Receive PATH2 Source Select' From SDI0"        # 打开扬声器,关闭耳机        cset "name='OUT2 Switch' on"        cset "name='OUT1 Switch' off"    ]    DisableSequence [    ]}

3.3 耳机设备

SectionDevice."Headphones" {    Comment "Headphones Output"    Value {        PlaybackPriority 200        # 优先级高于 Speaker        JackName "rk730-es7210 Headset"   # 插拔检测    }    EnableSequence [        # 打开耳麦麦克风        cset "name='Headset Mic Switch' on"        # 切换 SDI 映射(Headset 模式)        cset "name='SAI1 Receive PATH0 Source Select' From SDI0"        cset "name='SAI1 Receive PATH1 Source Select' From SDI1"        cset "name='SAI1 Receive PATH2 Source Select' From SDI2"        # 打开耳机,关闭扬声器        cset "name='OUT1 Switch' on"        cset "name='OUT2 Switch' off"    ]    DisableSequence [    ]}

两设备对比:

Speaker
Headphones
优先级
100(低)
200(高)
Jack 检测
无
rk730-es7210 Headset
OUT1(耳机)
off
on
OUT2(扬声器)
on
off
Headset Mic
off
on
SDI 映射
SDI1/SDI2/SDI0
SDI0/SDI1/SDI2

四、ES7210 vs ES7202 两种变体

alsa-config 仓库里同时提供了两种 RK730 的 UCM2 配置:

rk730-es7210(本文示例)
rk730-es7202
ADC
ES7210(4通道 I2S/TDM ADC)
ES7202(PDM 数字麦克风)
SDI 线
3 条(SDI0/SDI1/SDI2)
1 条(SDI0)
SDI 映射
切换设备时需重新映射
固定 SDI0,不需要映射
麦克风
在同一张声卡上
麦克风阵列在独立声卡 card1
Mic 控件Headset Mic SwitchHeadset Mic Switch
 + Main Mic Switch
适用
EVB1
EVB2 / Buildroot 嵌入式 Linux

两者的播放部分完全一致(OUT1=耳机、OUT2=扬声器),差异只在录音的 SDI 映射。


五、Speaker ↔ Headphone 切换流程

1. 用户插入耳机   │2. 内核 Jack "rk730-es7210 Headset" 触发事件   │3. UCM2 检测到 JackName 匹配,切换设备:   │   ├── Speaker.DisableSequence  (空 — 由 Headphones 覆盖)   │   └── Headphones.EnableSequence:       ├── Headset Mic Switch → on   (打开耳麦)       ├── SDI 映射切换              (SDI0/SDI1/SDI2)       ├── OUT1 Switch → on          (打开耳机)       └── OUT2 Switch → off         (关闭扬声器)   │4. 用户拔掉耳机   │5. UCM2 回退到 Speaker 设备:   │   └── Speaker.EnableSequence:       ├── Headset Mic Switch → off       ├── SDI 映射恢复              (SDI1/SDI2/SDI0)       ├── OUT2 Switch → on       └── OUT1 Switch → off

六、UCM2 与 Android HAL 的对应关系

两者操作的是同一套内核 mixer 控件,只是封装方式不同:

同一个场景的三种写法

扬声器打开
耳机打开
UCM2
 (HiFi.conf)
cset "name='OUT2 Switch' on"cset "name='OUT1 Switch' on"
AIDL HAL
 (mixer_paths_*.xml)
<ctl name="OUT2 Switch" value="1"/><ctl name="OUT1 Switch" value="1"/>
TinyALSA HAL
 (codec_config/*.h)
.ctl_name = "OUT2 Switch", .int_val = {on}.ctl_name = "OUT1 Switch", .int_val = {on}
手动调试
 (tinymix)
tinymix 'OUT2 Switch' 1tinymix 'OUT1 Switch' 1

架构对比

UCM2 (Linux)
AIDL HAL (Android)
配置格式HiFi.conf
 (conf 语法)
mixer_paths_*.xml
 (XML)
设备定义SectionDevice."Speaker"<path name="out_speaker">
场景切换EnableSequence
 / DisableSequence
Route::applyAndUpdatePaths()
触发方式
Jack 插拔事件 / alsaucm 命令
Framework setConnectedDevices()
优先级PlaybackPriority
 (数字越大越优先)
由 Android AudioPolicyManager 管理

七、调试方法

7.1 确认配置加载

# 查看 UCM2 配置目录ls /usr/share/alsa/ucm2/conf.d/# 应看到: rk730-es7210/# 列出可用卡片alsaucm listcards

7.2 手动操作 UCM2

# 激活 HiFi UseCasealsaucm -c rk730-es7210 set _verb HiFi# 启用扬声器alsaucm -c rk730-es7210 set _enadev Speaker# 启用耳机(模拟插拔)alsaucm -c rk730-es7210 set _enadev Headphones# 查看当前激活的设备alsaucm -c rk730-es7210 get _enadev

7.3 播放测试

# 激活扬声器后播放alsaucm -c rk730-es7210 set _enadev Speakeraplay -D hw:1,0 -c 2 -f S16_LE -r 48000 test.wav# 切换到耳机后播放alsaucm -c rk730-es7210 set _enadev Headphonesaplay -D hw:1,0 -c 2 -f S16_LE -r 48000 test.wav

7.4 检查 mixer 控件状态

# 查看 OUT1/OUT2 当前状态amixer -c 1 cget name='OUT1 Switch'amixer -c 1 cget name='OUT2 Switch'# 查看 SDI 映射状态amixer -c 1 cget name='SAI1 Receive PATH0 Source Select'amixer -c 1 cget name='SAI1 Receive PATH1 Source Select'amixer -c 1 cget name='SAI1 Receive PATH2 Source Select'

八、添加新 Codec 的 ALSA 配置

以添加 es5678 Codec 为例,三层各需修改一个文件:

1. Init 层:创建初始化脚本

新建 alsa/init/es5678:

CTL{reset}="mixer"CTL{name}="DAC Switch" CTL{value}="on"RESULT="true"

在 alsa/init/rockchip 调度器中添加:

CARDINFO{driver}=="es5678", INCLUDE="es5678", GOTO="init_end"

2. Cards 层:创建卡片配置

新建 alsa/cards/es5678.conf:

es5678.pcm.default {type hw    card $CARD}

3. UCM2 层:创建场景配置

新建 alsa/ucm2/conf.d/es5678/es5678.conf:

Syntax 3SectionUseCase."HiFi" {    File "HiFi.conf"    Comment "ES5678 HiFi Codec."}

新建 alsa/ucm2/conf.d/es5678/HiFi.conf:

SectionVerb {    EnableSequence [        cset "name='DAC Switch' on"    ]}SectionDevice."Speaker" {    Value { PlaybackPriority 100 }    EnableSequence [        cset "name='DAC Switch' on"        cset "name='Speaker Volume' 60"    ]}

控件名通过 amixer -c 1 contents 查看内核驱动实际注册的名称。


九、总结

层
阶段
作用
文件
init
开机
mixer 硬件初始化
alsa/init/rk730
cards
运行
默认 PCM 设备映射
alsa/cards/rk730-es7210.conf
UCM2
运行
Jack 感知 + 设备切换
alsa/ucm2/conf.d/rk730-es7210/

三层从底层到上层,各司其职。日常开发中添加新 Codec 时,三层都需要更新:init 层增加开机初始化脚本,cards 层增加默认 PCM 映射,UCM2 层增加场景切换配置。


本文是「Rockchip RK730 音频开发」系列文章。

SDK 路径:external/alsa-config/

设备路径:/usr/share/alsa/ucm2/conf.d/rk730-es7210/

示例平台:RK3572 SoC + RK730 Codec

最新文章

随机文章