Android 2.3 下面的音频调试技巧心得与大家分享

来源:互联网 发布:帝国时代地图编辑软件 编辑:程序博客网 时间:2024/05/22 10:40

记得开始调试3G的时候,要打通wm8976和RT5621的通道,以供3G的通话来用,记得我在这个项目里面有两种方案:

第一种方案就是上层通过写proc来实现。有关这个思路的实现我已经在另一篇博客里面有详细的描述(proc的使用),感兴趣的朋友,可以去看看,在Android 栏目里面

第二种方案就是看了samsung的代码,了解了他有一种机制可以通过上层来调用kernel的函数,来设置该音频芯片的寄存器,呵呵,samsung对有的音频芯片的支持并不是都是采用这样的机制,samsung开始对芯片初始化函数里面就已经把所用到的通道全部打开。嘿嘿,偷懒啊! 关键是我们有3G的功能就是要在打电话的时候打开芯片的一些通道,而不是在初始启动的时候,就得有一种机制,上层可以随时调用kernel里面的函数,修改音频芯片的寄存器。

  下面就让我来详细的描述这种方法,希望对调试音频驱动的朋友有帮助:

  首先来看看音频的上层代码: 

  下面函数的路劲是:Devive/Samsung/proprietary/libaudio/AudioHardware.cpp  里面

#define GSM_PATCH   

#if 1//wang 
#define LOGX LOGE
#else
#define LOGX LOGV
#endif

 status_t AudioHardware::AudioStreamOutALSA::open_l()    //在打开音频的时候回调用这个函数
{
    LOGX("wang ::AudioStreamOutALSA:: open_l ");
    mPcm = mHardware->openPcmOut_l();
    if (mPcm == NULL) {
        return NO_INIT;
    }
    mMixer = mHardware->openMixer_l();
    if (mMixer) {
        LOGX("open playback normal");
        TRACE_DRIVER_IN(DRV_MIXER_GET)
        mRouteCtl= mixer_get_control(mMixer, "Playback Path", 0);
        mRouteCtlGSM = mixer_get_control(mMixer, "SMT Mode", 0); //wang
        TRACE_DRIVER_OUT
    }
#ifdef GSM_PATCH   
    if (mRouteCtlGSM) {
        LOGX("### write() SMT Mode mHardware->mode()= %d", mHardware->mode());
        if (mHardware->mode() != AudioSystem::MODE_IN_CALL)
{
   LOGX("######   Music_Mode  ######");
                  TRACE_DRIVER_IN(DRV_MIXER_SEL)
                  mixer_ctl_select(mRouteCtlGSM, "Music_Mode");
                 TRACE_DRIVER_OUT
        } 
else
{
      LOGX("######   GSM_Mode  ######");
              TRACE_DRIVER_IN(DRV_MIXER_SEL)
               mixer_ctl_select(mRouteCtlGSM, "GSM_Mode");   //调用这个函数就会调用下面kernel的一个函数 下面我会描述
               TRACE_DRIVER_OUT
        }        
    }
#endif     

  

2:在kernel层      Smdkv2xx_wm8976.c 里面添加

static const char *smt_scenarios[] = {
"Off",
"GSM_Mode",
"Music_Mode",
};

static const struct soc_enum smdk_scenario_enum[] = {
        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(smt_scenarios), smt_scenarios),
};
static const struct snd_kcontrol_new wm8976_s5pv210_controls[] = {
SOC_ENUM_EXT("SMT Mode", smdk_scenario_enum[0], smdkv210_get_scenario,smdkv210_set_scenario),//上层会调用该红色函数
};

static int smdkv210_scenario = 0;
static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
{
        switch (smdkv210_scenario) 

         {

case SMT_AUDIO_OFF:
pr_debug("wang ::SMT_AUDIO_OFF : %s\n", __func__);
snd_soc_write(codec, WM8976_MIXL, 0);
snd_soc_write(codec, WM8976_MIXR, 0);
break;

case SMT_GSM_PATH:
pr_debug("wang ::SMT_GSM_PATH : %s\n", __func__);
snd_soc_write(codec, WM8976_MIXL, ((7<<6)|(1<<5)|(1<<0)));
snd_soc_write(codec, WM8976_MIXR, ((7<<6)|(1<<5)|(1<<0)));
break;
default:
case SMT_MUSIC_PATH:
pr_debug("wang ::SMT_MUSIC_PATH : %s\n", __func__);
snd_soc_write(codec, WM8976_MIXL, (1<<0));
snd_soc_write(codec, WM8976_MIXR, (1<<0));
break;

        }
        return 0;
}
static int smdkv210_get_scenario(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
{
        pr_debug("wang :: %s\n", __func__);
        ucontrol->value.integer.value[0] = smdkv210_scenario;
        return 0;
}
static int smdkv210_set_scenario(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
{
        pr_debug("wang :: %s\n", __func__);
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        if (smdkv210_scenario == ucontrol->value.integer.value[0]) {
return 0;
        }
        smdkv210_scenario = ucontrol->value.integer.value[0];
        set_scenario_endpoints(codec, smdkv210_scenario);
        return 1;
}

嘿嘿,知道上层如何能够调用到下面我感觉对于我们做驱动的人来讲,就比较好做了哦,下面就不说了好,有事吗问题希望能给大家给我留言,我会随时回答大家的问题。。。

同时如果有不对的地方希望大家,指正,大家一起探讨,有疑问记得评论博客就可以了,我会关注,没有特别事情不要加我qq,目前人比较多,上班用QQ不方便哦,见谅。。。。。


原创粉丝点击