3. 内核音频驱动框架
在嵌入式 ALSA 音频驱动中,snd_soc_card、snd_soc_dai_link、snd_soc_platform 和 snd_soc_codec 是构成 ASoC(ALSA System on Chip)框架的四大支柱。理解它们之间的组合与引用关系,是进行驱动移植与 Kconfig 裁剪的前提。
核心概念:ASoC 将音频系统抽象为 Card(声卡)、Link(链路)、Platform(DMA/CPU侧) 和 Codec(编解码器) 四个层次。Card 是顶层容器,Link 描述连接关系,Platform 负责数据传输,Codec 负责音频信号转换。
3.1 结构体职责与关键字段
| 结构体 | 角色 | 关键字段 | 对应硬件 |
|---|---|---|---|
snd_soc_card |
声卡顶层实例 | name, dai_link, num_links, dev |
整个音频设备(如:板级声卡) |
snd_soc_dai_link |
CPU DAI 与 Codec DAI 的连接 | name, cpus, codecs, platforms, ops |
I2S/PCM 总线连接 |
snd_soc_platform |
CPU 侧 DMA 引擎 | name, pcm_new, pcm_free, ops |
SoC 内置 DMA 控制器 |
snd_soc_codec |
音频编解码芯片 | name, dapm, controls, driver |
WM8960、ES8316、TLV320AIC3x 等 |
移植要点:在设备树匹配或板级文件中,
snd_soc_card 通过 dai_link 数组将 platform 和 codec 绑定在一起。裁剪 Kconfig 时,必须确保 platform 和 codec 对应的驱动模块被选中,否则声卡注册会失败。
3.2 结构体关系 SVG 架构图
下图展示了四个核心结构体在 ASoC 框架中的层级关系与数据流向:
3.3 典型注册流程与代码片段
在板级驱动中,通常按以下步骤组织这四个结构体:
- 定义 Codec 驱动:填充
snd_soc_codec_driver,注册编解码器控制接口。 - 定义 Platform 驱动:填充
snd_soc_platform_driver,实现 DMA 传输回调。 - 定义 DAI Link:将 CPU DAI 和 Codec DAI 通过
snd_soc_dai_link连接。 - 定义 Card:填充
snd_soc_card,挂载dai_link数组,调用devm_snd_soc_register_card()。
/* 示例:板级声卡注册代码片段 */
static struct snd_soc_dai_link imx_wm8960_dai_link = {
.name = "WM8960-HIFI",
.stream_name = "WM8960-HIFI",
.cpus = &imx_cpu_dai,
.num_cpus = 1,
.codecs = &wm8960_codec,
.num_codecs = 1,
.platforms = &imx_platform,
.num_platforms = 1,
.ops = &imx_wm8960_ops,
};
static struct snd_soc_card imx_wm8960_card = {
.name = "imx-wm8960",
.owner = THIS_MODULE,
.dai_link = &imx_wm8960_dai_link,
.num_links = 1,
};
static int imx_audio_probe(struct platform_device *pdev) {
struct snd_soc_card *card = &imx_wm8960_card;
card->dev = &pdev->dev;
return devm_snd_soc_register_card(&pdev->dev, card);
}
常见错误:在裁剪 Kconfig 时,如果只选中了
SND_SOC_IMX_WM8960 而忘记选中 SND_SOC_WM8960(Codec 驱动),内核编译不会报错,但运行时 snd_soc_register_card 会因找不到 Codec 组件而返回 -EPROBE_DEFER 或 -ENODEV。
3.4 结构体依赖关系总结
| 依赖方向 | 源结构体 | 目标结构体 | 说明 |
|---|---|---|---|
| 1 | snd_soc_card |
snd_soc_dai_link |
Card 通过 dai_link 指针引用 Link 数组 |
| 2 | snd_soc_dai_link |
snd_soc_platform |
Link 通过 platforms 指针绑定 DMA 引擎 |
| 3 | snd_soc_dai_link |
snd_soc_codec |
Link 通过 codecs 指针绑定编解码器 |
| 4 | snd_soc_platform |
硬件 DMA | Platform 驱动操作 DMA 寄存器 |
| 5 | snd_soc_codec |
硬件 I2C/SPI | Codec 驱动通过控制总线配置芯片 |
3.5 实战:Kconfig 裁剪与结构体对应关系
在 sound/soc/ 目录下,Kconfig 的配置项与上述结构体存在直接映射:
- CONFIG_SND_SOC:顶层开关,对应 ASoC 框架基础支持。
- CONFIG_SND_SOC_IMX_CPU_DAI:对应
snd_soc_dai_link中的 CPU DAI 部分。 - CONFIG_SND_SOC_WM8960:对应
snd_soc_codec驱动。 - CONFIG_SND_SOC_IMX_PCM:对应
snd_soc_platform驱动。 - CONFIG_SND_SOC_IMX_WM8960:对应
snd_soc_card板级实例。
裁剪原则:如果目标硬件只使用 WM8960 一个 Codec,且 SoC 是 i.MX6,则只需选中上述 5 个配置项,其余 Codec 驱动(如 ES8316、TLV320AIC3x)全部取消,可显著减小内核体积。