alsa之ASOC架构学习
高级Linux声音架构(ALSA)片上系统(ASoC)层的总体项目目标是为嵌入式片上系统处理器(如pxa2xx、au1x00、iMX等)和便携式音频编解码器提供更好的ALSA支持。在ASoC子系统出现之前,内核中对片上系统音频已有一定的支持,但存在一些局限性:
-
1、编解码器(Codec)驱动通常与底层 SoC 的 CPU 紧密耦合。
这种做法并不理想,因为它会导致代码重复 —— 例如,Linux 内核中曾经为 4 个不同的 SoC 平台分别维护了各自的 wm8731 编解码器驱动。换句话来理解,在早期 Linux ASoC 框架出现之前,每个 SoC 都得单独写一份针对该平台的 Codec 驱动,比如:wm8731-s3c.c(Samsung S3C 平台)、wm8731-omap.c(TI OMAP 平台)、wm8731-pxa.c(Intel PXA 平台)、wm8731-imx.c(NXP i.MX 平台);这些驱动功能几乎相同,只是硬件连接方式不同,造成了代码重复与维护困难。ASoC 框架后来引入了 CPU DAI / Codec DAI / Machine Driver 分层结构,才解决了这个问题。 -
2、当时没有一种标准化的方法来通知用户触发的音频事件(例如耳机/麦克风插入、插入后检测耳机或麦克风等)。这些事件在便携式设备上非常常见,但往往需要编写特定于机器(平台)的代码,来在此类事件发生后重新路由音频信号、开启放大器等操作。
-
3、在早期的驱动中,当播放或录制音频时,往往会直接给整个编解码器(Codec)上电。这种做法在 PC 上问题不大,但在便携式设备上会造成大量的电能浪费。
此外,当时的驱动也不支持通过调整编解码器的过采样率(oversampling rate)、偏置电流(bias current)等方式来节省功耗。
ASoC Design
ASoC 层(ALSA System on Chip) 的设计目标是为了解决前面提到的问题,并提供以下特性:
- 1、Codec 独立性(Codec independence)允许在不同平台和机器之间复用同一个编解码器驱动。也就是说,同一颗音频 Codec 芯片(例如 WM8731),可以在多个 SoC 平台上通用使用,而不必为每个平台分别编写驱动。
- 2、简化 Codec 与 SoC 之间的 I2S/PCM 接口配置(Easy I2S/PCM audio interface setup)每个 SoC 接口驱动与 Codec 驱动都会向 ASoC 核心层注册它们各自的音频接口能力。当上层应用(如 ALSA PCM)确定音频硬件参数(采样率、位宽、通道数)时,ASoC 核心会自动匹配并配置对应的 Codec 与 SoC 接口。
- 3、动态音频功耗管理(Dynamic Audio Power Management,DAPM)DAPM 机会自动让 Codec 始终保持在最低功耗状态。它会根据 Codec 内部的音频路由结构和当前活跃的音频流,自动上电或关闭内部电源模块,从而实现精细化的功耗控制。
- 4、减少“啪”声和“咔”声(Pop and Click Reduction)通过在正确的时序下为 Codec 上电/断电(包括使用数字静音),可以显著减少音频输出中的“啪”“咔”声。
ASoC 框架会在 Codec 需要切换电源状态时主动发出信号,以确保顺序正确。 - 5、机器特定控制(Machine Specific Controls)允许特定机器(板级)添加自定义的音频控制项,例如扬声器放大器音量调节、耳机插入检测等,从而满足不同硬件平台的特殊需求。
为了实现上述所有功能,ASoC(ALSA System on Chip) 基本上将一个嵌入式音频系统拆分为多个可复用的组件驱动(component drivers):
-
1、Codec 类驱动(Codec class drivers):
Codec 类驱动与平台无关,包含以下内容:– 音频控制(Audio Controls)
– 音频接口能力定义(Audio Interface Capabilities)
– Codec 的 DAPM 功耗管理定义(Codec DAPM Definition)
– Codec 的寄存器读写函数(Codec IO Functions)
该类驱动在必要时还可以扩展到 蓝牙(BT)、FM 收音机、MODEM 调制解调器等音频 IC。Codec 类驱动应当是通用的、可移植的代码,能在任意体系架构和平台上运行。
-
2、Platform 类驱动(Platform class drivers):
Platform 类驱动包含:– “音频 DMA 引擎驱动(Audio DMA Engine Driver);”
– “数字音频接口(DAI)驱动(如 I²S、AC97、PCM 等);”
– “以及该平台上任何与音频相关的 DSP 驱动。”
这些驱动直接面向具体 SoC 平台的音频硬件实现部分。
- 3、Machine 类驱动(Machine class driver):
Machine 类驱动相当于“胶水层”,负责将上述各个组件驱动描述并绑定在一起,
从而组成一个完整的 ALSA “声卡设备(sound card device)”。
它还负责处理所有与具体机器相关的控制逻辑与音频事件,例如:
– 在播放开始时打开扬声器放大器;
– 在耳机插入时切换音频路由;
– 控制外部功放电源等。
什么是 Codec(音频编解码器)
Codec(Coder/Decoder) 是一个 音频编解码芯片,负责:
-
把模拟信号(来自麦克风)转换为数字信号(ADC),
-
或把数字音频信号(来自 CPU/DSP)转换为模拟信号(DAC)。
例如常见的外部音频 Codec 芯片:
-
WM8731(Wolfson Microelectronics)
-
ALC5640(Realtek)
-
TLV320AIC31(TI)
-
AK4556、CS42L52 等
这些芯片通过 I²S、TDM、PCM、AC97、SPI、I²C 等总线与 SoC 连接。
Codec 芯片通常包含以下功能模块:
+-------------------+| Audio Codec ||-------------------|| ADC (Mic In) || DAC (Spk Out) || Mixer / EQ / AGC || Headphone AMP |+-------------------+
🔹 Mixer(混音器)
用于将多个输入源(Mic、Line-in、Playback 等)混合输出;
可控制输入增益、开关、路径选择。
🔹 EQ(Equalizer,均衡器)
用于调节频率响应;
可实现低频增强、高频抑制、声音优化等;
一般通过寄存器配置滤波器系数实现。
🔹 AGC(Automatic Gain Control,自动增益控制)
自动调节输入信号的增益,使输出音量保持稳定;
特别常用于麦克风通道,防止说话太轻或太响时音量差距过大。
4️⃣ Headphone AMP(耳机放大器)
功能:
将 DAC 输出的低电平音频信号放大,驱动耳机或小型扬声器;
通常包括可调音量、增益、负载检测(耳机插入检测)功能。
特点:
输出阻抗低;
能检测插入状态(Jack Detect);
有时支持差分输出(Differential Out)。
pipelie总结:
[Mic/Line-in] ─▶ [ADC] ─▶ [Digital Interface → SoC]
[SoC → Digital Interface] ─▶ [DAC] ─▶ [Mixer/EQ/AGC] ─▶ [Headphone AMP] ─▶ [Speaker/Headphone]
输入路径(录音):模拟信号 → ADC → 数字数据
输出路径(播放):数字数据 → DAC → 放大器 → 模拟输出
Mixer / EQ / AGC:在中间起到信号调节作用
所有模块都由驱动(Codec Driver)通过寄存器配置控制。
什么是 Codec Driver(编解码器驱动)
Codec 驱动 是运行在 Linux 内核中的一段代码,用来驱动这个外部 Codec 芯片。
它的职责包括:
| 功能 | 描述 |
|---|---|
| 寄存器配置 | 通过 I²C 或 SPI 配置 Codec 寄存器(音量、输入选择、采样率等) |
| 电源控制 | 管理 Codec 的上电、下电、休眠状态 |
| 音频格式设置 | 设置采样率、位宽、时钟、I2S 模式(主从、左对齐、右对齐) |
| Mixer 控制 | 提供 alsamixer 控件(音量、静音、增益) |
| 音频路径控制 | 控制输入输出通路(Mic→ADC、DAC→Spk) |
ASoC Codec Class Driver:
Codec 类驱动(Codec class driver) 是一种通用的、与硬件平台无关的代码,
其作用是配置 音频编解码器(Codec)、FM 收音机模块(FM)、调制解调器(MODEM)、蓝牙音频模块(BT) 或 外部音频 DSP,
以实现音频的**采集(Capture)与播放(Playback)**功能。
Codec 类驱动不应包含任何与目标平台或特定机器相关的代码。
所有与平台或机器相关的逻辑,都应分别放在 Platform 驱动 与 Machine 驱动 中实现。
每个 Codec 类驱动必须提供以下功能:
1️⃣ Codec DAI 与 PCM 配置
定义编解码器的数字音频接口(如 I²S/TDM/PCM)及其能力(采样率、位宽、通道数等)。
2️⃣ Codec 控制 IO(使用 RegMap API)
通过内核的 RegMap 框架访问 Codec 的寄存器,统一寄存器读写接口。
3️⃣ 混音器(Mixer)与音频控制(Audio Controls)
定义音量、静音、输入选择、通道开关等 ALSA 控件。
4️⃣ Codec 音频操作函数(Audio Operations)
包括启动播放/录音、停止、设置参数、切换采样率等操作接口。
5️⃣ DAPM 描述(DAPM Description)
定义 Codec 内部各音频模块的 DAPM 节点(Widget)及连接关系(Route)。
6️⃣ DAPM 事件处理函数(DAPM Event Handler)
用于在 DAPM 电源状态变化时执行特定操作(如上电延时、消除“啪声”)。
可选地,Codec 驱动还可以提供:
🔸 DAC 数字静音控制(DAC Digital Mute Control)
用于在播放停止或切换时快速静音,防止“pop/click”噪声。
参考资料:https://www.kernel.org/doc/html/latest/sound/soc/index.html
