0%

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设备驱动开发-约翰-马德奥》