驱动学习2--WM8960(TODO)

基于现有 Linux 内核中成熟的声卡驱动来学习,是掌握 Linux 音频架构(尤其是 ALSA ASoC 框架)最扎实、最地道的方式。通过阅读和调试经典的驱动源码,你可以清晰地看到硬件寄存器配置、DMA 传输、时钟同步以及音频路由(DAPM)是如何在内核中实现的。

在 ASoC(ALSA System on Chip)框架中,驱动被拆分为 Codec(解码芯片)Platform(主控 DMA/I2S)Machine(板级匹配) 三部分。

以下是为你推荐的 Linux 内核中最经典、最适合作为教科书来研读的声卡驱动:

1. 最经典的 Codec 驱动:WM8960

如果你想学习一个音频芯片驱动是怎么写的,Wolfson WM8960 是嵌入式 Linux 领域重工业级的" Hello World "。无论是 NXP i.MX6/i.MX8、全志、还是瑞芯微(Rockchip)的开发板,几乎都把它作为标配或官方参考设计。

  • 内核源码路径: sound/soc/codecs/wm8960.c

  • 为什么经典(必读理由):

    • 麻雀虽小,五脏俱全: 它是一个低功耗的立体声 Codec,既有耳机输出、扬声器驱动,又有麦克风输入。它的控制接口(I2C)和音频数据接口(I2S)非常标准。

    • DAPM(动态音频电源管理)的绝佳教材: 驱动里包含了非常完整的 SND_SOC_DAPM_INPUTOUTPUTMIXER 以及路由表(Route Table)。通过它,你能真正理解 Linux 是如何根据上层是否在放音,来自动、按需开启或关闭芯片内部某一段放大器或混音器的电源。

    • 时钟配置(Clock/PLL): 它展示了如何通过 wm8960_set_dai_sysclkwm8960_set_dai_fmt 来配置 Master/Slave 模式,以及如何计算 MCLK、BCLK 和 LRCK。

2. 最通用的数字音频接口驱动:Simple-Card

在实际开发中,很多时候我们新引入的声卡是一个标准的数字输出芯片(比如通过 I2S 转 HDMI、或者标准的蓝牙音频模块、或者外接一个极其简单的 DAC 颗粒)。这时候,你甚至不需要写专门的 Machine 驱动,内核自带的 Simple-Card 就是最经典的通用模板。

  • 内核源码路径: sound/soc/generic/simple-card.c

  • 为什么经典(必读理由):

    • 数据驱动(Device Tree)的极致体现: 它不绑定任何具体的 Soc 或 Codec,而是完全通过设备树(Device Tree / DTS)中的 sound-dai 节点,把 CPU 端的 I2S 和外载的 Codec 强行"拉郎配"绑定在一起。

    • 架构清晰: 读懂它的源码,你就能明白 Linux ASoC 底层是如何解析设备树、如何动态绑定 CPU DAI、Codec DAI 以及 Platform DMA,并最终注册一张标准声卡的(snd_soc_register_card)。

3. 经典的 SoC / Platform 驱动:基于 STM32 或 NXP i.MX

Platform 驱动负责的是 SoC 内部的 I2S 模块控制DMA 搬运数据。由于这部分和特定芯片架构强绑定,代码通常由芯片原厂(如 ST、NXP、TI)维护。

  • 推荐 A:STM32 I2S / SAI 驱动

    • 路径: sound/soc/stm32/stm32_sai.cstm32_i2s.c

    • 特点: ST 的寄存器设计相对规整,代码注释和结构非常清晰。通过它可以学习 CPU 端如何配置 TDM/I2S 格式,以及如何挂载 Linux 标准的 dmaengine(音频 DMA 传输框架)来实现零拷贝的音频数据传输。

  • 推荐 B:NXP fsl_ssi / fsl_sai 驱动

    • 路径: sound/soc/fsl/fsl_sai.c

    • 特点: 飞思卡尔(现 NXP)的音频驱动在内核里迭代了十几年,极其成熟。它对各种音频边界条件(时钟抖动、千奇百怪的采样率对齐、FIFO 溢出处理)考虑得非常周全,是工业级产品的代码典范。

4. 虚拟/仿真驱动:学习底层机制的避坑神器

如果你手头暂时没有特定的硬件板子,或者不想被复杂的硬件寄存器(I2C 读写失败、时钟没对齐死机等)干扰精力,只想纯粹研究 ALSA 内核的数据流、DMA Buffer 缓存管理和用户态交互,虚拟声卡是最好的选择。

  • 推荐:SND-GOLOOP 或 ASoC Dummy Driver

    • 路径: sound/drivers/aloop.c (标准的 ALSA 回环虚拟声卡) 或 sound/soc/codecs/snd-soc-dummy.c

    • 特点: 它们完全用软件模拟了一个"影子"声卡。你可以看到一个标准的 snd_pcm_ops 结构体(包含 open, close, ioctl, hw_params, prepare, trigger, pointer 等核心回调函数)在没有真实硬件中断的情况下,是如何通过定时器(Timer)来模拟音频 DMA 搬运进度并向上层唤醒数据缓冲区的。

💡 给你的学习路径建议

要想高效吃透这一块,单看代码容易陷入细节迷宫,建议结合以下方法:

  1. 以线带面(从用户态倒推内核):

    先在板子上用 aplay 播放一个音频,通过内核里面的 Trace 工具(或者最原始的 printk),去追踪 sys_write 是如何一路走到 snd_pcm_lib_write1,然后再如何触发 Platform 驱动的 DMA 传输,最后如何通知 Codec 开始解码的。

  2. 重点攻克 DAPM:

    ALSA 驱动里面最难也最精妙的是 DAPM(动态音频电源管理) 。你可以尝试去读 sound/soc/soc-dapm.c。当你在用户态用 amixer 切换一个开关(比如把 Headphone Mux 从 DAC 切换到 LineIn),内核是如何在后台自动计算出一条最短的硬件掉电/上电路径的。

  3. 经典书籍推荐:

    如果觉得直接啃内核文档(Documentation/sound/alsa/)太枯燥,可以去系统性看一看国内 Linux 社区(如蜗窝科技/wowo)关于 ALSA/ASoC 框架的系列文章,配合上述驱动源码阅读,效果最佳。

相关推荐
星恒随风1 小时前
C++入门(二):函数重载、引用、const引用和 inline 内联函数
开发语言·c++·笔记·学习
lengxuemo10 小时前
ICC2学习笔记之Placement and Optimization
笔记·学习
温柔只给梦中人10 小时前
NLP学习:注意力机制
人工智能·学习·自然语言处理
逐影者39711 小时前
ch592f学习
学习
小满Autumn11 小时前
MVVM Light 架构笔记:定位器、命令、消息与 IoC 实践
笔记·学习·架构·c#·上位机·mvvm
蓝黑墨水11 小时前
动画角色的整个流程
学习
ZK_H13 小时前
MFC学习——简易计算器以及跨应用通信
学习·5g·mfc
踏着七彩祥云的小丑15 小时前
Go学习第1天:入门
开发语言·学习·golang·go