现在的位置: 首页 > 综合 > 正文

DAPM之二:audio paths与dapm kcontrol

2012年12月29日 ⁄ 综合 ⁄ 共 6027字 ⁄ 字号 评论关闭

转载:http://blog.csdn.net/sepnic/article/details/6334922

备注:仅作个人学习资料保存使用,请移步原作者链接进行讨论。

在用alsa_amixer controls时,除了我们之前提到的snd_soc_add_controls添加的kcontrols外,还有一些多出来的controls。其实多出来的那些都是属于dapm kcontrol,主要用于切换音频路径。

 

一、AUDIO PATHS OVERVIEW

以标准内核2.6.32的wm8900 codec为例。先看AUDIO PATHS OVERVIEW,红色线路是LINPUT1(Left Input) -> LEFT INPUT PGA -> LEFT INPUT MIXER -> LEFTOUTPUT
MIXER
 -> LINEOUT1L
,表示从LINPUT输入的信号通过这条路径送到LINEOUT输出,再具现一点,就是录音信号直接放到SPK播出。在这条路径上,有三个带+号的圆圈,那就是多路混合器mixer,用于切换输入源或将多个输入源混合输出。

土黄色部分为LEFT INPUT PGA:可选择LINPUT1、LINPUT2和LINPUT3;

绿色部分是LEFT INPUT MIXER:可选择INPUTPGA、LINPUT2、LINPUT3和AUX/LCOM;

蓝色部分是LEFT OUTPUT MIXER:可选择INPUTMIXER、LINPUT3、AUX/LCOM和LEFT DAC等。

配置声音通路时,主要是对mixer做切换输入源操作。如要实现Playback,则需要打通DAC -> OUTPUT MIXER -> LINEOUT通路。

 

二、配置声音通路

 

这里先绕开代码,先用alsa_amixer实际操作切换声音路径(以上图的红色路径为例),有个直观印象。

~ # alsa_amixer controls
numid=1,iface=MIXER,name='Mic Bias Level'
......省略......
numid=68,iface=MIXER,name='Left Input Mixer AUX Switch'
numid=69,iface=MIXER,name='Left Input Mixer Input PGA Switch'
numid=66,iface=MIXER,name='Left Input Mixer LINPUT2 Switch'
numid=67,iface=MIXER,name='Left Input Mixer LINPUT3 Switch'
numid=73,iface=MIXER,name='Left Input PGA LINPUT1 Switch'
numid=74,iface=MIXER,name='Left Input PGA LINPUT2 Switch'
numid=75,iface=MIXER,name='Left Input PGA LINPUT3 Switch'

numid=3,iface=MIXER,name='Left Input PGA Switch'
numid=2,iface=MIXER,name='Left Input PGA Volume'
numid=4,iface=MIXER,name='Left Input PGA ZC Switch'
numid=57,iface=MIXER,name='Left Output Mixer AUX Bypass Switch'
numid=60,iface=MIXER,name='Left Output Mixer DACL Switch'
numid=56,iface=MIXER,name='Left Output Mixer LINPUT3 Bypass Switch'
numid=58,iface=MIXER,name='Left Output Mixer Left Input Mixer Switch'
numid=59,iface=MIXER,name='Left Output Mixer Right Input Mixer Switch'

......省略......
~ #

以上打印出所有的codec kcontrols,以之前对应的颜色区分了INPUT PGA、INPUT MIXER、OUTPUT MIXER三个mixer的路径选择。要打开红色通路,则进行如下操作:

[c-sharp] view
plain
copy

  1. alsa_amixer cset numid=3,iface=MIXER,name='Left Input PGA Switch' 1  
  2. alsa_amixer cset numid=73,iface=MIXER,name='Left Input PGA LINPUT1 Switch' 1  
  3. alsa_amixer cset numid=69,iface=MIXER,name='Left Input Mixer Input PGA Switch' 1  
  4. alsa_amixer cset numid=58,iface=MIXER,name='Left Output Mixer Left Input Mixer Switch' 1  
  5. alsa_amixer cset numid=43,iface=MIXER,name='LINEOUT1 Switch' 1  

numid3 : 使能Left Input PGA;

numid73: 令Left Input PGA选择LINPUT1输入源;

numid69: 令Left Input Mixer选择Left Input PGA输入源;

numid58: 令Left Output Mixer选择Left Input Mixer输入源;

numid43: 使能LINEOUT1。

【这里仅以最基本的alsa-util来配置回路,在实际应用中,可自己实现alsa mixer或编写asound.conf虚拟出不同的devices,前者较典型见Android2.2的ALSAControl.cpp,后者在之后的章节会提一下。我偏向于asound.conf实现,灵活性较高,不同的codec改动asound.conf就行了。】

 

三、AUDIO PATHS代码实现

 

知道声音通路如何配置后,回到驱动代码实现。音频路径功能与普通的snd_kcontrol差不多,但写法稍微复杂一点,以'Left Output Mixer Left Input Mixer Switch'为例说明。

