ALSA 架构
主要内容来之参考文档,对一些描述做了些修正.
ALSA 的基本架构可以用上图表示,组成部分主要有:
- ALSA 应用:可能是 Native Application 或 Server,用户通过调用 ALSA 库来实现声音的播放、录制和控制。
- ALSA Library :ALSA 用户空间库,提供统一的API,常见有 tinyalsa、alsa-lib等。
- ALSA Layer:内核中 ALSA 核心层,与应用层的 ALSA Library 进行交互。向上提供逻辑设备系统调用,向下驱动硬件设备。主要内容为 ALSA core 和一些辅助驱动。
- ASoC Layer:ASoC 是为支持 SoC 芯片设计的。SoC 芯片的集成度较高,传输总线、DSP、甚至 Codec 都有可能集成在一个芯片上。ASoC 层提供了一个嵌入式系统的设备管理框架,由三个部分组成:Machine、Platform、Codec。
ALSA 应用
ALSA 应用调用 ALSA 库提供的 API 来实现自己的需求。ALSA 库不同,代码实现差别也很大,这里不会做过多介绍。我们只是以 tinyalsa 为例,介绍一下声音播放的简单流程。
struct pcm_config config;
struct pcm *pcm;
char *buffer;
int size;
int num_read;
/* 设置音频的配置,通道、采样率、采样周期、编码格式等等 */
config.channels = xxx;
config.rate = xxx;
config.period_size = xxx;
config.period_count = xxx;
config.format = xxx;
/* 打开 PCM 设备 */
pcm = pcm_open(card, device, PCM_OUT, &config);
/* 根据音频配置计算需要的 buffer */
size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
buffer = malloc(size);
/* 读取数据,写入到 PCM 设备中 */
do {
num_read = fread(buffer, 1, size, file);
if (num_read > 0)
pcm_write(pcm, buffer, num_read));
} while (num_read > 0);
/* 释放 buffer,关闭设备 */
free(buffer);
pcm_close(pcm);
}
ALSA Library
应用一般通过 ALSA Library 与内核空间交互,尽管各种 Library 在实现上差别很大,但最终都是通过 Kernel ALSA Layer 提供系统调用完成调用。
- alsa-lib:ALSA 项目中提供的应用接口库,可以提供全部的接口支持,包括 PCM、Control、MIDI、Mixer、Sequencer、Timer等。同时在软件层面支持采样率转换、软件混音等复杂的实现。
- tinyalsa:tinyalsa 是一个简化的 ALSA Library,在 Android 中被使用。tinyalsa 仅支持 PCM 和 Control 接口,软件层面也非常简单。正因为其简单,所以很适合在嵌入式系统中使用。
ALSA Layer
ALSA Layer 是 ALSA 架构的核心层,在内核空间实现。它为用户空间提供逻辑设备接口,如PCM、Control、Mixer等等。同时为驱动提供接口来驱动硬件设备,如总线接口、DMA、Codec等等。
该层的主要数据结构包括,
- snd_card 表示一个声卡实例, 包含多个声卡设备
- snd_device 表示一个声卡设备部件
- snd_pcm 表示一个PCM设备, 声卡设备的一种, 用于播放和录音
- snd_control 表示Control设备, 声卡设备的一种, 用于控制声卡
- snd_pcm_str 表示PCM流, 分为playback和capture
- snd_pcm_substream PCM子流, 用于音频的播放或录制
- snd_pcm_ops PCM流操作集
各数据结构的关系如下,
核心驱动的一般实现步骤如下,
- 调用snd_card_create创建声卡实例(struct snd_card)。
- 定义声卡的私有结构体用于存放该声卡的一些资源信息, 如中断资源、IO资源、DMA资源等。
- 硬件初始化, 包括数字音频接口初始化、DMA控制器初始化、编解码器初始化。
- 调用snd_pcm_new创建逻辑设备, 并实现其操作集snd_pcm_ops。
- 调用snd_card_register注册声卡实例及声卡设备
ASoC Layer
为了简化 SoC 芯片上 ALSA 驱动的开发,在核心层的基础上构建了 ASoC(ALSA System on Chip) 层。ASoC 层主要由如下三部分组成:
- Codec:控制音频编解码器,完成音频采集和播放过程中模拟与数字间的转换。
- Platform:主要负责 SoC 芯片上音频 DMA 的传输控制,和数字音频接口的配置和控制,如I2S、PCM、AC97等。
- Machine:做为 Codec 和 Platform 的载体,将硬件设备关联起来,形成完整的硬件通路。
ASoC Layer 主要负责驱动音频硬件设备,对外表现为一个整体的 Machine。Platform 控制 SoC 芯片中数字音频传输。Codec 控制音频编解码器,可能为内置或外置,通常使用 I2C 进行控制。
ASoC 支持三种主流的数字音频接口(Digital Audio Interfaces):AC97、I2S 和 PCM。注意这里的 PCM 表示只有硬件接口协议,与上面所说的软件 PCM 接口不同。
AC97: 通常用于PC声卡, 为5线接口, 每个AC97帧为21uS长, 被分为13个时隙
- BCLK: 由AC97驱动, 为12.288 MHz
- SYNC: 同步信号, 由Controler驱动, 为48 kHz
- SDATDIN: 用于capture, AC97->Controler
- SDATAOUT: 用于playback, Controler->AC97
- RESET: 由Controler生成, 用于唤醒AC97
I2S是HiFi、STB和便携式设备中常用的4线DAI
- SCLK: 串行时钟
- LRCK: 也称WS, 声道选择线
- Tx: 用于传输音频数据
- Rx: 用于接收音频数据
PCM是另一种4线接口, 与I2S非常相似, 可以支持更灵活的协议
- BCLK: 位时钟, 根据采样率而变化
- SYNC: 同步信号
- Tx: 用于传输音频数据
- Rx: 用于接收音频数据
Codec驱动用于配置编解码器、FM、MODEM、BT 或外部 DSP, 以提供 playback 和 capture。每个Codec驱动必须提供如下功能:
- Codec DAI和PCM配置
- 使用RegMap实现的Codec控制IO
- Mixers和Audio控制
- Codec音频操作
- DAPM描述
- DAPM事件处理
- DAC静音控制(可选)