android soundrecorder之四 dapm介绍

转载请标注原文地址:http://blog.csdn.net/uranus_wm/article/details/12855325

 

前三篇文章对录音的大体流程介绍了下

这篇文章讲一下codec内部的dapm配置

dapm的全称:dynamic audio power managment

还是先看张图:

android soundrecorder之四 dapm介绍_第1张图片

这幅图是codec内部ctrl连接关系的一张示意图,当然实际的codec内部连接更加灵活,这里只是大致列出了其中一些走向关系

所谓dapm其实就是管理配置这些内部控制器,如mixer,muxer,gpa,micbias等,以实现音频通路和音量的切换以及电源管理

在codec probe的时候会向snd_soc注册一些dapm control

其中某些control以:{目标,控制,源}的形式出现

这类control形成了一条简单路径关系,“源”通过“控制”到达“目标”

这个“控制”通常类型是“MIXER”或者“MUXER”

他们通常是多条路径route的控制点

“MIXER”指多输入一输出,多输入可以同时有效

“MUXER”指多输入一输出,只能选择一路输入有效

由此简单路径我们构成一条从mic输入到speaker输出的完整路径

也可以是从mic输入到aif1输出的完整路径,这就是我们录音的dapm route

同时每一个“控制”都会对应其相应的寄存器配置,如下面的SOC_DAPM_SINGLE申明

static int wm8994_codec_probe(struct snd_soc_codec *codec)
{
struct wm8994 *control;
struct wm8994_priv *wm8994;
struct snd_soc_dapm_context *dapm = &codec->dapm;
wm_hubs_add_analogue_controls(codec);
snd_soc_add_controls(codec, wm8994_snd_controls,
    ARRAY_SIZE(wm8994_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
 ARRAY_SIZE(wm8994_dapm_widgets));
}

struct snd_soc_dapm_route {
const char *sink;
const char *control;
const char *source;
/* Note: currently only supported for links where source is a supply */
int (*connected)(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink);
};
static const struct snd_soc_dapm_route wm8994_lateclk_revd_intercon[] = {
{ "DAC1L", NULL, "Late DAC1L Enable PGA" },
{ "Late DAC1L Enable PGA", NULL, "DAC1L Mixer" },
{ "DAC1R", NULL, "Late DAC1R Enable PGA" },
{ "Late DAC1R Enable PGA", NULL, "DAC1R Mixer" },
{ "DAC2L", NULL, "Late DAC2L Enable PGA" },
{ "Late DAC2L Enable PGA", NULL, "AIF2DAC2L Mixer" },
{ "DAC2R", NULL, "Late DAC2R Enable PGA" },
{ "Late DAC2R Enable PGA", NULL, "AIF2DAC2R Mixer" },
{ "AIF2ADCL", NULL, "Late DAC2L Enable PGA" }, //wangmeng,20130625
{ "AIF2ADCR", NULL, "Late DAC2R Enable PGA"} //wangmeng,20130625
static const struct snd_soc_dapm_route intercon[] = {

{ "CLK_SYS", NULL, "AIF1CLK", check_clk_sys },
{ "CLK_SYS", NULL, "AIF2CLK", check_clk_sys },
/* DAC2/AIF2 outputs  */
{ "AIF2ADCL", NULL, "AIF2DAC2L Mixer" },
{ "AIF2DAC2L Mixer", "AIF2 Switch", "AIF2DACL" },
{ "AIF2DAC2L Mixer", "AIF1.2 Switch", "AIF1DAC2L" },
{ "AIF2DAC2L Mixer", "AIF1.1 Switch", "AIF1DAC1L" },
{ "AIF2DAC2L Mixer", "Left Sidetone Switch", "Left Sidetone" },
{ "AIF2DAC2L Mixer", "Right Sidetone Switch", "Right Sidetone" },
{ "AIF2ADCR", NULL, "AIF2DAC2R Mixer" },
{ "AIF2DAC2R Mixer", "AIF2 Switch", "AIF2DACR" },
{ "AIF2DAC2R Mixer", "AIF1.2 Switch", "AIF1DAC2R" },
{ "AIF2DAC2R Mixer", "AIF1.1 Switch", "AIF1DAC1R" },
{ "AIF2DAC2R Mixer", "Left Sidetone Switch", "Left Sidetone" },
{ "AIF2DAC2R Mixer", "Right Sidetone Switch", "Right Sidetone" },
}

SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0,
  aif2dac2r_mix, ARRAY_SIZE(aif2dac2r_mix)),


static const struct snd_kcontrol_new aif2dac2r_mix[] = {

SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
5, 1, 0),
SOC_DAPM_SINGLE("Left Sidetone Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
4, 1, 0),
SOC_DAPM_SINGLE("AIF2 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
2, 1, 0),
SOC_DAPM_SINGLE("AIF1.2 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
1, 1, 0),
SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
0, 1, 0),
};

上面的代码片段我们可以发现找到这样一条route:

{ "AIF2DAC2R Mixer", "AIF1.1 Switch", "AIF1DAC1R" },
{ "Late DAC2R Enable PGA", NULL, "AIF2DAC2R Mixer" },

“AIF1DAC1R”通过“AIF1.1 Switch”到达“AIF2DAC2R Mixer”再通过“NULL”到达“Late DAC2R Enable PGA”

这里“NULL”表示无条件到达,说明其内部是直接相连的

 

下面这段是录音时从main mic输入(IN1LN-IN1LP差分输入)到aif1输出的配置表

实际操作时,通常将“源”省略

const AudioMixer device_input_Main_Mic[] = {
#if defined (USES_I2S_AUDIO) || defined (USES_PCM_AUDIO)
//Main_MIC(IN1L N_VMID) to MIXIN to ADC to DAC2 Mixer to AIF2(ADCDAT2)
//Main_MIC(IN1L N_VMID) to MIXINL
    {"IN1L PGA IN1LN Switch", 1}, //OFF,IN1LN
    {"IN1L PGA IN1LP Switch", 1}, //VMID,IN1LP
    {"IN1L Switch", 1}, //[0..1]:[MUTE..UNMUTE] ,0018h:b7
    {"IN1L Volume", 12}, //[1..31]:[-16.5db..+30db],0018h
    {"MIXINL IN1L Switch", 1},
    {"MIXINL IN1L Volume",1}, //[0..1]:[0db..+30db]],0029h
/*ADCL to AIF1ADC*/
    {"ADCL Mux", 0}, //ADC,DMIC
    {"AIF1ADCL Source", 0}, //Left,Right
    {"AIF1ADCR Source", 0}, //Left,Right
    {"AIF1ADC1 Volume", 119}, //[0,1..119]:[MUTE,-71.625db..+17.625db],0400h_0401h default:C0 eq 0db
    {"AIF1ADC1L DRC Switch",1},
    {"AIF1ADC1R DRC Switch",1},
    {"AIF1ADC1L Mixer ADC/DMIC Switch",1},
    {"AIF1ADC1R Mixer ADC/DMIC Switch",1},
#elif defined(USES_SPDIF_AUDIO)
#endif
    {NULL, NULL}
};



 

你可能感兴趣的:(alsa,Codec,linux内核,dapm)