Linux 驱动之 ALSA(一)概述

ASOC

ALSA 是为桌面计算机而设计的,没有考虑嵌入式设备的限制,在处理嵌入式设备时会产生很多问题,包括但不限于如下:

  • 编解码器和 CPU 之间的耦合太强,导致代码移植困难。
  • 没有处理用户音频相关行为通知的标准方法,在移动场景中,用户的相关音频操作很频繁。
  • 在最初的 ALSA 设置中没有考虑 PM 机制。

ASOC 就是为了解决以上问题而产生的。ALSA(ALSA system on chip, ASOC)层的目的是为嵌入式处理器和各种编解码器提供更好的 ALSA 支持。ASOC 具有以下优势:

  • 独立的编解码器驱动程序。
  • 更方便的配置 CPU 和编解码器动态音频电源管理(dynamic audio power management, DAPM)之间的音频数据接口。
  • 减少弹出和点击操作,并增加与平台相关的控件。

为了实现上述功能,ASoC 将嵌入式音频系统划分为 3 个可重用的组件驱动程序,即机器类(machine class)、平台类(platform class)和编解码器类(codec)。其中,平台类和编解码器类是跨平台(cross-platform)的,而机器类是板级的(board-specific)。

ASoC 数字音频接口

数字音频接口(digital audio interface,DAI)是一种总线控制器,它可以将音频数据从一端(如 SoC)传送到另一端(编解码器)。ASoC 当前支持 SoC 控制器和便携式音频编解码器上的大多数 DAI,如 AC97、I2S、PCM、S/PDIF 和 TDM。

I2S

I2S 全称 Inter-IC Sond Bus,是飞利浦在 1986 年定义 (1996 年修订)的数字音频传输标准,用于数字音频数据在系统内部器件之间传输,例如编解码器 Codec、DSP、数字输入/输出接口、ADC、DAC 和数字滤波器等。 对于 I2S 的数字接口定义也比较简单,没有从地址或者从设备的概念,在 I2S 总线上,只能同时存在一个主设备和发送设备。在 I2S 系统中,提供时钟(SCK)的设备为主设备,其常见的系统框图如下:

在 I2S 传输协议中,数据信号、时钟信号以及控制信号是分开传输的。I2S 协议只定义三根信号线:时钟信号 SCK、数据信号 SD 和左右声道选择信号 WS。

  • SCLK:
    时钟信号:模块内的同步信号,主模式时由模块内部自己产生,从模式由外部提供

  • SD:
    数据信号:在 WS 变化后的第一个 SCK 脉冲,先传输最高位(MSB, Most Significant Bit)。先传送 MSB 是因为发送设备和接收设备的字长可能不同

  • WS:
    左右声道选择信号 Word Select:WS=0,表示选择左声道;WS=1,表示选择右声道。WS 也称帧时钟,即 LRCLK/Left Right Clock。WS 频率等于声音的采样率

其数据传输的方式如下图:

PCM/TDM

PCM = Pulse Code Modulation 是通过等时间隔(即采样率时钟周期)采样将模拟信号数字化的方法。下图是 4bit 采样速率的 PCM 数据量化示意图:

PCM 接口常用于板级音频数字信号的传输,与 I2S 类似,其实 I2S 也是 PCM 的一种特例接口,只不过,I2S 的速率会更高,比较适用于传音乐。而 PCM 通常用于 AP 处理器与通信 MODEM 之间的语言数据传输(就是双向打电话数据),对于 I2S 只能传 2 个声道的数据,而 PCM 可以传多达 16 路数据,采用时分复用的方式,也就是 TDM。其接口与 I2S 类似,电路信号为:

  • PCM_CLK 数据时钟信号
  • PCM_SYNC 帧同步时钟信号
  • PCM_IN 接收数据信号
  • PCM_OUT 发送数据信号

PDM

PDM(Pulse Density Modulation) 是一种数字信号表示模拟信号的调制方法,声音通过传感器获得模拟信号,经过 AD,得到音频数字信号,然后经过 PDM 脉冲转换成数字信号。PDM 使用远高于 PCM 采样率的时钟采用调制模拟分量,只有 1 位输出,要么是 0,要么是 1。

PDM 方式的逻辑相对复杂,但只需要两根线,时钟和数据。对于下图,主设备为两个从设备提供时钟,分别在时钟的上升沿和下降沿触发选择 Source 1/2 作为数据输入。

PDM 在诸如手机和平板等对于空间限制严格的场合有着广泛的应用前景。在数字麦克风领域,应用最广的就是 PDM 接口,其次为 I2S 接口。

S/PDIF

S/PDIF 的全称是 Sony/Philips Digital Interface Format,由于被广泛采用,它成为事实上的民用数字音频格式标准,大量的消费类音频数字产品如民用 CD 机、DAT、MD 机、计算机声卡数字口等都支持 S/PDIF,在不少专业设备上也有该标准的接口。就传输方式而言,SPDIF 分为输出(SPDIF OUT)和输入(SPDIF IN)两种。

