ALSA SOC架构关键点

关于ALSA(Advanced Linux Sound Architecture)中文资料真的很少,可能是国人很少真的从零开始做驱动开发的原因。毕竟像wolfson或者realtek这样的公司多还是老外在做开发。ALSA 对SOC支持,更是ALSA在嵌入式领域的应用,也是后来才加入到ALSA中的,那资料更是少了。我花了一个星期也几乎没有任何发现,而后通过零星资料的蛛丝马迹,终于对ALSA有感觉了。对今后的继续学习是非常有帮助的。

按通常的三层分类方式,从下到上,依次是ALSA driver、ALSA lib、ALSA application。

ALSA application包括aplay、arecord,他们属于ALSA utils的工具。这些工具用于测试驱动非常的好。

ALSA lib提供诸如打开,关闭,播放的函数库

ALSA driver是后来才加入了对SOC的支持,并且将hardware audio codec的控制抽象出来,放在sound/soc/codecs的目录里。而和SOC硬件相关的代码抽象出来放在omap目录里(加入SOC是omap)。这种分离式的设计使得一个codec的代码,在不做任何修改的情况下,可以对应很多的SOC。(把通用的代码尽量抽象出来是驱动程序架构设计一直追求的目标)

ALSA的SOC中的一个大家伙,就是DAPM (Dynamic Audio Power Management),它将电源划分为4个域:

  1. Codec domain - VREF, VMID (core codec and audio power) Usually controlled at codec probe/remove and suspend/resume, although can be set at stream time if power is not needed for sidetone, etc.
  2. Platform/Machine domain - physically connected inputs and outputs Is platform/machine and user action specific, is configured by the machine driver and responds to asynchronous events e.g when HP are inserted
  3. Path domain - audio susbsystem signal paths Automatically set when mixer and mux settings are changed by the user. e.g. alsamixer, amixer.
  4. Stream domain - DACs and ADCs. Enabled and disabled when stream playback/capture is started and stopped respectively. e.g. aplay, arecord.

对于codec domain,它位于sound/soc/codecs目录下,例如wm9713.c。

对于Platform/Machine domain,他放在machine名字的目录里,如sound/soc/s3c24xx目录下neo1973_wm9753.c,以机器名和codec的名字同时命名。

在定义codec的audio path的时候,你需要知道这样的背景知识,DAPM在概念上分为以下部件,

 

  • Mixer      - Mixes several analog signals into a single analog signal.
  • Mux        - An analog switch that outputs only one of many inputs.
  • PGA        - A programmable gain amplifier or attenuation widget.
  • ADC        - Analog to Digital Converter
  • DAC        - Digital to Analog Converter
  • Switch     - An analog switch
  • Input      - A codec input pin
  • Output     - A codec output pin
  • Headphone  - Headphone (and optional Jack)
  • Mic        - Mic (and optional Jack)
  • Line       - Line Input/Output (and optional Jack)
  • Speaker    - Speaker
  • Pre        - Special PRE widget (exec before all others)
  • Post       - Special POST widget (exec after all others)

可以看出这些部件主要也是抽象了codec内部的硬件构件。audio path是路径,所以有输入,输出的概念。除了path的终点,每个部件都包含输入口,和输出口。

对于path上输入的开始端点,它只需要输出到下一个部件就好。同理对于path上输出的端点,它只需要从前一个部件输入就好。path的头尾端点就是用SND_SOC_DAPM_INPUT或者SND_SOC_DAPM_OUTPUT定义这个部件。

codec中都有混音器,它总是把多个输入加和为一个输出信号,他就由SND_SOC_DAPM_MIXER定义。

同样,codec中也会有一些多路开关,他是有多个输入,但是只有一个输入可以和输出接通,这样的部件由SND_SOC_DAPM_MUX定义。

PGA就如它在硬件中的名字,一般就是一个输入,和一个输出。用SND_SOC_DAPM_PGA定义

OK,你的codec代码中将所有可能的path全部连接起来,问题来了,对于每一个audio path都有一个头,和一个尾。但是这条path中间可以走的路那就很多了,也不是一定的。尤其对于手机里的场景中audio path,可以有speaker路径,headphone路径,A2DP路径,GSM phone路径或者MIC路径,很多了,我要根据需要打开或者关闭这些路径。我被这个问题困惑了很久,ALSA的设计中到底由哪个部分负责。一开始我还怀疑是不是codec的audio path没有定义完整?或者ALSA有切换这种场景的函数?再或者由machine代码来定义这样的路径?

后来我的猜想都不正确。Audio Codec中有许多部件,并且可以是任意的名字,ALSA怎么可能知道该如何操作这些部件来切换到你想要的路径,即时ALSA lib也不会关心这部分内容,这些细微的切换又ALSA application以上来完成,ALSA lib也最多提供各种操作mixer或者Mux的函数,如果切换是你应用的事情。

对部件的操作函数是snd_mixer_selem_set_enum_item(),alsamixer也是通过这个函数达到切换的目的

 

 

 

你可能感兴趣的:(Linux开发,Android)