第17章Linux音频设备驱动之S3C6410+WM9714 ASoC驱动实例

17.6 S3C6410+WM9714 ASoC驱动实例

        LDD6410 开发板上为 S3C6410 的 AC97 接口上连接了 Wolfson 公司的 WM9714 Codec 芯片,其硬件连接如图 17.6 所示。WM9714 芯片主要外接了 Microphone、Line in 模拟输入和Headphone 模拟输出。而在数字接口方面,与 S3C6410 CPU 的连接包含了 AC-Link 总线上必要的信号。

第17章Linux音频设备驱动之S3C6410+WM9714 ASoC驱动实例

    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()等方法进行配合。