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 芯片通常包含以下功能模块:

go 复制代码
+-------------------+
  |    Audio Codec    |
  |-------------------|
  |  ADC  (Mic In)    |
  |  DAC  (Spk Out)   |
  |  Mixer / EQ / AGC |
  |  Headphone AMP    |
  +-------------------+

🔹 Mixer(混音器)

用于将多个输入源(Mic、Line-in、Playback 等)混合输出;

可控制输入增益、开关、路径选择。

🔹 EQ(Equalizer,均衡器)

用于调节频率响应;

可实现低频增强、高频抑制、声音优化等;

一般通过寄存器配置滤波器系数实现。

🔹 AGC(Automatic Gain Control,自动增益控制)

自动调节输入信号的增益,使输出音量保持稳定;

特别常用于麦克风通道,防止说话太轻或太响时音量差距过大。

🔹Headphone AMP(耳机放大器)

功能:

将 DAC 输出的低电平音频信号放大,驱动耳机或小型扬声器;

通常包括可调音量、增益、负载检测(耳机插入检测)功能。

特点:

输出阻抗低;

能检测插入状态(Jack Detect);

有时支持差分输出(Differential Out)。

pipelie音频流线路总结:

go 复制代码
[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)

整个架构示意图

资料参考:https://www.kernel.org/doc/html/latest/sound/soc/index.html