17.6 S3C6410+WM9714 ASoC驱动实例
LDD6410 开发板上为 S3C6410 的 AC97 接口上连接了 Wolfson 公司的 WM9714 Codec 芯片,其硬件连接如图 17.6 所示。WM9714 芯片主要外接了 Microphone、Line in 模拟输入和Headphone 模拟输出。而在数字接口方面,与 S3C6410 CPU 的连接包含了 AC-Link 总线上必要的信号。
WM9714 是一款比较复杂的 Codec 芯片,其与 AC97 2.2 兼容。内部集成 HiFi(高保真) 立体声ADC/DAC、AUX ADC/DAC 和用于话音的 Voice ADC/DAC,同时包含数个 mux 和 mixer 以及增益调节,在使用该芯片上,读懂数据手册中的“Audio Paths Overview”即音频路径图非常关键。
LDD6410 开发板上 ASoC 驱动的 3 部分分别是:
(1)Codec 驱动,由sound/soc/codecs/wm9713.c实现。
(2)平台驱动,由sound/soc/s3c/s3c-ac97.c 实现 S3C6410 CPU 端的 DAI (数字音频接口)驱动,由
sound/soc/s3c/s3c-pcm.c 实现 CPU 端的 DMA 驱动。
(3)板驱动,由sound/soc/s3c/smdk6410_wm9713.c 实现,它将第 1 部分和第 2 部分进行绑定。
代码分析:
1、codec驱动
sound/soc/codecs/wm9713.c支持 WM9713、WM9714,主要定义一系列的mixer 控制、DAPM、AC97 底层读写、时钟/PLL 控制以及 snd_soc_ops 的成员函数。
2、平台驱动
1)sound/soc/s3c/s3c-ac97.c 实现 CPU 端 AC97 DAI (数字音频接口)的驱动,会导出 snd_soc_dai 结构体的实例s3c_ac97_dai。
2) sound/soc/s3c/s3c-pcm.c 实现 CPU 端的 DMA 驱动,导出 snd_soc_platform 结构体的实例 s3c24xx_soc_platform,其核心如代码清单 17.36。
代码清单 17.36 S3C6410 平台驱动 DMA 进行 PCM 流操作
struct snd_soc_platform s3c24xx_soc_platform = {
.name = "s3c24xx-audio",
.pcm_ops = &s3c24xx_pcm_ops,
.pcm_new = s3c24xx_pcm_new,
.pcm_free = s3c24xx_pcm_free_dma_buffers,
};
EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
3)板驱动
sound/soc/s3c/smdk6410_wm9713.c,将 Codec 和平台驱动中导出的 symbol 绑定在一起,并在模块加载函数中注册一个名为“soc-audio”的 platform设备。
本章总结:
音频设备接口包括 PCM、IIS(数字音频数据传输总线) 和 AC97 等,分别适用于不同的应用场合。针对音频设备,Linux内核包含 3 类音频设备驱动框架,OSS、ALSA 和 ASoC,OSS 包含 dsp 和 mixer 字符设备接口,在用户空间的编程中,完全使用文件操作;ALSA 以 card 和组件(PCM、mixer 等)为主线,在用户空间的编程中使用 alsa-lib;ASoC 则是 ALSA 在 SoC 方面的演变,ASoC 建立在 ALSA 之上,将 ALSA 驱动中 CPU 相关的代码和 Codec 相关的代码进行分离。
在音频设备驱动中,几乎必须使用 DMA,而 DMA 的缓冲区会被分割成一个一个的段,每次 DMA 操作进行其中的一段。OSS 驱动的阻塞读写具有流控能力,在用户空间不需要进行流量方面的定时工作,但是它需要及时地写(播放)和读(录音),以免出现缓冲区的 underflow或 overflow。ALSA 和 ASoC 的流控则由 ALSA 的核心层处理,底层驱动仅以 trigger()、pointer()等方法进行配合。