ASOC 子元素

  • 平台(platform):这是指 SoC 的音频 DMA 引擎,如 i.MX、Rockchip 和 STM32。平台类驱动程序可以细分为两部分,如下所述:
    • CPU DAI 驱动程序:在嵌入式系统中,它通常是指 CPU 的音频总线控制器,如、I2S、S/PDIF、AC97 和 PCM 总线控制器,有时可能会集成到一个更大的模块中,即串行音频接口(serialaudiointerface,SA)
    • PCM DMA 驱动程序:PCM 驱动程序与平台无关,仅与 SOCDMA 引擎上游 API 交互
  • 编解码器(codec):除了编解码功能外还包括 AIF、DAC、ADC、Mixer、PGA、Lin-in、Lin-out。一些高端芯片还具有回声消除、噪声抑制和其他组件。

  • 机器(machine):系统级表示,链接两个音频接口(cpu_dai 和 codec dai),该链接在内核通过 struct snd_soc_dai_link 实例抽象出来。

框架

  • alsa-utils(用户空间) ALSA 实用程序包由 Linux 社区提供,包含 ALSA 项目的命令行实用程序(aplay、arecord、amixer、alsamixer ...)。

  • alsa-lib(用户空间) ALSA 库包含需要访问 ALSA 声音接口的程序(例如 alsa-utils 程序)使用的 ALSA 库。ALSA 库在内核模块提供的音频设备上提供了一定程度的抽象,例如 PCM 和控制抽象 。

  • ALSA Framework(内核空间) ALSA 核心提供了一个 API 来实现音频驱动程序和 PCM/控制接口,以在用户空间上公开音频设备。PCM 接口处理数据流和控制。该界面管理 ALSA 驱动程序导出的控件(音频路径、音量。..)。

  • ASoC Framework(内核空间) ALSA 片上系统 ( ASoC ) 层的目标是改进 ALSA 对嵌入式片上系统处理器和音频编解码器的支持。ASoC 框架提供了一个 DMA 引擎,它与 DMA 框架连接以处理音频样本的传输。ASoC 还通过 DAPM 驱动程序支持音频路径的动态电源管理。ASoC 充当 ALSA 驱动程序,它将嵌入式音频系统分为三种类型的独立于平台的驱动程序:CPU DAI、编解码器和机器驱动程序。

  • ASoC driver(内核空间) ASoC 驱动程序允许为 ASoC 驱动程序类实现硬件相关代码 :
    • 编解码器驱动程序
    • CPU DAI 驱动程序
    • 机器驱动程序

Debug

Procfs filesystem

  • List PCM audio devices:
1
$ cat /proc/asound/pcm
  • Get hardware parameters of a PCM audio device (device "0" of card "0" here):
1
$ cat /proc/asound/card0/pcm0p/sub0/hw_params

Debugfs filesystem

  • List DAIs
1
$ cat /sys/kernel/debug/asoc/dais
  • List DAPMs of "xxx.audio-controller" CPU DAI of "STM32MP1-EV" soundcard
1
$ ls /sys/kernel/debug/asoc/STM32MP1-EV/xxx.audio-controller/dapm

How to trace

Dynamic traces

ALSA framework and driver debug traces can be added to the kernel logs by using the dynamic debug mechanism.

1
2
$ echo -n 'file stm32_sai.c +p; file stm32_sai_sub.c +p' > /sys/kernel/debug/dynamic_debug/control; 
$ dmesg -n8;

Tracing filesystem

Activate DAPM traces

  • Enable trace
1
$ echo '1' > /sys/kernel/debug/tracing/events/asoc/enable
  • Check log
1
$ cat /sys/kernel/debug/tracing/trace

Activate PCM hardware parameter traces

  • Enable trace
1
$ echo '1' > /sys/kernel/debug/tracing/events/snd_pcm/enable
  • Check log
1
$ cat /sys/kernel/debug/tracing/trace

Activate PCM buffer state traces

Prerequisite: the CONFIG_FUNCTION_TRACER, CONFIG_SND_DEBUG, CONFIG_SND_DEBUG_VERBOSE and SND_PCM_XRUN_DEBUG configurations must first be enabled in the Linux kernel configuration

  • Set XRUN trace verbosity
1
$ echo 3 > /proc/asound/card0/pcm0p/xrun_debug
  • Enable trace
1
$ echo '1' > /sys/kernel/debug/tracing/events/snd_pcm/enable
  • Check log
1
$ cat /sys/kernel/debug/tracing/trace

参考文献

https://blog.csdn.net/u012489236/article/details/98040985?spm=1001.2014.3001.5501
https://blog.csdn.net/u012489236/article/details/98068122?spm=1001.2014.3001.5501
https://blog.csdn.net/u012489236/article/details/98079176?spm=1001.2014.3001.5501
《Linux 设备驱动开发-约翰-马德奥》