1、实现Left Output Mixer的输入源选择:

[c-sharp] view
plain
copy

  1. static const struct snd_kcontrol_new wm8900_loutmix_controls[] = {  
  2. SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0),  
  3. SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0),  
  4. SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 7, 1, 0),  
  5. SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 3, 1, 0),  
  6. SOC_DAPM_SINGLE("DACL Switch", WM8900_REG_LOUTMIXCTL1, 8, 1, 0),  
  7. };  

2、添加名为Left Output Mixer的widget:

[c-sharp] view
plain
copy

  1. static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = {  
  2. /* Externally visible pins */  
  3. ......省略......  
  4. /* Input */  
  5. ......省略......  
  6. SND_SOC_DAPM_MIXER("Left Input Mixer", WM8900_REG_POWER2, 5, 0,  
  7.            wm8900_linmix_controls,  
  8.            ARRAY_SIZE(wm8900_linmix_controls)),  
  9. ......省略......  
  10. /* Output */  
  11. ......省略......  
  12. SND_SOC_DAPM_MIXER("Left Output Mixer", WM8900_REG_POWER3, 3, 0,  
  13.            wm8900_loutmix_controls,  
  14.            ARRAY_SIZE(wm8900_loutmix_controls)),  
  15. ......省略......  
  16. };  

【MIXER:多个输入源混合成一个输出,用SND_SOC_DAPM_MIXER定义这个widget,类型为snd_soc_dapm_mixer;
  MUX:多路选择器,多路输入,但只能选择一路作为输出,用SND_SOC_DAPM_MUX定义这个widget,类型为snd_soc_dapm_mux;
  PGA:单路输入,单路输出,带gain调整的部件,用SND_SOC_DAPM_PGA定义这个widget,类型为snd_soc_dapm_pga。】

3、搭建音频路径:

[c-sharp] view
plain
copy

  1. static const struct snd_soc_dapm_route audio_map[] = {  
  2. /* Inputs */  
  3. ......省略......  
  4. /* Outputs */  
  5. ......省略......  
  6. {"Left Output Mixer""Left Input Mixer Switch""Left Input Mixer"},  
  7. ......省略......  
  8. };  

前面的"Left Output Mixer"表示操作目的对象sink,对应widgets中的名为Left Output Mixer的widget;

中间的"Left Input Mixer Switch"表示操作行为control,对应wm8900_loutmix_controls中的名为Left Input Mixer Switch的kcontrol;

后面的"Left Input Mixer"表示操作源对象source,对应widgets中的名为Left Input Mixer的widget。

合起来的意思:通过动作"Left Input Mixer Switch"将输入源"Left Input Mixer"送到目的混合器"Left Output Mixer"输出。

这里我的解析有点拗口,直接看dapm.txt更清晰一点:

[c-sharp] view
plain
copy

  1. e.g., from the WM8731 output mixer (wm8731.c)  
  2. The WM8731 output mixer has 3 inputs (sources)  
  3.  1. Line Bypass Input  
  4.  2. DAC (HiFi playback)  
  5.  3. Mic Sidetone Input  
  6. Each input in this example has a kcontrol associated with it (defined in example  
  7. above) and is connected to the output mixer via it's kcontrol name. We can now  
  8. connect the destination widget (wrt audio signal) with it's source widgets.  
  9.     /* output mixer */  
  10.     {"Output Mixer""Line Bypass Switch""Line Input"},  
  11.     {"Output Mixer""HiFi Playback Switch""DAC"},  
  12.     {"Output Mixer""Mic Sidetone Switch""Mic Bias"},  
  13. So we have :-  
  14.     Destination Widget  <=== Path Name <=== Source Widget  
  15. Or:-  
  16.     Sink, Path, Source  
  17. Or :-  
  18.     "Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".  
  19. When there is no path name connecting widgets (e.g. a direct connection) we  
  20. pass NULL for the path name.  

注意:dapm kcontrol名称 = 目的对象sink名称 + 操作行为control名称,即'Left Output Mixer Left Input Mixer Switch',操作源对象source名称被忽略。之后深入源码分析。

4、将kcontrols、widgets和route串联起来:

[c-sharp] view
plain
copy

  1. static int wm8900_add_widgets(struct snd_soc_codec *codec)  
  2. {  
  3.     snd_soc_dapm_new_controls(codec, wm8900_dapm_widgets,  
  4.                   ARRAY_SIZE(wm8900_dapm_widgets));  
  5.     snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));  
  6.     snd_soc_dapm_new_widgets(codec);  
  7.     return 0;  
  8. }  

 

四、dapm kcontrol

好了,如果仅仅是为了实现audio paths的话,了解以上应该是足够的了。但人生的追求不应该那么简单,我们要从更根源处剖析问题,以后再审视相似的问题时,站的高度也不同。

snd_soc_dapm_route的定义:

[c-sharp] view
plain
copy

  1. /* 
  2.  * DAPM audio route definition. 

抱歉!评论已关闭.